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

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

Issue 749063003: Fix grabbing capture when the mouse is pressed on Desktop Linux. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years 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 last_xmotion_.type = LASTEvent; 47 last_xmotion_.type = LASTEvent;
49 } 48 }
50 49
51 X11WholeScreenMoveLoop::~X11WholeScreenMoveLoop() {} 50 X11WholeScreenMoveLoop::~X11WholeScreenMoveLoop() {}
52 51
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 } 136 }
138 default: 137 default:
139 break; 138 break;
140 } 139 }
141 } 140 }
142 } 141 }
143 142
144 return ui::POST_DISPATCH_PERFORM_DEFAULT; 143 return ui::POST_DISPATCH_PERFORM_DEFAULT;
145 } 144 }
146 145
147 bool X11WholeScreenMoveLoop::RunMoveLoop(aura::Window* source, 146 bool X11WholeScreenMoveLoop::RunMoveLoop(aura::Window* source) {
148 gfx::NativeCursor cursor) {
149 DCHECK(!in_move_loop_); // Can only handle one nested loop at a time. 147 DCHECK(!in_move_loop_); // Can only handle one nested loop at a time.
150 148
151 // Query the mouse cursor prior to the move loop starting so that it can be
152 // restored when the move loop finishes.
153 initial_cursor_ = source->GetHost()->last_cursor();
154
155 grab_input_window_ = CreateDragInputWindow(gfx::GetXDisplay()); 149 grab_input_window_ = CreateDragInputWindow(gfx::GetXDisplay());
156 150
157 // Only grab mouse capture of |grab_input_window_| if |source| does not have 151 // Only grab mouse capture of |grab_input_window_| if |source| does not have
158 // capture. 152 // capture.
159 // - The caller may intend to transfer capture to a different aura::Window 153 // - The caller may intend to transfer capture to a different aura::Window
160 // when the move loop ends and not release capture. 154 // when the move loop ends and not release capture.
161 // - Releasing capture and X window destruction are both asynchronous. We drop 155 // - Releasing capture and X window destruction are both asynchronous. We drop
162 // events targeted at |grab_input_window_| in the time between the move 156 // events targeted at |grab_input_window_| in the time between the move
163 // loop ends and |grab_input_window_| loses capture. 157 // loop ends and |grab_input_window_| loses capture.
164 grabbed_pointer_ = false; 158 grabbed_pointer_ = false;
165 if (!source->HasCapture()) { 159 if (!source->HasCapture()) {
166 aura::client::CaptureClient* capture_client = 160 aura::client::CaptureClient* capture_client =
167 aura::client::GetCaptureClient(source->GetRootWindow()); 161 aura::client::GetCaptureClient(source->GetRootWindow());
168 CHECK(capture_client->GetGlobalCaptureWindow() == NULL); 162 CHECK(capture_client->GetGlobalCaptureWindow() == NULL);
169 grabbed_pointer_ = GrabPointer(cursor); 163 grabbed_pointer_ = GrabPointer();
170 if (!grabbed_pointer_) { 164 if (!grabbed_pointer_) {
171 XDestroyWindow(gfx::GetXDisplay(), grab_input_window_); 165 XDestroyWindow(gfx::GetXDisplay(), grab_input_window_);
172 return false; 166 return false;
173 } 167 }
174 } 168 }
175 169
176 GrabEscKey(); 170 GrabEscKey();
177 171
178 scoped_ptr<ui::ScopedEventDispatcher> old_dispatcher = 172 scoped_ptr<ui::ScopedEventDispatcher> old_dispatcher =
179 nested_dispatcher_.Pass(); 173 nested_dispatcher_.Pass();
(...skipping 15 matching lines...) Expand all
195 base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop); 189 base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop);
196 base::RunLoop run_loop; 190 base::RunLoop run_loop;
197 quit_closure_ = run_loop.QuitClosure(); 191 quit_closure_ = run_loop.QuitClosure();
198 run_loop.Run(); 192 run_loop.Run();
199 nested_dispatcher_ = old_dispatcher.Pass(); 193 nested_dispatcher_ = old_dispatcher.Pass();
200 return !canceled_; 194 return !canceled_;
201 } 195 }
202 196
203 void X11WholeScreenMoveLoop::UpdateCursor(gfx::NativeCursor cursor) { 197 void X11WholeScreenMoveLoop::UpdateCursor(gfx::NativeCursor cursor) {
204 if (in_move_loop_) { 198 if (in_move_loop_) {
205 // We cannot call GrabPointer() because we do not want to change the 199 if (grabbed_pointer_) {
206 // "owner_events" property of the active pointer grab. 200 // Do not grab the server. We already have pointer grab.
207 XChangeActivePointerGrab( 201 ui::GrabPointer(grab_input_window_, false, cursor.platform());
208 gfx::GetXDisplay(), 202 } else {
209 ButtonPressMask | ButtonReleaseMask | PointerMotionMask, 203 NOTREACHED();
210 cursor.platform(), 204 }
211 CurrentTime);
212 } 205 }
213 } 206 }
214 207
215 void X11WholeScreenMoveLoop::EndMoveLoop() { 208 void X11WholeScreenMoveLoop::EndMoveLoop() {
216 if (!in_move_loop_) 209 if (!in_move_loop_)
217 return; 210 return;
218 211
219 // Prevent DispatchMouseMovement from dispatching any posted motion event. 212 // Prevent DispatchMouseMovement from dispatching any posted motion event.
220 weak_factory_.InvalidateWeakPtrs(); 213 weak_factory_.InvalidateWeakPtrs();
221 last_xmotion_.type = LASTEvent; 214 last_xmotion_.type = LASTEvent;
222 215
223 // We undo our emulated mouse click from RunMoveLoop(); 216 // We undo our emulated mouse click from RunMoveLoop();
224 if (should_reset_mouse_flags_) { 217 if (should_reset_mouse_flags_) {
225 aura::Env::GetInstance()->set_mouse_button_flags(0); 218 aura::Env::GetInstance()->set_mouse_button_flags(0);
226 should_reset_mouse_flags_ = false; 219 should_reset_mouse_flags_ = false;
227 } 220 }
228 221
229 // TODO(erg): Is this ungrab the cause of having to click to give input focus 222 // TODO(erg): Is this ungrab the cause of having to click to give input focus
230 // on drawn out windows? Not ungrabbing here screws the X server until I kill 223 // on drawn out windows? Not ungrabbing here screws the X server until I kill
231 // the chrome process. 224 // the chrome process.
232 225
233 // Ungrab before we let go of the window. 226 // Ungrab before we let go of the window.
227 if (grabbed_pointer_)
228 ui::UngrabPointer();
229
234 XDisplay* display = gfx::GetXDisplay(); 230 XDisplay* display = gfx::GetXDisplay();
235 if (grabbed_pointer_)
236 XUngrabPointer(display, CurrentTime);
237 else
238 UpdateCursor(initial_cursor_);
239
240 unsigned int esc_keycode = XKeysymToKeycode(display, XK_Escape); 231 unsigned int esc_keycode = XKeysymToKeycode(display, XK_Escape);
241 for (size_t i = 0; i < arraysize(kModifiersMasks); ++i) { 232 for (size_t i = 0; i < arraysize(kModifiersMasks); ++i) {
242 XUngrabKey(display, esc_keycode, kModifiersMasks[i], grab_input_window_); 233 XUngrabKey(display, esc_keycode, kModifiersMasks[i], grab_input_window_);
243 } 234 }
244 235
245 // Restore the previous dispatcher. 236 // Restore the previous dispatcher.
246 nested_dispatcher_.reset(); 237 nested_dispatcher_.reset();
247 delegate_->OnMoveLoopEnded(); 238 delegate_->OnMoveLoopEnded();
248 XDestroyWindow(display, grab_input_window_); 239 XDestroyWindow(display, grab_input_window_);
249 grab_input_window_ = None; 240 grab_input_window_ = None;
250 241
251 in_move_loop_ = false; 242 in_move_loop_ = false;
252 quit_closure_.Run(); 243 quit_closure_.Run();
253 } 244 }
254 245
255 bool X11WholeScreenMoveLoop::GrabPointer(gfx::NativeCursor cursor) { 246 bool X11WholeScreenMoveLoop::GrabPointer() {
256 XDisplay* display = gfx::GetXDisplay(); 247 XDisplay* display = gfx::GetXDisplay();
257 XGrabServer(display); 248 XGrabServer(display);
258 249
259 // Pass "owner_events" as false so that X sends all mouse events to 250 // Pass "owner_events" as false so that X sends all mouse events to
260 // |grab_input_window_|. 251 // |grab_input_window_|.
261 int ret = XGrabPointer( 252 int ret = ui::GrabPointer(grab_input_window_, false, None);
sadrul 2014/12/22 21:08:59 Should you send cursor.platform() for cursor?
262 display,
263 grab_input_window_,
264 False, // owner_events
265 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
266 GrabModeAsync,
267 GrabModeAsync,
268 None,
269 cursor.platform(),
270 CurrentTime);
271 if (ret != GrabSuccess) { 253 if (ret != GrabSuccess) {
272 DLOG(ERROR) << "Grabbing pointer for dragging failed: " 254 DLOG(ERROR) << "Grabbing pointer for dragging failed: "
273 << ui::GetX11ErrorString(display, ret); 255 << ui::GetX11ErrorString(display, ret);
274 } 256 }
275 XUngrabServer(display); 257 XUngrabServer(display);
276 XFlush(display); 258 XFlush(display);
277 return ret == GrabSuccess; 259 return ret == GrabSuccess;
278 } 260 }
279 261
280 void X11WholeScreenMoveLoop::GrabEscKey() { 262 void X11WholeScreenMoveLoop::GrabEscKey() {
(...skipping 16 matching lines...) Expand all
297 DefaultRootWindow(display), 279 DefaultRootWindow(display),
298 -100, -100, 10, 10, 280 -100, -100, 10, 10,
299 0, CopyFromParent, InputOnly, CopyFromParent, 281 0, CopyFromParent, InputOnly, CopyFromParent,
300 attribute_mask, &swa); 282 attribute_mask, &swa);
301 XMapRaised(display, window); 283 XMapRaised(display, window);
302 ui::X11EventSource::GetInstance()->BlockUntilWindowMapped(window); 284 ui::X11EventSource::GetInstance()->BlockUntilWindowMapped(window);
303 return window; 285 return window;
304 } 286 }
305 287
306 } // namespace views 288 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698