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 |