190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file. 490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h" 690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <X11/Xlib.h> 890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/bind.h" 107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/message_loop/message_loop.h" 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/run_loop.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/aura/client/capture_client.h" 1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/aura/env.h" 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/aura/window.h" 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h" 16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/aura/window_tree_host.h" 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/base/x/x11_util.h" 18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event.h" 195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/events/event_utils.h" 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/events/keycodes/keyboard_code_conversion_x.h" 215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/events/platform/scoped_event_dispatcher.h" 22c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/events/platform/x11/x11_event_source.h" 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace views { 2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)X11WholeScreenMoveLoop::X11WholeScreenMoveLoop(X11MoveLoopDelegate* delegate) 2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) : delegate_(delegate), 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) in_move_loop_(false), 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci initial_cursor_(ui::kCursorNull), 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) should_reset_mouse_flags_(false), 31effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch grab_input_window_(None), 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci grabbed_pointer_(false), 33c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch canceled_(false), 34effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch weak_factory_(this) { 35effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch last_xmotion_.type = LASTEvent; 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)X11WholeScreenMoveLoop::~X11WholeScreenMoveLoop() {} 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 40effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid X11WholeScreenMoveLoop::DispatchMouseMovement() { 41effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!weak_factory_.HasWeakPtrs()) 42effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 43effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch weak_factory_.InvalidateWeakPtrs(); 44effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_EQ(MotionNotify, last_xmotion_.type); 45effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch delegate_->OnMouseMovement(&last_xmotion_); 46effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch last_xmotion_.type = LASTEvent; 47effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 48effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 49c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch//////////////////////////////////////////////////////////////////////////////// 50c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// DesktopWindowTreeHostLinux, ui::PlatformEventDispatcher implementation: 51c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 52c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool X11WholeScreenMoveLoop::CanDispatchEvent(const ui::PlatformEvent& event) { 535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return in_move_loop_; 54c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 55c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochuint32_t X11WholeScreenMoveLoop::DispatchEvent(const ui::PlatformEvent& event) { 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // This method processes all events while the move loop is active. 585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!in_move_loop_) 595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return ui::POST_DISPATCH_PERFORM_DEFAULT; 6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci XEvent* xev = event; 6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) switch (xev->type) { 6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case MotionNotify: { 64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch last_xmotion_ = xev->xmotion; 65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!weak_factory_.HasWeakPtrs()) { 66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Post a task to dispatch mouse movement event when control returns to 67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // the message loop. This allows smoother dragging since the events are 68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // dispatched without waiting for the drag widget updates. 69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::MessageLoopForUI::current()->PostTask( 70effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FROM_HERE, 71effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Bind(&X11WholeScreenMoveLoop::DispatchMouseMovement, 72effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch weak_factory_.GetWeakPtr())); 73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return ui::POST_DISPATCH_NONE; 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case ButtonRelease: { 77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (xev->xbutton.button == Button1) { 78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Assume that drags are being done with the left mouse button. Only 79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // break the drag if the left mouse button was released. 80effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DispatchMouseMovement(); 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate_->OnMouseReleased(); 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!grabbed_pointer_) { 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If the source widget had capture prior to the move loop starting, 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // it may be relying on views::Widget getting the mouse release and 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // releasing capture in Widget::OnMouseEvent(). 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return ui::POST_DISPATCH_PERFORM_DEFAULT; 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return ui::POST_DISPATCH_NONE; 9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case KeyPress: { 93c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (ui::KeyboardCodeFromXKeyEvent(xev) == ui::VKEY_ESCAPE) { 94c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch canceled_ = true; 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EndMoveLoop(); 965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return ui::POST_DISPATCH_NONE; 97c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) break; 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case GenericEvent: { 1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ui::EventType type = ui::EventTypeFromNative(xev); 1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu switch (type) { 1035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case ui::ET_MOUSE_MOVED: 1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case ui::ET_MOUSE_DRAGGED: 1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case ui::ET_MOUSE_RELEASED: { 1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu XEvent xevent = {0}; 1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (type == ui::ET_MOUSE_RELEASED) { 1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu xevent.type = ButtonRelease; 1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu xevent.xbutton.button = ui::EventButtonFromNative(xev); 1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } else { 1115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu xevent.type = MotionNotify; 1125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu xevent.xany.display = xev->xgeneric.display; 1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu xevent.xany.window = grab_input_window_; 1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // The fields used below are in the same place for all of events 1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // above. Using xmotion from XEvent's unions to avoid repeating 1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // the code. 1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu xevent.xmotion.root = DefaultRootWindow(xev->xgeneric.display); 1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu xevent.xmotion.time = ui::EventTimeFromNative(xev).InMilliseconds(); 1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu gfx::Point point(ui::EventSystemLocationFromNative(xev)); 1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu xevent.xmotion.x_root = point.x(); 1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu xevent.xmotion.y_root = point.y(); 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return DispatchEvent(&xevent); 1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu default: 1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu break; 1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return ui::POST_DISPATCH_PERFORM_DEFAULT; 13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool X11WholeScreenMoveLoop::RunMoveLoop(aura::Window* source, 1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch gfx::NativeCursor cursor) { 1360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!in_move_loop_); // Can only handle one nested loop at a time. 1370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Query the mouse cursor prior to the move loop starting so that it can be 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // restored when the move loop finishes. 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci initial_cursor_ = source->GetHost()->last_cursor(); 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci grab_input_window_ = CreateDragInputWindow(gfx::GetXDisplay()); 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Only grab mouse capture of |grab_input_window_| if |source| does not have 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // capture. 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // - The caller may intend to transfer capture to a different aura::Window 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // when the move loop ends and not release capture. 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // - Releasing capture and X window destruction are both asynchronous. We drop 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // events targeted at |grab_input_window_| in the time between the move 1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // loop ends and |grab_input_window_| loses capture. 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci grabbed_pointer_ = false; 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!source->HasCapture()) { 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci aura::client::CaptureClient* capture_client = 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci aura::client::GetCaptureClient(source->GetRootWindow()); 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(capture_client->GetGlobalCaptureWindow() == NULL); 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci grabbed_pointer_ = GrabPointer(cursor); 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!grabbed_pointer_) { 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci XDestroyWindow(gfx::GetXDisplay(), grab_input_window_); 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!GrabKeyboard()) { 1640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch XDestroyWindow(gfx::GetXDisplay(), grab_input_window_); 16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return false; 1660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_ptr<ui::ScopedEventDispatcher> old_dispatcher = 1695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu nested_dispatcher_.Pass(); 1705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu nested_dispatcher_ = 1715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ui::PlatformEventSource::GetInstance()->OverrideDispatcher(this); 17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // We are handling a mouse drag outside of the aura::Window system. We must 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // manually make aura think that the mouse button is pressed so that we don't 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // draw extraneous tooltips. 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) aura::Env* env = aura::Env::GetInstance(); 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!env->IsMouseButtonDown()) { 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) env->set_mouse_button_flags(ui::EF_LEFT_MOUSE_BUTTON); 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) should_reset_mouse_flags_ = true; 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch in_move_loop_ = true; 183c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch canceled_ = false; 18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoopForUI* loop = base::MessageLoopForUI::current(); 18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop); 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::RunLoop run_loop; 18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) quit_closure_ = run_loop.QuitClosure(); 18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) run_loop.Run(); 1895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu nested_dispatcher_ = old_dispatcher.Pass(); 190c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return !canceled_; 19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid X11WholeScreenMoveLoop::UpdateCursor(gfx::NativeCursor cursor) { 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (in_move_loop_) { 1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // We cannot call GrabPointer() because we do not want to change the 1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // "owner_events" property of the active pointer grab. 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci XChangeActivePointerGrab( 1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::GetXDisplay(), 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ButtonPressMask | ButtonReleaseMask | PointerMotionMask, 2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cursor.platform(), 2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CurrentTime); 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 2047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void X11WholeScreenMoveLoop::EndMoveLoop() { 20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!in_move_loop_) 20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Prevent DispatchMouseMovement from dispatching any posted motion event. 210effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch weak_factory_.InvalidateWeakPtrs(); 211effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch last_xmotion_.type = LASTEvent; 212effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // We undo our emulated mouse click from RunMoveLoop(); 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (should_reset_mouse_flags_) { 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) aura::Env::GetInstance()->set_mouse_button_flags(0); 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) should_reset_mouse_flags_ = false; 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // TODO(erg): Is this ungrab the cause of having to click to give input focus 22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // on drawn out windows? Not ungrabbing here screws the X server until I kill 22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // the chrome process. 22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Ungrab before we let go of the window. 22468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XDisplay* display = gfx::GetXDisplay(); 2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (grabbed_pointer_) 226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) XUngrabPointer(display, CurrentTime); 2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci else 2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UpdateCursor(initial_cursor_); 2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci XUngrabKeyboard(display, CurrentTime); 23190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Restore the previous dispatcher. 2335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu nested_dispatcher_.reset(); 23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) delegate_->OnMoveLoopEnded(); 23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) XDestroyWindow(display, grab_input_window_); 2365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu grab_input_window_ = None; 23790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) in_move_loop_ = false; 23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) quit_closure_.Run(); 24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 24190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool X11WholeScreenMoveLoop::GrabPointer(gfx::NativeCursor cursor) { 24368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XDisplay* display = gfx::GetXDisplay(); 2447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch XGrabServer(display); 245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Pass "owner_events" as false so that X sends all mouse events to 2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // |grab_input_window_|. 2487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int ret = XGrabPointer( 2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch display, 2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch grab_input_window_, 2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci False, // owner_events 2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ButtonPressMask | ButtonReleaseMask | PointerMotionMask, 2537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch GrabModeAsync, 2547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch GrabModeAsync, 2557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch None, 2567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch cursor.platform(), 2577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CurrentTime); 2587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (ret != GrabSuccess) { 259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DLOG(ERROR) << "Grabbing pointer for dragging failed: " 2607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch << ui::GetX11ErrorString(display, ret); 2617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) XUngrabServer(display); 2635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu XFlush(display); 264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return ret == GrabSuccess; 2657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 2667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool X11WholeScreenMoveLoop::GrabKeyboard() { 2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci XDisplay* display = gfx::GetXDisplay(); 2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int ret = XGrabKeyboard(display, 2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci grab_input_window_, 2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci False, 2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GrabModeAsync, 2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GrabModeAsync, 2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CurrentTime); 2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (ret != GrabSuccess) { 2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DLOG(ERROR) << "Grabbing keyboard for dragging failed: " 2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << ui::GetX11ErrorString(display, ret); 2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return true; 2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)Window X11WholeScreenMoveLoop::CreateDragInputWindow(XDisplay* display) { 284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) unsigned long attribute_mask = CWEventMask | CWOverrideRedirect; 285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) XSetWindowAttributes swa; 286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) memset(&swa, 0, sizeof(swa)); 287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) swa.event_mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | 288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) KeyPressMask | KeyReleaseMask | StructureNotifyMask; 289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) swa.override_redirect = True; 290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Window window = XCreateWindow(display, 291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DefaultRootWindow(display), 292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) -100, -100, 10, 10, 293f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 0, CopyFromParent, InputOnly, CopyFromParent, 294f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) attribute_mask, &swa); 295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) XMapRaised(display, window); 296c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ui::X11EventSource::GetInstance()->BlockUntilWindowMapped(window); 297f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return window; 298f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 299f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace views 301