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