Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(363)

Side by Side Diff: webrtc/modules/desktop_capture/cropping_window_capturer_win.cc

Issue 2997493002: desktopCapture: minimized window shouldn't be treated as on-top on Win10 (Closed)
Patch Set: rebase Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/desktop_capture/cropping_window_capturer.h" 11 #include "webrtc/modules/desktop_capture/cropping_window_capturer.h"
12 12
13 #include "webrtc/modules/desktop_capture/win/scoped_gdi_object.h" 13 #include "webrtc/modules/desktop_capture/win/scoped_gdi_object.h"
14 #include "webrtc/modules/desktop_capture/win/screen_capture_utils.h" 14 #include "webrtc/modules/desktop_capture/win/screen_capture_utils.h"
15 #include "webrtc/modules/desktop_capture/win/window_capture_utils.h" 15 #include "webrtc/modules/desktop_capture/win/window_capture_utils.h"
16 #include "webrtc/rtc_base/logging.h" 16 #include "webrtc/rtc_base/logging.h"
17 #include "webrtc/rtc_base/win32.h" 17 #include "webrtc/rtc_base/win32.h"
18 18
19 namespace webrtc { 19 namespace webrtc {
20 20
21 namespace { 21 namespace {
22 22
23 // Used to pass input/output data during the EnumWindow call for verifying if 23 // Used to pass input/output data during the EnumWindow call for verifying if
24 // the selected window is on top. 24 // the selected window is on top.
25 struct TopWindowVerifierContext { 25 struct TopWindowVerifierContext {
26 TopWindowVerifierContext(HWND selected_window, HWND excluded_window) 26 TopWindowVerifierContext(HWND selected_window,
27 HWND excluded_window,
28 DesktopRect selected_window_rect)
27 : selected_window(selected_window), 29 : selected_window(selected_window),
28 excluded_window(excluded_window), 30 excluded_window(excluded_window),
29 is_top_window(false), 31 selected_window_rect(selected_window_rect),
30 selected_window_process_id(0) {} 32 is_top_window(false) {
33 RTC_DCHECK_NE(selected_window, excluded_window);
34 }
31 35
32 HWND selected_window; 36 const HWND selected_window;
33 HWND excluded_window; 37 const HWND excluded_window;
38 const DesktopRect selected_window_rect;
34 bool is_top_window; 39 bool is_top_window;
35 DWORD selected_window_process_id;
36 DesktopRect selected_window_rect;
37 }; 40 };
38 41
39 // The function is called during EnumWindow for every window enumerated and is 42 // The function is called during EnumWindow for every window enumerated and is
40 // responsible for verifying if the selected window is on top. 43 // responsible for verifying if the selected window is on top.
41 BOOL CALLBACK TopWindowVerifier(HWND hwnd, LPARAM param) { 44 BOOL CALLBACK TopWindowVerifier(HWND hwnd, LPARAM param) {
42 TopWindowVerifierContext* context = 45 TopWindowVerifierContext* context =
43 reinterpret_cast<TopWindowVerifierContext*>(param); 46 reinterpret_cast<TopWindowVerifierContext*>(param);
44 47
45 if (hwnd == context->selected_window) { 48 if (hwnd == context->selected_window) {
46 context->is_top_window = true; 49 context->is_top_window = true;
(...skipping 16 matching lines...) Expand all
63 if (GetAncestor(hwnd, GA_ROOTOWNER) == context->selected_window) { 66 if (GetAncestor(hwnd, GA_ROOTOWNER) == context->selected_window) {
64 return TRUE; 67 return TRUE;
65 } 68 }
66 69
67 // If |hwnd| has no title and belongs to the same process, assume it's a 70 // If |hwnd| has no title and belongs to the same process, assume it's a
68 // tooltip or context menu from the selected window and ignore it. 71 // tooltip or context menu from the selected window and ignore it.
69 const size_t kTitleLength = 32; 72 const size_t kTitleLength = 32;
70 WCHAR window_title[kTitleLength]; 73 WCHAR window_title[kTitleLength];
71 GetWindowText(hwnd, window_title, kTitleLength); 74 GetWindowText(hwnd, window_title, kTitleLength);
72 if (wcsnlen_s(window_title, kTitleLength) == 0) { 75 if (wcsnlen_s(window_title, kTitleLength) == 0) {
73 DWORD enumerated_process; 76 DWORD enumerated_window_process_id;
74 GetWindowThreadProcessId(hwnd, &enumerated_process); 77 DWORD selected_window_process_id;
75 if (!context->selected_window_process_id) { 78 GetWindowThreadProcessId(hwnd, &enumerated_window_process_id);
76 GetWindowThreadProcessId(context->selected_window, 79 GetWindowThreadProcessId(context->selected_window,
77 &context->selected_window_process_id); 80 &selected_window_process_id);
78 } 81 if (selected_window_process_id == enumerated_window_process_id) {
79 if (context->selected_window_process_id == enumerated_process) {
80 return TRUE; 82 return TRUE;
81 } 83 }
82 } 84 }
83 85
84 // Check if the enumerated window intersects with the selected window. 86 // Check if the enumerated window intersects with the selected window.
85 RECT enumerated_rect; 87 RECT enumerated_rect;
86 if (!GetWindowRect(hwnd, &enumerated_rect)) { 88 if (!GetWindowRect(hwnd, &enumerated_rect)) {
87 // Bail out if failed to get the window area. 89 // Bail out if failed to get the window area.
88 context->is_top_window = false; 90 context->is_top_window = false;
89 return FALSE; 91 return FALSE;
(...skipping 30 matching lines...) Expand all
120 // rectangular, or the rect from GetWindowRect if the region is not set. 122 // rectangular, or the rect from GetWindowRect if the region is not set.
121 DesktopRect window_region_rect_; 123 DesktopRect window_region_rect_;
122 124
123 AeroChecker aero_checker_; 125 AeroChecker aero_checker_;
124 }; 126 };
125 127
126 bool CroppingWindowCapturerWin::ShouldUseScreenCapturer() { 128 bool CroppingWindowCapturerWin::ShouldUseScreenCapturer() {
127 if (!rtc::IsWindows8OrLater() && aero_checker_.IsAeroEnabled()) 129 if (!rtc::IsWindows8OrLater() && aero_checker_.IsAeroEnabled())
128 return false; 130 return false;
129 131
132 HWND selected = reinterpret_cast<HWND>(selected_window());
133 // Check if the window is hidden or minimized.
134 if (IsIconic(selected) || !IsWindowVisible(selected)) {
135 return false;
136 }
137
130 // Check if the window is a translucent layered window. 138 // Check if the window is a translucent layered window.
131 HWND selected = reinterpret_cast<HWND>(selected_window());
132 LONG window_ex_style = GetWindowLong(selected, GWL_EXSTYLE); 139 LONG window_ex_style = GetWindowLong(selected, GWL_EXSTYLE);
133 if (window_ex_style & WS_EX_LAYERED) { 140 if (window_ex_style & WS_EX_LAYERED) {
134 COLORREF color_ref_key = 0; 141 COLORREF color_ref_key = 0;
135 BYTE alpha = 0; 142 BYTE alpha = 0;
136 DWORD flags = 0; 143 DWORD flags = 0;
137 144
138 // GetLayeredWindowAttributes fails if the window was setup with 145 // GetLayeredWindowAttributes fails if the window was setup with
139 // UpdateLayeredWindow. We have no way to know the opacity of the window in 146 // UpdateLayeredWindow. We have no way to know the opacity of the window in
140 // that case. This happens for Stiky Note (crbug/412726). 147 // that case. This happens for Stiky Note (crbug/412726).
141 if (!GetLayeredWindowAttributes(selected, &color_ref_key, &alpha, &flags)) 148 if (!GetLayeredWindowAttributes(selected, &color_ref_key, &alpha, &flags))
142 return false; 149 return false;
143 150
144 // UpdateLayeredWindow is the only way to set per-pixel alpha and will cause 151 // UpdateLayeredWindow is the only way to set per-pixel alpha and will cause
145 // the previous GetLayeredWindowAttributes to fail. So we only need to check 152 // the previous GetLayeredWindowAttributes to fail. So we only need to check
146 // the window wide color key or alpha. 153 // the window wide color key or alpha.
147 if ((flags & LWA_COLORKEY) || ((flags & LWA_ALPHA) && (alpha < 255))) 154 if ((flags & LWA_COLORKEY) || ((flags & LWA_ALPHA) && (alpha < 255)))
148 return false; 155 return false;
149 } 156 }
150 157
151 TopWindowVerifierContext context(
152 selected, reinterpret_cast<HWND>(excluded_window()));
153
154 RECT selected_window_rect; 158 RECT selected_window_rect;
155 if (!GetWindowRect(selected, &selected_window_rect)) { 159 if (!GetWindowRect(selected, &selected_window_rect)) {
156 return false; 160 return false;
157 } 161 }
158 context.selected_window_rect = DesktopRect::MakeLTRB( 162 window_region_rect_ = DesktopRect::MakeLTRB(
159 selected_window_rect.left, 163 selected_window_rect.left, selected_window_rect.top,
160 selected_window_rect.top, 164 selected_window_rect.right, selected_window_rect.bottom);
161 selected_window_rect.right,
162 selected_window_rect.bottom);
163 165
164 // Get the window region and check if it is rectangular. 166 // Get the window region and check if it is rectangular.
165 win::ScopedGDIObject<HRGN, win::DeleteObjectTraits<HRGN> > 167 win::ScopedGDIObject<HRGN, win::DeleteObjectTraits<HRGN> >
166 scoped_hrgn(CreateRectRgn(0, 0, 0, 0)); 168 scoped_hrgn(CreateRectRgn(0, 0, 0, 0));
167 int region_type = GetWindowRgn(selected, scoped_hrgn.Get()); 169 int region_type = GetWindowRgn(selected, scoped_hrgn.Get());
168 170
169 // Do not use the screen capturer if the region is empty or not rectangular. 171 // Do not use the screen capturer if the region is empty or not rectangular.
170 if (region_type == COMPLEXREGION || region_type == NULLREGION) 172 if (region_type == COMPLEXREGION || region_type == NULLREGION)
171 return false; 173 return false;
172 174
173 if (region_type == SIMPLEREGION) { 175 if (region_type == SIMPLEREGION) {
174 RECT region_rect; 176 RECT region_rect;
175 GetRgnBox(scoped_hrgn.Get(), &region_rect); 177 GetRgnBox(scoped_hrgn.Get(), &region_rect);
176 DesktopRect rgn_rect = 178 DesktopRect rgn_rect =
177 DesktopRect::MakeLTRB(region_rect.left, 179 DesktopRect::MakeLTRB(region_rect.left,
178 region_rect.top, 180 region_rect.top,
179 region_rect.right, 181 region_rect.right,
180 region_rect.bottom); 182 region_rect.bottom);
181 rgn_rect.Translate(context.selected_window_rect.left(), 183 rgn_rect.Translate(window_region_rect_.left(), window_region_rect_.top());
182 context.selected_window_rect.top()); 184 window_region_rect_.IntersectWith(rgn_rect);
183 context.selected_window_rect.IntersectWith(rgn_rect);
184 } 185 }
185 window_region_rect_ = context.selected_window_rect;
186 186
187 // Check if the window is occluded by any other window, excluding the child 187 // Check if the window is occluded by any other window, excluding the child
188 // windows, context menus, and |excluded_window_|. 188 // windows, context menus, and |excluded_window_|.
189 // TODO(zijiehe): EnumWindows enumerates root window only, so the window may 189 // TODO(zijiehe): EnumWindows enumerates root window only, so the window may
190 // be covered by its own child window. See bug 190 // be covered by its own child window. See bug
191 // https://bugs.chromium.org/p/webrtc/issues/detail?id=8062 191 // https://bugs.chromium.org/p/webrtc/issues/detail?id=8062
192 TopWindowVerifierContext context(
193 selected, reinterpret_cast<HWND>(excluded_window()), window_region_rect_);
192 EnumWindows(&TopWindowVerifier, reinterpret_cast<LPARAM>(&context)); 194 EnumWindows(&TopWindowVerifier, reinterpret_cast<LPARAM>(&context));
193 return context.is_top_window; 195 return context.is_top_window;
194 } 196 }
195 197
196 DesktopRect CroppingWindowCapturerWin::GetWindowRectInVirtualScreen() { 198 DesktopRect CroppingWindowCapturerWin::GetWindowRectInVirtualScreen() {
197 DesktopRect original_rect; 199 DesktopRect original_rect;
198 DesktopRect window_rect; 200 DesktopRect window_rect;
199 HWND hwnd = reinterpret_cast<HWND>(selected_window()); 201 HWND hwnd = reinterpret_cast<HWND>(selected_window());
200 if (!GetCroppedWindowRect(hwnd, &window_rect, &original_rect)) { 202 if (!GetCroppedWindowRect(hwnd, &window_rect, &original_rect)) {
201 LOG(LS_WARNING) << "Failed to get window info: " << GetLastError(); 203 LOG(LS_WARNING) << "Failed to get window info: " << GetLastError();
(...skipping 11 matching lines...) Expand all
213 } // namespace 215 } // namespace
214 216
215 // static 217 // static
216 std::unique_ptr<DesktopCapturer> CroppingWindowCapturer::CreateCapturer( 218 std::unique_ptr<DesktopCapturer> CroppingWindowCapturer::CreateCapturer(
217 const DesktopCaptureOptions& options) { 219 const DesktopCaptureOptions& options) {
218 return std::unique_ptr<DesktopCapturer>( 220 return std::unique_ptr<DesktopCapturer>(
219 new CroppingWindowCapturerWin(options)); 221 new CroppingWindowCapturerWin(options));
220 } 222 }
221 223
222 } // namespace webrtc 224 } // namespace webrtc
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698