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 |