| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "ui/views/widget/desktop_aura/x11_desktop_window_move_client_managed.h" | |
| 6 | |
| 7 #include <X11/extensions/XInput2.h> | |
| 8 #include <X11/Xlib.h> | |
| 9 | |
| 10 #include "base/run_loop.h" | |
| 11 #include "ui/aura/window.h" | |
| 12 #include "ui/aura/window_tree_host.h" | |
| 13 #include "ui/base/x/x11_util.h" | |
| 14 #include "ui/events/event_utils.h" | |
| 15 #include "ui/events/platform/platform_event_source.h" | |
| 16 #include "ui/events/platform/scoped_event_dispatcher.h" | |
| 17 #include "ui/views/widget/desktop_aura/x11_pointer_grab.h" | |
| 18 | |
| 19 namespace views { | |
| 20 | |
| 21 namespace { | |
| 22 | |
| 23 bool IsButtonReleaseEvent(XEvent* xev) { | |
| 24 if (xev->type == ButtonRelease) | |
| 25 return xev->xbutton.button == Button1; | |
| 26 if (xev->type == GenericEvent) { | |
| 27 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); | |
| 28 if (xievent->evtype == XI_RawButtonRelease) | |
| 29 return ui::EventButtonFromNative(xev) == Button1; | |
| 30 } | |
| 31 return false; | |
| 32 } | |
| 33 | |
| 34 void SelectButtonReleaseEvents(bool select) { | |
| 35 unsigned char mask[XIMaskLen(XI_LASTEVENT)]; | |
| 36 memset(mask, 0, sizeof(mask)); | |
| 37 if (select) | |
| 38 XISetMask(mask, XI_RawButtonRelease); | |
| 39 XIEventMask evmask; | |
| 40 evmask.deviceid = XIAllMasterDevices; | |
| 41 evmask.mask_len = sizeof(mask); | |
| 42 evmask.mask = mask; | |
| 43 XDisplay* display = gfx::GetXDisplay(); | |
| 44 XISelectEvents(display, DefaultRootWindow(display), &evmask, 1); | |
| 45 } | |
| 46 | |
| 47 } // anonymous namespace | |
| 48 | |
| 49 X11DesktopWindowMoveClientManaged::X11DesktopWindowMoveClientManaged() | |
| 50 : weak_factory_(this) {} | |
| 51 X11DesktopWindowMoveClientManaged::~X11DesktopWindowMoveClientManaged() {} | |
| 52 | |
| 53 bool X11DesktopWindowMoveClientManaged::CanDispatchEvent( | |
| 54 const ui::PlatformEvent& event) { | |
| 55 return in_move_loop_; | |
| 56 } | |
| 57 | |
| 58 uint32_t X11DesktopWindowMoveClientManaged::DispatchEvent( | |
| 59 const ui::PlatformEvent& event) { | |
| 60 DCHECK(base::MessageLoopForUI::IsCurrent()); | |
| 61 | |
| 62 XEvent* xev = event; | |
| 63 | |
| 64 // This method processes all events while the move loop is active. | |
| 65 if (!in_move_loop_) | |
| 66 return ui::POST_DISPATCH_PERFORM_DEFAULT; | |
| 67 | |
| 68 if (IsButtonReleaseEvent(xev)) { | |
| 69 EndMoveLoop(); | |
| 70 return ui::POST_DISPATCH_NONE; | |
| 71 } | |
| 72 return ui::POST_DISPATCH_PERFORM_DEFAULT; | |
| 73 } | |
| 74 | |
| 75 aura::client::WindowMoveResult X11DesktopWindowMoveClientManaged::RunMoveLoop( | |
| 76 aura::Window* window, | |
| 77 const gfx::Vector2d& drag_offset, | |
| 78 aura::client::WindowMoveSource move_source) { | |
| 79 auto screen_location = window->GetBoundsInScreen().origin() + drag_offset; | |
| 80 window_ = window->GetHost()->GetAcceleratedWidget(); | |
| 81 | |
| 82 SelectButtonReleaseEvents(true); | |
| 83 | |
| 84 window->ReleaseCapture(); | |
| 85 UngrabPointer(); | |
| 86 MoveResizeManagedWindow(window_, screen_location, ui::NetWmMoveResize::MOVE); | |
| 87 | |
| 88 std::unique_ptr<ui::ScopedEventDispatcher> old_dispatcher = | |
| 89 std::move(nested_dispatcher_); | |
| 90 nested_dispatcher_ = | |
| 91 ui::PlatformEventSource::GetInstance()->OverrideDispatcher(this); | |
| 92 | |
| 93 base::WeakPtr<X11DesktopWindowMoveClientManaged> alive( | |
| 94 weak_factory_.GetWeakPtr()); | |
| 95 | |
| 96 in_move_loop_ = true; | |
| 97 base::MessageLoopForUI* loop = base::MessageLoopForUI::current(); | |
| 98 base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop); | |
| 99 base::RunLoop run_loop; | |
| 100 quit_closure_ = run_loop.QuitClosure(); | |
| 101 run_loop.Run(); | |
| 102 | |
| 103 if (!alive) | |
| 104 return aura::client::MOVE_CANCELED; | |
| 105 | |
| 106 nested_dispatcher_ = std::move(old_dispatcher); | |
| 107 return aura::client::MOVE_SUCCESSFUL; | |
| 108 } | |
| 109 | |
| 110 void X11DesktopWindowMoveClientManaged::EndMoveLoop() { | |
| 111 if (!in_move_loop_) | |
| 112 return; | |
| 113 | |
| 114 MoveResizeManagedWindow(window_, gfx::Point(), ui::NetWmMoveResize::CANCEL); | |
| 115 SelectButtonReleaseEvents(false); | |
| 116 | |
| 117 quit_closure_.Run(); | |
| 118 } | |
| 119 | |
| 120 } // namespace views | |
| OLD | NEW |