1 /*
2  *  Copyright (c) 2014 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 
11 #include "modules/desktop_capture/win/screen_capture_utils.h"
12 
13 #include <windows.h>
14 
15 #include <string>
16 #include <vector>
17 
18 #include "modules/desktop_capture/desktop_capturer.h"
19 #include "rtc_base/checks.h"
20 #include "rtc_base/string_utils.h"
21 #include "rtc_base/win32.h"
22 
23 namespace webrtc {
24 
GetScreenList(DesktopCapturer::SourceList * screens,std::vector<std::string> * device_names)25 bool GetScreenList(DesktopCapturer::SourceList* screens,
26                    std::vector<std::string>* device_names /* = nullptr */) {
27   RTC_DCHECK_EQ(screens->size(), 0U);
28   if (device_names) {
29     RTC_DCHECK_EQ(device_names->size(), 0U);
30   }
31 
32   BOOL enum_result = TRUE;
33   for (int device_index = 0;; ++device_index) {
34     DISPLAY_DEVICEW device;
35     device.cb = sizeof(device);
36     enum_result = EnumDisplayDevicesW(NULL, device_index, &device, 0);
37 
38     // |enum_result| is 0 if we have enumerated all devices.
39     if (!enum_result)
40       break;
41 
42     // We only care about active displays.
43     if (!(device.StateFlags & DISPLAY_DEVICE_ACTIVE))
44       continue;
45 
46     screens->push_back({device_index, std::string()});
47     if (device_names) {
48       device_names->push_back(rtc::ToUtf8(device.DeviceName));
49     }
50   }
51   return true;
52 }
53 
IsScreenValid(DesktopCapturer::SourceId screen,std::wstring * device_key)54 bool IsScreenValid(DesktopCapturer::SourceId screen, std::wstring* device_key) {
55   if (screen == kFullDesktopScreenId) {
56     *device_key = L"";
57     return true;
58   }
59 
60   DISPLAY_DEVICEW device;
61   device.cb = sizeof(device);
62   BOOL enum_result = EnumDisplayDevicesW(NULL, screen, &device, 0);
63   if (enum_result)
64     *device_key = device.DeviceKey;
65 
66   return !!enum_result;
67 }
68 
GetFullscreenRect()69 DesktopRect GetFullscreenRect() {
70   return DesktopRect::MakeXYWH(GetSystemMetrics(SM_XVIRTUALSCREEN),
71                                GetSystemMetrics(SM_YVIRTUALSCREEN),
72                                GetSystemMetrics(SM_CXVIRTUALSCREEN),
73                                GetSystemMetrics(SM_CYVIRTUALSCREEN));
74 }
75 
GetScreenRect(DesktopCapturer::SourceId screen,const std::wstring & device_key)76 DesktopRect GetScreenRect(DesktopCapturer::SourceId screen,
77                           const std::wstring& device_key) {
78   if (screen == kFullDesktopScreenId) {
79     return GetFullscreenRect();
80   }
81 
82   DISPLAY_DEVICEW device;
83   device.cb = sizeof(device);
84   BOOL result = EnumDisplayDevicesW(NULL, screen, &device, 0);
85   if (!result)
86     return DesktopRect();
87 
88   // Verifies the device index still maps to the same display device, to make
89   // sure we are capturing the same device when devices are added or removed.
90   // DeviceKey is documented as reserved, but it actually contains the registry
91   // key for the device and is unique for each monitor, while DeviceID is not.
92   if (device_key != device.DeviceKey)
93     return DesktopRect();
94 
95   DEVMODEW device_mode;
96   device_mode.dmSize = sizeof(device_mode);
97   device_mode.dmDriverExtra = 0;
98   result = EnumDisplaySettingsExW(device.DeviceName, ENUM_CURRENT_SETTINGS,
99                                   &device_mode, 0);
100   if (!result)
101     return DesktopRect();
102 
103   return DesktopRect::MakeXYWH(
104       device_mode.dmPosition.x, device_mode.dmPosition.y,
105       device_mode.dmPelsWidth, device_mode.dmPelsHeight);
106 }
107 
108 }  // namespace webrtc
109