From c30087a9ff585bb38f6287856a0d86725d052d03 Mon Sep 17 00:00:00 2001 From: "varkha@chromium.org" Date: Thu, 20 Feb 2014 12:59:45 +0000 Subject: [PATCH] Avoids releasing pointer grab prematurely BUG=338247 TEST= 1.Launch chrome://settings..ctrl+D,save the Bookmark in Bookmark Bar. 2.Open 3 to 4 new Tabs via ctrl+T,in chrome://settings page Drag the Bookmark from the Bookmark Bar. 3.Hover the Dragged Bookmark over the second New-Tab and Release the Bookmark over the New-Tab. 4.Hover the Dragged Bookmark over the third New-Tab (the tab gets activated) and Release the Bookmark over the New-Tab. 5.Close browser - should not crash. Review URL: https://codereview.chromium.org/140663013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@252201 0039d316-1c4b-4281-b951-d872f2087c98 --- .../desktop_aura/x11_whole_screen_move_loop.cc | 38 ++++++++++++++-------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc b/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc index 2b65c2ae4f5a..9f15291ceef0 100644 --- a/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc +++ b/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc @@ -94,20 +94,30 @@ uint32_t X11WholeScreenMoveLoop::Dispatch(const base::NativeEvent& event) { bool X11WholeScreenMoveLoop::RunMoveLoop(aura::Window* source, gfx::NativeCursor cursor) { // Start a capture on the host, so that it continues to receive events during - // the drag. - ScopedCapturer capturer(source->GetDispatcher()->host()); - - DCHECK(!in_move_loop_); // Can only handle one nested loop at a time. - in_move_loop_ = true; - - XDisplay* display = gfx::GetXDisplay(); - - grab_input_window_ = CreateDragInputWindow(display); - if (!drag_image_.isNull()) - CreateDragImageWindow(); - base::MessagePumpX11::Current()->AddDispatcherForWindow( - this, grab_input_window_); - + // the drag. This may be second time we are capturing the mouse events - the + // first being when a mouse is first pressed. That first capture needs to be + // released before the call to GrabPointerWithCursor below, otherwise it may + // get released while we still need the pointer grab, which is why we restrict + // the scope here. + { + ScopedCapturer capturer(source->GetDispatcher()->host()); + + DCHECK(!in_move_loop_); // Can only handle one nested loop at a time. + in_move_loop_ = true; + + XDisplay* display = gfx::GetXDisplay(); + + grab_input_window_ = CreateDragInputWindow(display); + if (!drag_image_.isNull()) + CreateDragImageWindow(); + base::MessagePumpX11::Current()->AddDispatcherForWindow( + this, grab_input_window_); + // Releasing ScopedCapturer ensures that any other instance of + // X11ScopedCapture will not prematurely release grab that will be acquired + // below. + } + // TODO(varkha): Consider integrating GrabPointerWithCursor with + // ScopedCapturer to avoid possibility of logically keeping multiple grabs. if (!GrabPointerWithCursor(cursor)) return false; -- 2.11.4.GIT