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

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, 12 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"
(...skipping 21 matching lines...) Expand all
32 Mod5Mask, // Scroll lock 32 Mod5Mask, // Scroll lock
33 Mod2Mask | LockMask, 33 Mod2Mask | LockMask,
34 Mod2Mask | Mod5Mask, 34 Mod2Mask | Mod5Mask,
35 LockMask | Mod5Mask, 35 LockMask | Mod5Mask,
36 Mod2Mask | LockMask | Mod5Mask 36 Mod2Mask | LockMask | Mod5Mask
37 }; 37 };
38 38
39 X11WholeScreenMoveLoop::X11WholeScreenMoveLoop(X11MoveLoopDelegate* delegate) 39 X11WholeScreenMoveLoop::X11WholeScreenMoveLoop(X11MoveLoopDelegate* delegate)
40 : delegate_(delegate), 40 : delegate_(delegate),
41 in_move_loop_(false), 41 in_move_loop_(false),
42 initial_cursor_(ui::kCursorNull),
43 should_reset_mouse_flags_(false), 42 should_reset_mouse_flags_(false),
44 grab_input_window_(None), 43 grab_input_window_(None),
45 grabbed_pointer_(false), 44 grabbed_pointer_(false),
46 canceled_(false), 45 canceled_(false),
47 weak_factory_(this) { 46 weak_factory_(this) {
48 } 47 }
49 48
50 X11WholeScreenMoveLoop::~X11WholeScreenMoveLoop() {} 49 X11WholeScreenMoveLoop::~X11WholeScreenMoveLoop() {}
51 50
52 void X11WholeScreenMoveLoop::DispatchMouseMovement() { 51 void X11WholeScreenMoveLoop::DispatchMouseMovement() {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 EndMoveLoop(); 114 EndMoveLoop();
116 return ui::POST_DISPATCH_NONE; 115 return ui::POST_DISPATCH_NONE;
117 } 116 }
118 break; 117 break;
119 default: 118 default:
120 break; 119 break;
121 } 120 }
122 return ui::POST_DISPATCH_PERFORM_DEFAULT; 121 return ui::POST_DISPATCH_PERFORM_DEFAULT;
123 } 122 }
124 123
125 bool X11WholeScreenMoveLoop::RunMoveLoop(aura::Window* source, 124 bool X11WholeScreenMoveLoop::RunMoveLoop(aura::Window* source) {
126 gfx::NativeCursor cursor) {
127 DCHECK(!in_move_loop_); // Can only handle one nested loop at a time. 125 DCHECK(!in_move_loop_); // Can only handle one nested loop at a time.
128 126
129 // Query the mouse cursor prior to the move loop starting so that it can be
130 // restored when the move loop finishes.
131 initial_cursor_ = source->GetHost()->last_cursor();
132
133 grab_input_window_ = CreateDragInputWindow(gfx::GetXDisplay()); 127 grab_input_window_ = CreateDragInputWindow(gfx::GetXDisplay());
134 128
135 // Only grab mouse capture of |grab_input_window_| if |source| does not have 129 // Only grab mouse capture of |grab_input_window_| if |source| does not have
136 // capture. 130 // capture.
137 // - The caller may intend to transfer capture to a different aura::Window 131 // - The caller may intend to transfer capture to a different aura::Window
138 // when the move loop ends and not release capture. 132 // when the move loop ends and not release capture.
139 // - Releasing capture and X window destruction are both asynchronous. We drop 133 // - Releasing capture and X window destruction are both asynchronous. We drop
140 // events targeted at |grab_input_window_| in the time between the move 134 // events targeted at |grab_input_window_| in the time between the move
141 // loop ends and |grab_input_window_| loses capture. 135 // loop ends and |grab_input_window_| loses capture.
142 grabbed_pointer_ = false; 136 grabbed_pointer_ = false;
143 if (!source->HasCapture()) { 137 if (!source->HasCapture()) {
144 aura::client::CaptureClient* capture_client = 138 aura::client::CaptureClient* capture_client =
145 aura::client::GetCaptureClient(source->GetRootWindow()); 139 aura::client::GetCaptureClient(source->GetRootWindow());
146 CHECK(capture_client->GetGlobalCaptureWindow() == NULL); 140 CHECK(capture_client->GetGlobalCaptureWindow() == NULL);
147 grabbed_pointer_ = GrabPointer(cursor); 141 grabbed_pointer_ = GrabPointer();
148 if (!grabbed_pointer_) { 142 if (!grabbed_pointer_) {
149 XDestroyWindow(gfx::GetXDisplay(), grab_input_window_); 143 XDestroyWindow(gfx::GetXDisplay(), grab_input_window_);
150 return false; 144 return false;
151 } 145 }
152 } 146 }
153 147
154 GrabEscKey(); 148 GrabEscKey();
155 149
156 scoped_ptr<ui::ScopedEventDispatcher> old_dispatcher = 150 scoped_ptr<ui::ScopedEventDispatcher> old_dispatcher =
157 nested_dispatcher_.Pass(); 151 nested_dispatcher_.Pass();
(...skipping 15 matching lines...) Expand all
173 base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop); 167 base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop);
174 base::RunLoop run_loop; 168 base::RunLoop run_loop;
175 quit_closure_ = run_loop.QuitClosure(); 169 quit_closure_ = run_loop.QuitClosure();
176 run_loop.Run(); 170 run_loop.Run();
177 nested_dispatcher_ = old_dispatcher.Pass(); 171 nested_dispatcher_ = old_dispatcher.Pass();
178 return !canceled_; 172 return !canceled_;
179 } 173 }
180 174
181 void X11WholeScreenMoveLoop::UpdateCursor(gfx::NativeCursor cursor) { 175 void X11WholeScreenMoveLoop::UpdateCursor(gfx::NativeCursor cursor) {
182 if (in_move_loop_) { 176 if (in_move_loop_) {
183 // We cannot call GrabPointer() because we do not want to change the 177 if (grabbed_pointer_) {
184 // "owner_events" property of the active pointer grab. 178 // Do not grab the server. We already have pointer grab.
185 XChangeActivePointerGrab( 179 ui::GrabPointer(grab_input_window_, false, cursor.platform());
186 gfx::GetXDisplay(), 180 } else {
187 ButtonPressMask | ButtonReleaseMask | PointerMotionMask, 181 NOTREACHED();
188 cursor.platform(), 182 }
189 CurrentTime);
190 } 183 }
191 } 184 }
192 185
193 void X11WholeScreenMoveLoop::EndMoveLoop() { 186 void X11WholeScreenMoveLoop::EndMoveLoop() {
194 if (!in_move_loop_) 187 if (!in_move_loop_)
195 return; 188 return;
196 189
197 // Prevent DispatchMouseMovement from dispatching any posted motion event. 190 // Prevent DispatchMouseMovement from dispatching any posted motion event.
198 weak_factory_.InvalidateWeakPtrs(); 191 weak_factory_.InvalidateWeakPtrs();
199 last_motion_in_screen_.reset(); 192 last_motion_in_screen_.reset();
200 193
201 // We undo our emulated mouse click from RunMoveLoop(); 194 // We undo our emulated mouse click from RunMoveLoop();
202 if (should_reset_mouse_flags_) { 195 if (should_reset_mouse_flags_) {
203 aura::Env::GetInstance()->set_mouse_button_flags(0); 196 aura::Env::GetInstance()->set_mouse_button_flags(0);
204 should_reset_mouse_flags_ = false; 197 should_reset_mouse_flags_ = false;
205 } 198 }
206 199
207 // TODO(erg): Is this ungrab the cause of having to click to give input focus 200 // TODO(erg): Is this ungrab the cause of having to click to give input focus
208 // on drawn out windows? Not ungrabbing here screws the X server until I kill 201 // on drawn out windows? Not ungrabbing here screws the X server until I kill
209 // the chrome process. 202 // the chrome process.
210 203
211 // Ungrab before we let go of the window. 204 // Ungrab before we let go of the window.
205 if (grabbed_pointer_)
206 ui::UngrabPointer();
207
212 XDisplay* display = gfx::GetXDisplay(); 208 XDisplay* display = gfx::GetXDisplay();
213 if (grabbed_pointer_)
214 XUngrabPointer(display, CurrentTime);
215 else
216 UpdateCursor(initial_cursor_);
217
218 unsigned int esc_keycode = XKeysymToKeycode(display, XK_Escape); 209 unsigned int esc_keycode = XKeysymToKeycode(display, XK_Escape);
219 for (size_t i = 0; i < arraysize(kModifiersMasks); ++i) { 210 for (size_t i = 0; i < arraysize(kModifiersMasks); ++i) {
220 XUngrabKey(display, esc_keycode, kModifiersMasks[i], grab_input_window_); 211 XUngrabKey(display, esc_keycode, kModifiersMasks[i], grab_input_window_);
221 } 212 }
222 213
223 // Restore the previous dispatcher. 214 // Restore the previous dispatcher.
224 nested_dispatcher_.reset(); 215 nested_dispatcher_.reset();
225 delegate_->OnMoveLoopEnded(); 216 delegate_->OnMoveLoopEnded();
226 XDestroyWindow(display, grab_input_window_); 217 XDestroyWindow(display, grab_input_window_);
227 grab_input_window_ = None; 218 grab_input_window_ = None;
228 219
229 in_move_loop_ = false; 220 in_move_loop_ = false;
230 quit_closure_.Run(); 221 quit_closure_.Run();
231 } 222 }
232 223
233 bool X11WholeScreenMoveLoop::GrabPointer(gfx::NativeCursor cursor) { 224 bool X11WholeScreenMoveLoop::GrabPointer() {
234 XDisplay* display = gfx::GetXDisplay(); 225 XDisplay* display = gfx::GetXDisplay();
235 XGrabServer(display); 226 XGrabServer(display);
236 227
237 // Pass "owner_events" as false so that X sends all mouse events to 228 // Pass "owner_events" as false so that X sends all mouse events to
238 // |grab_input_window_|. 229 // |grab_input_window_|.
239 int ret = XGrabPointer( 230 int ret = ui::GrabPointer(grab_input_window_, false, None);
pkotwicz 2014/12/22 23:44:16 Passing None for the Cursor argument seems like th
sadrul 2014/12/23 16:53:50 This is different from what we do now though, righ
pkotwicz 2014/12/23 18:22:22 I do not understand. If X11WholeScreenMoveLoop::Ru
sadrul 2015/01/14 20:34:01 Why not continue to do the same (i.e. why should w
pkotwicz 2015/01/14 20:50:07 The problem is that if RunMoveLoop() takes a curso
240 display,
241 grab_input_window_,
242 False, // owner_events
243 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
244 GrabModeAsync,
245 GrabModeAsync,
246 None,
247 cursor.platform(),
248 CurrentTime);
249 if (ret != GrabSuccess) { 231 if (ret != GrabSuccess) {
250 DLOG(ERROR) << "Grabbing pointer for dragging failed: " 232 DLOG(ERROR) << "Grabbing pointer for dragging failed: "
251 << ui::GetX11ErrorString(display, ret); 233 << ui::GetX11ErrorString(display, ret);
252 } 234 }
253 XUngrabServer(display); 235 XUngrabServer(display);
254 XFlush(display); 236 XFlush(display);
255 return ret == GrabSuccess; 237 return ret == GrabSuccess;
256 } 238 }
257 239
258 void X11WholeScreenMoveLoop::GrabEscKey() { 240 void X11WholeScreenMoveLoop::GrabEscKey() {
(...skipping 16 matching lines...) Expand all
275 DefaultRootWindow(display), 257 DefaultRootWindow(display),
276 -100, -100, 10, 10, 258 -100, -100, 10, 10,
277 0, CopyFromParent, InputOnly, CopyFromParent, 259 0, CopyFromParent, InputOnly, CopyFromParent,
278 attribute_mask, &swa); 260 attribute_mask, &swa);
279 XMapRaised(display, window); 261 XMapRaised(display, window);
280 ui::X11EventSource::GetInstance()->BlockUntilWindowMapped(window); 262 ui::X11EventSource::GetInstance()->BlockUntilWindowMapped(window);
281 return window; 263 return window;
282 } 264 }
283 265
284 } // namespace views 266 } // namespace views
OLDNEW
« ui/base/x/x11_util.cc ('K') | « ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698