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