henrike@webrtc.org | f7795df | 2014-05-13 18:00:26 +0000 | [diff] [blame^] | 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 | |
| 18 | namespace rtc { |
| 19 | |
| 20 | namespace { |
| 21 | |
| 22 | // Window class names that we want to filter out. |
| 23 | const char kProgramManagerClass[] = "Progman"; |
| 24 | const char kButtonClass[] = "Button"; |
| 25 | |
| 26 | } // namespace |
| 27 | |
| 28 | BOOL 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 | |
| 70 | BOOL 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 | |
| 92 | Win32WindowPicker::Win32WindowPicker() { |
| 93 | } |
| 94 | |
| 95 | bool Win32WindowPicker::Init() { |
| 96 | return true; |
| 97 | } |
| 98 | // TODO: Consider changing enumeration to clear() descriptions |
| 99 | // before append(). |
| 100 | bool Win32WindowPicker::GetWindowList(WindowDescriptionList* descriptions) { |
| 101 | LPARAM desc = reinterpret_cast<LPARAM>(descriptions); |
| 102 | return EnumWindows(Win32WindowPicker::EnumProc, desc) != FALSE; |
| 103 | } |
| 104 | |
| 105 | bool 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 | |
| 122 | bool 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 | |
| 135 | bool Win32WindowPicker::IsVisible(const WindowId& id) { |
| 136 | return (::IsWindow(id.id()) != FALSE && ::IsWindowVisible(id.id()) != FALSE); |
| 137 | } |
| 138 | |
| 139 | bool Win32WindowPicker::MoveToFront(const WindowId& id) { |
| 140 | return SetForegroundWindow(id.id()) != FALSE; |
| 141 | } |
| 142 | |
| 143 | } // namespace rtc |