• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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 
EnumProc(HWND hwnd,LPARAM l_param)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];
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 
MonitorEnumProc(HMONITOR h_monitor,HDC hdc_monitor,LPRECT lprc_monitor,LPARAM l_param)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 
Win32WindowPicker()93 Win32WindowPicker::Win32WindowPicker() {
94 }
95 
Init()96 bool Win32WindowPicker::Init() {
97   return true;
98 }
99 // TODO: Consider changing enumeration to clear() descriptions
100 // before append().
GetWindowList(WindowDescriptionList * descriptions)101 bool Win32WindowPicker::GetWindowList(WindowDescriptionList* descriptions) {
102   LPARAM desc = reinterpret_cast<LPARAM>(descriptions);
103   return EnumWindows(Win32WindowPicker::EnumProc, desc) != FALSE;
104 }
105 
GetDesktopList(DesktopDescriptionList * descriptions)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 
GetDesktopDimensions(const DesktopId & id,int * width,int * height)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 
IsVisible(const WindowId & id)136 bool Win32WindowPicker::IsVisible(const WindowId& id) {
137   return (::IsWindow(id.id()) != FALSE && ::IsWindowVisible(id.id()) != FALSE);
138 }
139 
MoveToFront(const WindowId & id)140 bool Win32WindowPicker::MoveToFront(const WindowId& id) {
141   return SetForegroundWindow(id.id()) != FALSE;
142 }
143 
144 }  // namespace rtc
145