1/* 2 * Copyright 2010 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10#include "webrtc/base/win32windowpicker.h" 11 12#include <string> 13#include <vector> 14 15#include "webrtc/base/common.h" 16#include "webrtc/base/logging.h" 17 18namespace rtc { 19 20namespace { 21 22// Window class names that we want to filter out. 23const char kProgramManagerClass[] = "Progman"; 24const char kButtonClass[] = "Button"; 25 26} // namespace 27 28BOOL CALLBACK Win32WindowPicker::EnumProc(HWND hwnd, LPARAM l_param) { 29 WindowDescriptionList* descriptions = 30 reinterpret_cast<WindowDescriptionList*>(l_param); 31 32 // Skip windows that are invisible, minimized, have no title, or are owned, 33 // unless they have the app window style set. Except for minimized windows, 34 // this is what Alt-Tab does. 35 // TODO: Figure out how to grab a thumbnail of a minimized window and 36 // include them in the list. 37 int len = GetWindowTextLength(hwnd); 38 HWND owner = GetWindow(hwnd, GW_OWNER); 39 LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE); 40 if (len == 0 || IsIconic(hwnd) || !IsWindowVisible(hwnd) || 41 (owner && !(exstyle & WS_EX_APPWINDOW))) { 42 // TODO: Investigate if windows without title still could be 43 // interesting to share. We could use the name of the process as title: 44 // 45 // GetWindowThreadProcessId() 46 // OpenProcess() 47 // QueryFullProcessImageName() 48 return TRUE; 49 } 50 51 // Skip the Program Manager window and the Start button. 52 TCHAR class_name_w[500]; 53 ::GetClassName(hwnd, class_name_w, 500); 54 std::string class_name = ToUtf8(class_name_w); 55 if (class_name == kProgramManagerClass || class_name == kButtonClass) { 56 // We don't want the Program Manager window nor the Start button. 57 return TRUE; 58 } 59 60 TCHAR window_title[500]; 61 GetWindowText(hwnd, window_title, ARRAY_SIZE(window_title)); 62 std::string title = ToUtf8(window_title); 63 64 WindowId id(hwnd); 65 WindowDescription desc(id, title); 66 descriptions->push_back(desc); 67 return TRUE; 68} 69 70BOOL CALLBACK Win32WindowPicker::MonitorEnumProc(HMONITOR h_monitor, 71 HDC hdc_monitor, 72 LPRECT lprc_monitor, 73 LPARAM l_param) { 74 DesktopDescriptionList* desktop_desc = 75 reinterpret_cast<DesktopDescriptionList*>(l_param); 76 77 DesktopId id(h_monitor, static_cast<int>(desktop_desc->size())); 78 // TODO: Figure out an appropriate desktop title. 79 DesktopDescription desc(id, ""); 80 81 // Determine whether it's the primary monitor. 82 MONITORINFO monitor_info = {0}; 83 monitor_info.cbSize = sizeof(monitor_info); 84 bool primary = (GetMonitorInfo(h_monitor, &monitor_info) && 85 (monitor_info.dwFlags & MONITORINFOF_PRIMARY) != 0); 86 desc.set_primary(primary); 87 88 desktop_desc->push_back(desc); 89 return TRUE; 90} 91 92Win32WindowPicker::Win32WindowPicker() { 93} 94 95bool Win32WindowPicker::Init() { 96 return true; 97} 98// TODO: Consider changing enumeration to clear() descriptions 99// before append(). 100bool Win32WindowPicker::GetWindowList(WindowDescriptionList* descriptions) { 101 LPARAM desc = reinterpret_cast<LPARAM>(descriptions); 102 return EnumWindows(Win32WindowPicker::EnumProc, desc) != FALSE; 103} 104 105bool Win32WindowPicker::GetDesktopList(DesktopDescriptionList* descriptions) { 106 // Create a fresh WindowDescriptionList so that we can use desktop_desc.size() 107 // in MonitorEnumProc to compute the desktop index. 108 DesktopDescriptionList desktop_desc; 109 HDC hdc = GetDC(NULL); 110 bool success = false; 111 if (EnumDisplayMonitors(hdc, NULL, Win32WindowPicker::MonitorEnumProc, 112 reinterpret_cast<LPARAM>(&desktop_desc)) != FALSE) { 113 // Append the desktop descriptions to the end of the returned descriptions. 114 descriptions->insert(descriptions->end(), desktop_desc.begin(), 115 desktop_desc.end()); 116 success = true; 117 } 118 ReleaseDC(NULL, hdc); 119 return success; 120} 121 122bool Win32WindowPicker::GetDesktopDimensions(const DesktopId& id, 123 int* width, 124 int* height) { 125 MONITORINFOEX monitor_info; 126 monitor_info.cbSize = sizeof(MONITORINFOEX); 127 if (!GetMonitorInfo(id.id(), &monitor_info)) { 128 return false; 129 } 130 *width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left; 131 *height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top; 132 return true; 133} 134 135bool Win32WindowPicker::IsVisible(const WindowId& id) { 136 return (::IsWindow(id.id()) != FALSE && ::IsWindowVisible(id.id()) != FALSE); 137} 138 139bool Win32WindowPicker::MoveToFront(const WindowId& id) { 140 return SetForegroundWindow(id.id()) != FALSE; 141} 142 143} // namespace rtc 144