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

Side by Side Diff: ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc

Issue 821803002: Use XGrabPointer instead of XChangeActivatePointerGrab() to change the cursor during a pointer grab (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@fix_capture
Patch Set: Created 5 years, 11 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h" 5 #include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h"
6 6
7 #include <X11/keysym.h> 7 #include <X11/keysym.h>
8 #include <X11/Xlib.h> 8 #include <X11/Xlib.h>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/message_loop/message_loop.h" 11 #include "base/message_loop/message_loop.h"
12 #include "base/run_loop.h" 12 #include "base/run_loop.h"
13 #include "ui/aura/client/capture_client.h" 13 #include "ui/aura/client/capture_client.h"
14 #include "ui/aura/env.h" 14 #include "ui/aura/env.h"
15 #include "ui/aura/window.h" 15 #include "ui/aura/window.h"
16 #include "ui/aura/window_event_dispatcher.h" 16 #include "ui/aura/window_event_dispatcher.h"
17 #include "ui/aura/window_tree_host.h" 17 #include "ui/aura/window_tree_host.h"
18 #include "ui/base/x/x11_util.h" 18 #include "ui/base/x/x11_util.h"
19 #include "ui/events/event.h" 19 #include "ui/events/event.h"
20 #include "ui/events/event_utils.h" 20 #include "ui/events/event_utils.h"
21 #include "ui/events/keycodes/keyboard_code_conversion_x.h" 21 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
22 #include "ui/events/platform/scoped_event_dispatcher.h" 22 #include "ui/events/platform/scoped_event_dispatcher.h"
23 #include "ui/events/platform/x11/x11_event_source.h" 23 #include "ui/events/platform/x11/x11_event_source.h"
24 #include "ui/views/widget/desktop_aura/x11_pointer_grab.h"
24 25
25 namespace views { 26 namespace views {
26 27
27 // XGrabKey requires the modifier mask to explicitly be specified. 28 // XGrabKey requires the modifier mask to explicitly be specified.
28 const unsigned int kModifiersMasks[] = { 29 const unsigned int kModifiersMasks[] = {
29 0, // No additional modifier. 30 0, // No additional modifier.
30 Mod2Mask, // Num lock 31 Mod2Mask, // Num lock
31 LockMask, // Caps lock 32 LockMask, // Caps lock
32 Mod5Mask, // Scroll lock 33 Mod5Mask, // Scroll lock
33 Mod2Mask | LockMask, 34 Mod2Mask | LockMask,
34 Mod2Mask | Mod5Mask, 35 Mod2Mask | Mod5Mask,
35 LockMask | Mod5Mask, 36 LockMask | Mod5Mask,
36 Mod2Mask | LockMask | Mod5Mask 37 Mod2Mask | LockMask | Mod5Mask
37 }; 38 };
38 39
39 X11WholeScreenMoveLoop::X11WholeScreenMoveLoop(X11MoveLoopDelegate* delegate) 40 X11WholeScreenMoveLoop::X11WholeScreenMoveLoop(X11MoveLoopDelegate* delegate)
40 : delegate_(delegate), 41 : delegate_(delegate),
41 in_move_loop_(false), 42 in_move_loop_(false),
42 initial_cursor_(ui::kCursorNull),
43 should_reset_mouse_flags_(false), 43 should_reset_mouse_flags_(false),
44 grab_input_window_(None), 44 grab_input_window_(None),
45 grabbed_pointer_(false), 45 grabbed_pointer_(false),
46 canceled_(false), 46 canceled_(false),
47 weak_factory_(this) { 47 weak_factory_(this) {
48 } 48 }
49 49
50 X11WholeScreenMoveLoop::~X11WholeScreenMoveLoop() {} 50 X11WholeScreenMoveLoop::~X11WholeScreenMoveLoop() {}
51 51
52 void X11WholeScreenMoveLoop::DispatchMouseMovement() { 52 void X11WholeScreenMoveLoop::DispatchMouseMovement() {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 EndMoveLoop(); 116 EndMoveLoop();
117 return ui::POST_DISPATCH_NONE; 117 return ui::POST_DISPATCH_NONE;
118 } 118 }
119 break; 119 break;
120 default: 120 default:
121 break; 121 break;
122 } 122 }
123 return ui::POST_DISPATCH_PERFORM_DEFAULT; 123 return ui::POST_DISPATCH_PERFORM_DEFAULT;
124 } 124 }
125 125
126 bool X11WholeScreenMoveLoop::RunMoveLoop(aura::Window* source, 126 bool X11WholeScreenMoveLoop::RunMoveLoop(aura::Window* source) {
127 gfx::NativeCursor cursor) {
128 DCHECK(!in_move_loop_); // Can only handle one nested loop at a time. 127 DCHECK(!in_move_loop_); // Can only handle one nested loop at a time.
129 128
130 // Query the mouse cursor prior to the move loop starting so that it can be
131 // restored when the move loop finishes.
132 initial_cursor_ = source->GetHost()->last_cursor();
133
134 grab_input_window_ = CreateDragInputWindow(gfx::GetXDisplay()); 129 grab_input_window_ = CreateDragInputWindow(gfx::GetXDisplay());
135 130
136 // Only grab mouse capture of |grab_input_window_| if |source| does not have 131 // Only grab mouse capture of |grab_input_window_| if |source| does not have
137 // capture. 132 // capture.
138 // - The caller may intend to transfer capture to a different aura::Window 133 // - The caller may intend to transfer capture to a different aura::Window
139 // when the move loop ends and not release capture. 134 // when the move loop ends and not release capture.
140 // - Releasing capture and X window destruction are both asynchronous. We drop 135 // - Releasing capture and X window destruction are both asynchronous. We drop
141 // events targeted at |grab_input_window_| in the time between the move 136 // events targeted at |grab_input_window_| in the time between the move
142 // loop ends and |grab_input_window_| loses capture. 137 // loop ends and |grab_input_window_| loses capture.
143 grabbed_pointer_ = false; 138 grabbed_pointer_ = false;
144 if (!source->HasCapture()) { 139 if (!source->HasCapture()) {
145 aura::client::CaptureClient* capture_client = 140 aura::client::CaptureClient* capture_client =
146 aura::client::GetCaptureClient(source->GetRootWindow()); 141 aura::client::GetCaptureClient(source->GetRootWindow());
147 CHECK(capture_client->GetGlobalCaptureWindow() == NULL); 142 CHECK(capture_client->GetGlobalCaptureWindow() == NULL);
148 grabbed_pointer_ = GrabPointer(cursor); 143 grabbed_pointer_ = GrabPointer();
149 if (!grabbed_pointer_) { 144 if (!grabbed_pointer_) {
150 XDestroyWindow(gfx::GetXDisplay(), grab_input_window_); 145 XDestroyWindow(gfx::GetXDisplay(), grab_input_window_);
151 return false; 146 return false;
152 } 147 }
153 } 148 }
154 149
155 GrabEscKey(); 150 GrabEscKey();
156 151
157 scoped_ptr<ui::ScopedEventDispatcher> old_dispatcher = 152 scoped_ptr<ui::ScopedEventDispatcher> old_dispatcher =
158 nested_dispatcher_.Pass(); 153 nested_dispatcher_.Pass();
(...skipping 21 matching lines...) Expand all
180 175
181 if (!alive) 176 if (!alive)
182 return false; 177 return false;
183 178
184 nested_dispatcher_ = old_dispatcher.Pass(); 179 nested_dispatcher_ = old_dispatcher.Pass();
185 return !canceled_; 180 return !canceled_;
186 } 181 }
187 182
188 void X11WholeScreenMoveLoop::UpdateCursor(gfx::NativeCursor cursor) { 183 void X11WholeScreenMoveLoop::UpdateCursor(gfx::NativeCursor cursor) {
189 if (in_move_loop_) { 184 if (in_move_loop_) {
190 // We cannot call GrabPointer() because we do not want to change the 185 if (grabbed_pointer_) {
191 // "owner_events" property of the active pointer grab. 186 // Do not grab the server. We already have pointer grab.
192 XChangeActivePointerGrab( 187 ::views::GrabPointer(grab_input_window_, false, cursor.platform());
193 gfx::GetXDisplay(), 188 } else {
194 ButtonPressMask | ButtonReleaseMask | PointerMotionMask, 189 NOTREACHED();
sadrul 2015/01/15 23:41:20 Add a comment like so: NOTREACHED() << "You mus
pkotwicz 2015/01/16 15:22:46 This message would be incorrect. We reach here if
sadrul 2015/01/16 15:25:14 The point is, add a correct comment that explains
195 cursor.platform(), 190 }
196 CurrentTime);
197 } 191 }
198 } 192 }
199 193
200 void X11WholeScreenMoveLoop::EndMoveLoop() { 194 void X11WholeScreenMoveLoop::EndMoveLoop() {
201 if (!in_move_loop_) 195 if (!in_move_loop_)
202 return; 196 return;
203 197
204 // Prevent DispatchMouseMovement from dispatching any posted motion event. 198 // Prevent DispatchMouseMovement from dispatching any posted motion event.
205 last_motion_in_screen_.reset(); 199 last_motion_in_screen_.reset();
206 200
207 // We undo our emulated mouse click from RunMoveLoop(); 201 // We undo our emulated mouse click from RunMoveLoop();
208 if (should_reset_mouse_flags_) { 202 if (should_reset_mouse_flags_) {
209 aura::Env::GetInstance()->set_mouse_button_flags(0); 203 aura::Env::GetInstance()->set_mouse_button_flags(0);
210 should_reset_mouse_flags_ = false; 204 should_reset_mouse_flags_ = false;
211 } 205 }
212 206
213 // TODO(erg): Is this ungrab the cause of having to click to give input focus 207 // TODO(erg): Is this ungrab the cause of having to click to give input focus
214 // on drawn out windows? Not ungrabbing here screws the X server until I kill 208 // on drawn out windows? Not ungrabbing here screws the X server until I kill
215 // the chrome process. 209 // the chrome process.
216 210
217 // Ungrab before we let go of the window. 211 // Ungrab before we let go of the window.
212 if (grabbed_pointer_)
213 UngrabPointer();
214
218 XDisplay* display = gfx::GetXDisplay(); 215 XDisplay* display = gfx::GetXDisplay();
219 if (grabbed_pointer_)
220 XUngrabPointer(display, CurrentTime);
221 else
222 UpdateCursor(initial_cursor_);
223
224 unsigned int esc_keycode = XKeysymToKeycode(display, XK_Escape); 216 unsigned int esc_keycode = XKeysymToKeycode(display, XK_Escape);
225 for (size_t i = 0; i < arraysize(kModifiersMasks); ++i) { 217 for (size_t i = 0; i < arraysize(kModifiersMasks); ++i) {
226 XUngrabKey(display, esc_keycode, kModifiersMasks[i], grab_input_window_); 218 XUngrabKey(display, esc_keycode, kModifiersMasks[i], grab_input_window_);
227 } 219 }
228 220
229 // Restore the previous dispatcher. 221 // Restore the previous dispatcher.
230 nested_dispatcher_.reset(); 222 nested_dispatcher_.reset();
231 delegate_->OnMoveLoopEnded(); 223 delegate_->OnMoveLoopEnded();
232 XDestroyWindow(display, grab_input_window_); 224 XDestroyWindow(display, grab_input_window_);
233 grab_input_window_ = None; 225 grab_input_window_ = None;
234 226
235 in_move_loop_ = false; 227 in_move_loop_ = false;
236 quit_closure_.Run(); 228 quit_closure_.Run();
237 } 229 }
238 230
239 bool X11WholeScreenMoveLoop::GrabPointer(gfx::NativeCursor cursor) { 231 bool X11WholeScreenMoveLoop::GrabPointer() {
240 XDisplay* display = gfx::GetXDisplay(); 232 XDisplay* display = gfx::GetXDisplay();
241 XGrabServer(display); 233 XGrabServer(display);
242 234
243 // Pass "owner_events" as false so that X sends all mouse events to 235 // Pass "owner_events" as false so that X sends all mouse events to
244 // |grab_input_window_|. 236 // |grab_input_window_|.
245 int ret = XGrabPointer( 237 int ret = ::views::GrabPointer(grab_input_window_, false, None);
246 display,
247 grab_input_window_,
248 False, // owner_events
249 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
250 GrabModeAsync,
251 GrabModeAsync,
252 None,
253 cursor.platform(),
254 CurrentTime);
255 if (ret != GrabSuccess) { 238 if (ret != GrabSuccess) {
256 DLOG(ERROR) << "Grabbing pointer for dragging failed: " 239 DLOG(ERROR) << "Grabbing pointer for dragging failed: "
257 << ui::GetX11ErrorString(display, ret); 240 << ui::GetX11ErrorString(display, ret);
258 } 241 }
259 XUngrabServer(display); 242 XUngrabServer(display);
260 XFlush(display); 243 XFlush(display);
261 return ret == GrabSuccess; 244 return ret == GrabSuccess;
262 } 245 }
263 246
264 void X11WholeScreenMoveLoop::GrabEscKey() { 247 void X11WholeScreenMoveLoop::GrabEscKey() {
(...skipping 16 matching lines...) Expand all
281 DefaultRootWindow(display), 264 DefaultRootWindow(display),
282 -100, -100, 10, 10, 265 -100, -100, 10, 10,
283 0, CopyFromParent, InputOnly, CopyFromParent, 266 0, CopyFromParent, InputOnly, CopyFromParent,
284 attribute_mask, &swa); 267 attribute_mask, &swa);
285 XMapRaised(display, window); 268 XMapRaised(display, window);
286 ui::X11EventSource::GetInstance()->BlockUntilWindowMapped(window); 269 ui::X11EventSource::GetInstance()->BlockUntilWindowMapped(window);
287 return window; 270 return window;
288 } 271 }
289 272
290 } // namespace views 273 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698