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

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

Issue 1959863002: CURSORINFO.flags should be checked before capturing its bitmap (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: More comments about why we do not CloseHandle on an HCURSOR. Created 4 years, 7 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) 2013 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2013 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/mouse_cursor_monitor.h" 11 #include "webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
12 12
13 #include <assert.h> 13 #include <assert.h>
14 #include <string.h>
14 15
15 #include <memory> 16 #include <memory>
16 17
17 #include "webrtc/modules/desktop_capture/desktop_frame.h" 18 #include "webrtc/modules/desktop_capture/desktop_frame.h"
19 #include "webrtc/modules/desktop_capture/desktop_geometry.h"
18 #include "webrtc/modules/desktop_capture/mouse_cursor.h" 20 #include "webrtc/modules/desktop_capture/mouse_cursor.h"
19 #include "webrtc/modules/desktop_capture/win/cursor.h" 21 #include "webrtc/modules/desktop_capture/win/cursor.h"
20 #include "webrtc/modules/desktop_capture/win/window_capture_utils.h" 22 #include "webrtc/modules/desktop_capture/win/window_capture_utils.h"
21 #include "webrtc/system_wrappers/include/logging.h" 23 #include "webrtc/system_wrappers/include/logging.h"
22 24
23 namespace webrtc { 25 namespace webrtc {
24 26
27 namespace {
28
29 bool IsSameCursorShape(const CURSORINFO& left, const CURSORINFO& right) {
30 // If the cursors are not showing, we do not care the hCursor handle.
31 return left.flags == right.flags &&
32 (left.flags != CURSOR_SHOWING ||
33 left.hCursor == right.hCursor);
34 }
35
36 } // namespace
37
25 class MouseCursorMonitorWin : public MouseCursorMonitor { 38 class MouseCursorMonitorWin : public MouseCursorMonitor {
26 public: 39 public:
27 explicit MouseCursorMonitorWin(HWND window); 40 explicit MouseCursorMonitorWin(HWND window);
28 explicit MouseCursorMonitorWin(ScreenId screen); 41 explicit MouseCursorMonitorWin(ScreenId screen);
29 virtual ~MouseCursorMonitorWin(); 42 virtual ~MouseCursorMonitorWin();
30 43
31 void Init(Callback* callback, Mode mode) override; 44 void Init(Callback* callback, Mode mode) override;
32 void Capture() override; 45 void Capture() override;
33 46
34 private: 47 private:
35 // Get the rect of the currently selected screen, relative to the primary 48 // Get the rect of the currently selected screen, relative to the primary
36 // display's top-left. If the screen is disabled or disconnected, or any error 49 // display's top-left. If the screen is disabled or disconnected, or any error
37 // happens, an empty rect is returned. 50 // happens, an empty rect is returned.
38 DesktopRect GetScreenRect(); 51 DesktopRect GetScreenRect();
39 52
40 HWND window_; 53 HWND window_;
41 ScreenId screen_; 54 ScreenId screen_;
42 55
43 Callback* callback_; 56 Callback* callback_;
44 Mode mode_; 57 Mode mode_;
45 58
46 HDC desktop_dc_; 59 HDC desktop_dc_;
47 60
48 HCURSOR last_cursor_; 61 // The last CURSORINFO (converted to MouseCursor) we have sent to the client.
62 CURSORINFO last_cursor_;
49 }; 63 };
50 64
51 MouseCursorMonitorWin::MouseCursorMonitorWin(HWND window) 65 MouseCursorMonitorWin::MouseCursorMonitorWin(HWND window)
52 : window_(window), 66 : window_(window),
53 screen_(kInvalidScreenId), 67 screen_(kInvalidScreenId),
54 callback_(NULL), 68 callback_(NULL),
55 mode_(SHAPE_AND_POSITION), 69 mode_(SHAPE_AND_POSITION),
56 desktop_dc_(NULL), 70 desktop_dc_(NULL) {
57 last_cursor_(NULL) { 71 memset(&last_cursor_, 0, sizeof(CURSORINFO));
58 } 72 }
59 73
60 MouseCursorMonitorWin::MouseCursorMonitorWin(ScreenId screen) 74 MouseCursorMonitorWin::MouseCursorMonitorWin(ScreenId screen)
61 : window_(NULL), 75 : window_(NULL),
62 screen_(screen), 76 screen_(screen),
63 callback_(NULL), 77 callback_(NULL),
64 mode_(SHAPE_AND_POSITION), 78 mode_(SHAPE_AND_POSITION),
65 desktop_dc_(NULL), 79 desktop_dc_(NULL) {
66 last_cursor_(NULL) {
67 assert(screen >= kFullDesktopScreenId); 80 assert(screen >= kFullDesktopScreenId);
81 memset(&last_cursor_, 0, sizeof(CURSORINFO));
68 } 82 }
69 83
70 MouseCursorMonitorWin::~MouseCursorMonitorWin() { 84 MouseCursorMonitorWin::~MouseCursorMonitorWin() {
71 if (desktop_dc_) 85 if (desktop_dc_)
72 ReleaseDC(NULL, desktop_dc_); 86 ReleaseDC(NULL, desktop_dc_);
73 } 87 }
74 88
75 void MouseCursorMonitorWin::Init(Callback* callback, Mode mode) { 89 void MouseCursorMonitorWin::Init(Callback* callback, Mode mode) {
76 assert(!callback_); 90 assert(!callback_);
77 assert(callback); 91 assert(callback);
78 92
79 callback_ = callback; 93 callback_ = callback;
80 mode_ = mode; 94 mode_ = mode;
81 95
82 desktop_dc_ = GetDC(NULL); 96 desktop_dc_ = GetDC(NULL);
83 } 97 }
84 98
85 void MouseCursorMonitorWin::Capture() { 99 void MouseCursorMonitorWin::Capture() {
86 assert(callback_); 100 assert(callback_);
87 101
88 CURSORINFO cursor_info; 102 CURSORINFO cursor_info;
89 cursor_info.cbSize = sizeof(CURSORINFO); 103 cursor_info.cbSize = sizeof(CURSORINFO);
90 if (!GetCursorInfo(&cursor_info)) { 104 if (!GetCursorInfo(&cursor_info)) {
91 LOG_F(LS_ERROR) << "Unable to get cursor info. Error = " << GetLastError(); 105 LOG_F(LS_ERROR) << "Unable to get cursor info. Error = " << GetLastError();
92 return; 106 return;
93 } 107 }
94 108
95 if (last_cursor_ != cursor_info.hCursor) { 109 if (!IsSameCursorShape(cursor_info, last_cursor_)) {
96 last_cursor_ = cursor_info.hCursor; 110 if (cursor_info.flags == CURSOR_SUPPRESSED) {
97 // Note that |cursor_info.hCursor| does not need to be freed. 111 // The cursor is intentionally hidden now, send an empty bitmap.
98 std::unique_ptr<MouseCursor> cursor( 112 last_cursor_ = cursor_info;
99 CreateMouseCursorFromHCursor(desktop_dc_, cursor_info.hCursor)); 113 callback_->OnMouseCursor(new MouseCursor(
100 if (cursor.get()) 114 new BasicDesktopFrame(DesktopSize()), DesktopVector()));
101 callback_->OnMouseCursor(cursor.release()); 115 } else {
116 // According to MSDN https://goo.gl/u6gyuC, HCURSOR instances returned by
117 // functions other than CreateCursor do not need to be actively destroyed.
118 // And CloseHandle function (https://goo.gl/ja5ycW) does not close a
119 // cursor, so assume a HCURSOR does not need to be closed.
120 if (cursor_info.flags == 0) {
121 // Host machine does not have a hardware mouse attached, we will send a
122 // default one instead.
123 // Note, Windows automatically caches cursor resource, so we do not need
124 // to cache the result of LoadCursor.
125 cursor_info.hCursor = LoadCursor(nullptr, IDC_ARROW);
126 }
127 std::unique_ptr<MouseCursor> cursor(
128 CreateMouseCursorFromHCursor(desktop_dc_, cursor_info.hCursor));
129 if (cursor) {
130 last_cursor_ = cursor_info;
131 callback_->OnMouseCursor(cursor.release());
132 }
133 }
102 } 134 }
103 135
104 if (mode_ != SHAPE_AND_POSITION) 136 if (mode_ != SHAPE_AND_POSITION)
105 return; 137 return;
106 138
107 DesktopVector position(cursor_info.ptScreenPos.x, cursor_info.ptScreenPos.y); 139 DesktopVector position(cursor_info.ptScreenPos.x, cursor_info.ptScreenPos.y);
108 bool inside = cursor_info.flags == CURSOR_SHOWING; 140 bool inside = cursor_info.flags == CURSOR_SHOWING;
109 141
110 if (window_) { 142 if (window_) {
111 DesktopRect original_rect; 143 DesktopRect original_rect;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 return new MouseCursorMonitorWin(reinterpret_cast<HWND>(window)); 198 return new MouseCursorMonitorWin(reinterpret_cast<HWND>(window));
167 } 199 }
168 200
169 MouseCursorMonitor* MouseCursorMonitor::CreateForScreen( 201 MouseCursorMonitor* MouseCursorMonitor::CreateForScreen(
170 const DesktopCaptureOptions& options, 202 const DesktopCaptureOptions& options,
171 ScreenId screen) { 203 ScreenId screen) {
172 return new MouseCursorMonitorWin(screen); 204 return new MouseCursorMonitorWin(screen);
173 } 205 }
174 206
175 } // namespace webrtc 207 } // 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