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