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/arraysize.h" 16#include "webrtc/base/common.h" 17#include "webrtc/base/logging.h" 18 19namespace rtc { 20 21namespace { 22 23// Window class names that we want to filter out. 24const char kProgramManagerClass[] = "Progman"; 25const char kButtonClass[] = "Button"; 26 27} // namespace 28 29BOOL 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]; 62 GetWindowText(hwnd, window_title, arraysize(window_title)); 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 71BOOL 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 93Win32WindowPicker::Win32WindowPicker() { 94} 95 96bool Win32WindowPicker::Init() { 97 return true; 98} 99// TODO: Consider changing enumeration to clear() descriptions 100// before append(). 101bool Win32WindowPicker::GetWindowList(WindowDescriptionList* descriptions) { 102 LPARAM desc = reinterpret_cast<LPARAM>(descriptions); 103 return EnumWindows(Win32WindowPicker::EnumProc, desc) != FALSE; 104} 105 106bool 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 123bool 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 136bool Win32WindowPicker::IsVisible(const WindowId& id) { 137 return (::IsWindow(id.id()) != FALSE && ::IsWindowVisible(id.id()) != FALSE); 138} 139 140bool Win32WindowPicker::MoveToFront(const WindowId& id) { 141 return SetForegroundWindow(id.id()) != FALSE; 142} 143 144} // namespace rtc 145