henrike@webrtc.org | 0e118e7 | 2013-07-10 00:45:36 +0000 | [diff] [blame] | 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 |