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

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

Issue 2889063002: Linux desktopCapture: fix the cursor position issue in Window sharing (Closed)
Patch Set: Created 3 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 <memory> 11 #include <memory>
12 12
13 #include "webrtc/modules/desktop_capture/mouse_cursor_monitor.h" 13 #include "webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
14 14
15 #include <X11/extensions/Xfixes.h> 15 #include <X11/extensions/Xfixes.h>
16 #include <X11/Xlib.h> 16 #include <X11/Xlib.h>
17 #include <X11/Xutil.h> 17 #include <X11/Xutil.h>
18 18
19 #include "webrtc/base/logging.h" 19 #include "webrtc/base/logging.h"
20 #include "webrtc/modules/desktop_capture/desktop_capture_options.h" 20 #include "webrtc/modules/desktop_capture/desktop_capture_options.h"
21 #include "webrtc/modules/desktop_capture/desktop_frame.h" 21 #include "webrtc/modules/desktop_capture/desktop_frame.h"
22 #include "webrtc/modules/desktop_capture/mouse_cursor.h" 22 #include "webrtc/modules/desktop_capture/mouse_cursor.h"
23 #include "webrtc/modules/desktop_capture/x11/x_error_trap.h" 23 #include "webrtc/modules/desktop_capture/x11/x_error_trap.h"
24 24
25 namespace webrtc {
26
25 namespace { 27 namespace {
26 28
27 // WindowCapturer returns window IDs of X11 windows with WM_STATE attribute. 29 // WindowCapturer returns window IDs of X11 windows with WM_STATE attribute.
28 // These windows may not be immediate children of the root window, because 30 // These windows may not be immediate children of the root window, because
29 // window managers may re-parent them to add decorations. However, 31 // window managers may re-parent them to add decorations. However,
30 // XQueryPointer() expects to be passed children of the root. This function 32 // XQueryPointer() expects to be passed children of the root. This function
31 // searches up the list of the windows to find the root child that corresponds 33 // searches up the list of the windows to find the root child that corresponds
32 // to |window|. 34 // to |window|.
33 Window GetTopLevelWindow(Display* display, Window window) { 35 Window GetTopLevelWindow(Display* display, Window window) {
34 while (true) { 36 while (true) {
(...skipping 12 matching lines...) Expand all
47 49
48 if (parent == root) 50 if (parent == root)
49 break; 51 break;
50 52
51 window = parent; 53 window = parent;
52 } 54 }
53 55
54 return window; 56 return window;
55 } 57 }
56 58
59 DesktopSize GetWindowSize(Display* display, Window window) {
60 XWindowAttributes attributes;
61 {
62 XErrorTrap error_trap(display);
63 if (!XGetWindowAttributes(display, window, &attributes) ||
64 error_trap.GetLastErrorAndDisable() != 0) {
65 return DesktopSize(0, 0);
Sergey Ulanov 2017/05/19 20:36:03 DesktopSize(); Don't need the zeros
braveyao1 2017/05/19 22:38:59 Done.
66 }
67 }
68
69 return DesktopSize(attributes.width, attributes.height);
70 }
71
72 // As the comments to |GetTopLevelWindow()| above states, in window capture,
Sergey Ulanov 2017/05/19 20:36:03 nit: || around name of a function are not necessar
braveyao1 2017/05/19 22:38:59 Done.
73 // the captured frame is in the coordinates of the input |window|, while the
74 // captured cursor position is in the coordinates of its |parent| window.
75 // And these two coordinates are not always same. The |parent| window may have
76 // decorations added, including the caption bar on top of the window and the
77 // shadow and border around them. The offset needs to be compensated later.
78 DesktopVector GetCursorPostionOffset(Display* display,
79 Window parent,
80 Window children) {
Sergey Ulanov 2017/05/19 20:36:03 s/children/child/ 'children' is plural
braveyao1 2017/05/19 22:38:59 Done.
81 DesktopSize parent_size = GetWindowSize(display, parent);
82 DesktopSize children_size = GetWindowSize(display, children);
83
84 if (parent_size.is_empty() || children_size.is_empty()) {
85 return DesktopVector(0, 0);
86 }
87 // The |x_offset| is the thickness of the shadow and border added around.
88 // The |y_offset| doesn't include the shadow and border added at the bottom.
89 int x_offset = (parent_size.width() - children_size.width()) / 2;
Sergey Ulanov 2017/05/19 20:36:03 This assumes that the border has the same width on
braveyao1 2017/05/19 22:38:59 Done.
90 int y_offset = parent_size.height() - children_size.height() - x_offset;
Sergey Ulanov 2017/05/19 20:36:03 This also assumes that border at the bottom is the
braveyao1 2017/05/19 22:38:59 Done.
91
92 return DesktopVector(x_offset, y_offset);
93 }
94
57 } // namespace 95 } // namespace
58 96
59 namespace webrtc {
60
61 class MouseCursorMonitorX11 : public MouseCursorMonitor, 97 class MouseCursorMonitorX11 : public MouseCursorMonitor,
62 public SharedXDisplay::XEventHandler { 98 public SharedXDisplay::XEventHandler {
63 public: 99 public:
64 MouseCursorMonitorX11(const DesktopCaptureOptions& options, Window window); 100 MouseCursorMonitorX11(const DesktopCaptureOptions& options,
101 Window window,
102 DesktopVector offset);
65 ~MouseCursorMonitorX11() override; 103 ~MouseCursorMonitorX11() override;
66 104
67 void Init(Callback* callback, Mode mode) override; 105 void Init(Callback* callback, Mode mode) override;
68 void Capture() override; 106 void Capture() override;
69 107
70 private: 108 private:
71 // SharedXDisplay::XEventHandler interface. 109 // SharedXDisplay::XEventHandler interface.
72 bool HandleXEvent(const XEvent& event) override; 110 bool HandleXEvent(const XEvent& event) override;
73 111
74 Display* display() { return x_display_->display(); } 112 Display* display() { return x_display_->display(); }
75 113
76 // Captures current cursor shape and stores it in |cursor_shape_|. 114 // Captures current cursor shape and stores it in |cursor_shape_|.
77 void CaptureCursor(); 115 void CaptureCursor();
78 116
79 rtc::scoped_refptr<SharedXDisplay> x_display_; 117 rtc::scoped_refptr<SharedXDisplay> x_display_;
80 Callback* callback_; 118 Callback* callback_;
81 Mode mode_; 119 Mode mode_;
82 Window window_; 120 Window window_;
121 DesktopVector offset_;
83 122
84 bool have_xfixes_; 123 bool have_xfixes_;
85 int xfixes_event_base_; 124 int xfixes_event_base_;
86 int xfixes_error_base_; 125 int xfixes_error_base_;
87 126
88 std::unique_ptr<MouseCursor> cursor_shape_; 127 std::unique_ptr<MouseCursor> cursor_shape_;
89 }; 128 };
90 129
91 MouseCursorMonitorX11::MouseCursorMonitorX11( 130 MouseCursorMonitorX11::MouseCursorMonitorX11(
92 const DesktopCaptureOptions& options, 131 const DesktopCaptureOptions& options,
93 Window window) 132 Window window,
133 DesktopVector offset)
94 : x_display_(options.x_display()), 134 : x_display_(options.x_display()),
95 callback_(NULL), 135 callback_(NULL),
96 mode_(SHAPE_AND_POSITION), 136 mode_(SHAPE_AND_POSITION),
97 window_(window), 137 window_(window),
138 offset_(offset),
98 have_xfixes_(false), 139 have_xfixes_(false),
99 xfixes_event_base_(-1), 140 xfixes_event_base_(-1),
100 xfixes_error_base_(-1) { 141 xfixes_error_base_(-1) {
101 // Set a default initial cursor shape in case XFixes is not present. 142 // Set a default initial cursor shape in case XFixes is not present.
102 const int kSize = 5; 143 const int kSize = 5;
103 std::unique_ptr<DesktopFrame> default_cursor( 144 std::unique_ptr<DesktopFrame> default_cursor(
104 new BasicDesktopFrame(DesktopSize(kSize, kSize))); 145 new BasicDesktopFrame(DesktopSize(kSize, kSize)));
105 const uint8_t pixels[kSize * kSize] = { 146 const uint8_t pixels[kSize * kSize] = {
106 0x00, 0x00, 0x00, 0x00, 0x00, 147 0x00, 0x00, 0x00, 0x00, 0x00,
107 0x00, 0xff, 0xff, 0xff, 0x00, 148 0x00, 0xff, 0xff, 0xff, 0x00,
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 if (!result || error_trap.GetLastErrorAndDisable() != 0) { 219 if (!result || error_trap.GetLastErrorAndDisable() != 0) {
179 state = OUTSIDE; 220 state = OUTSIDE;
180 } else { 221 } else {
181 // In screen mode (window_ == root_window) the mouse is always inside. 222 // In screen mode (window_ == root_window) the mouse is always inside.
182 // XQueryPointer() sets |child_window| to None if the cursor is outside 223 // XQueryPointer() sets |child_window| to None if the cursor is outside
183 // |window_|. 224 // |window_|.
184 state = 225 state =
185 (window_ == root_window || child_window != None) ? INSIDE : OUTSIDE; 226 (window_ == root_window || child_window != None) ? INSIDE : OUTSIDE;
186 } 227 }
187 228
188 callback_->OnMouseCursorPosition(state, 229 callback_->OnMouseCursorPosition(
189 webrtc::DesktopVector(win_x, win_y)); 230 state, DesktopVector(win_x, win_y).subtract(offset_));
190 } 231 }
191 } 232 }
192 233
193 bool MouseCursorMonitorX11::HandleXEvent(const XEvent& event) { 234 bool MouseCursorMonitorX11::HandleXEvent(const XEvent& event) {
194 if (have_xfixes_ && event.type == xfixes_event_base_ + XFixesCursorNotify) { 235 if (have_xfixes_ && event.type == xfixes_event_base_ + XFixesCursorNotify) {
195 const XFixesCursorNotifyEvent* cursor_event = 236 const XFixesCursorNotifyEvent* cursor_event =
196 reinterpret_cast<const XFixesCursorNotifyEvent*>(&event); 237 reinterpret_cast<const XFixesCursorNotifyEvent*>(&event);
197 if (cursor_event->subtype == XFixesDisplayCursorNotify) { 238 if (cursor_event->subtype == XFixesDisplayCursorNotify) {
198 CaptureCursor(); 239 CaptureCursor();
199 } 240 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 XFree(img); 272 XFree(img);
232 273
233 cursor_shape_.reset(new MouseCursor(image.release(), hotspot)); 274 cursor_shape_.reset(new MouseCursor(image.release(), hotspot));
234 } 275 }
235 276
236 // static 277 // static
237 MouseCursorMonitor* MouseCursorMonitor::CreateForWindow( 278 MouseCursorMonitor* MouseCursorMonitor::CreateForWindow(
238 const DesktopCaptureOptions& options, WindowId window) { 279 const DesktopCaptureOptions& options, WindowId window) {
239 if (!options.x_display()) 280 if (!options.x_display())
240 return NULL; 281 return NULL;
241 window = GetTopLevelWindow(options.x_display()->display(), window); 282 Window parent = GetTopLevelWindow(options.x_display()->display(), window);
242 if (window == None) 283 if (parent == None)
243 return NULL; 284 return NULL;
244 return new MouseCursorMonitorX11(options, window); 285
286 DesktopVector offset =
287 GetCursorPostionOffset(options.x_display()->display(), parent, window);
288 return new MouseCursorMonitorX11(options, parent, offset);
245 } 289 }
246 290
247 MouseCursorMonitor* MouseCursorMonitor::CreateForScreen( 291 MouseCursorMonitor* MouseCursorMonitor::CreateForScreen(
248 const DesktopCaptureOptions& options, 292 const DesktopCaptureOptions& options,
249 ScreenId screen) { 293 ScreenId screen) {
250 if (!options.x_display()) 294 if (!options.x_display())
251 return NULL; 295 return NULL;
296
252 return new MouseCursorMonitorX11( 297 return new MouseCursorMonitorX11(
253 options, DefaultRootWindow(options.x_display()->display())); 298 options, DefaultRootWindow(options.x_display()->display()),
299 DesktopVector(0, 0));
254 } 300 }
255 301
256 } // namespace webrtc 302 } // 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