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_PERFORM_DEFAULT; | |
Tom (Use chromium acct)
2016/10/12 20:38:08
I wasn't sure whether to use POST_DISPATCH_PERFORM
Elliot Glaysher
2016/10/12 20:48:06
I assume POST_DISPATCH_NONE since you're handling
Tom (Use chromium acct)
2016/10/12 22:35:18
Done.
| |
71 return ui::POST_DISPATCH_NONE; | |
72 } | |
73 return ui::POST_DISPATCH_PERFORM_DEFAULT; | |
74 } | |
75 | |
76 aura::client::WindowMoveResult X11DesktopWindowMoveClientManaged::RunMoveLoop( | |
77 aura::Window* window, | |
78 const gfx::Vector2d& drag_offset, | |
79 aura::client::WindowMoveSource move_source) { | |
80 auto screen_location = window->GetBoundsInScreen().origin() + drag_offset; | |
81 window_ = window->GetHost()->GetAcceleratedWidget(); | |
82 | |
83 SelectButtonReleaseEvents(true); | |
84 | |
85 window->ReleaseCapture(); | |
Tom (Use chromium acct)
2016/10/12 20:38:08
If I don't ReleaseCapture() here, when the drag en
Elliot Glaysher
2016/10/12 20:48:06
I vaguely remember doing the same thing for the sa
Tom (Use chromium acct)
2016/10/12 22:35:18
Acknowledged.
| |
86 UngrabPointer(); | |
87 MoveResizeWindowManaged(window_, screen_location, ui::NetWmMoveResize::MOVE); | |
88 | |
89 std::unique_ptr<ui::ScopedEventDispatcher> old_dispatcher = | |
90 std::move(nested_dispatcher_); | |
91 nested_dispatcher_ = | |
92 ui::PlatformEventSource::GetInstance()->OverrideDispatcher(this); | |
93 | |
94 base::WeakPtr<X11DesktopWindowMoveClientManaged> alive( | |
95 weak_factory_.GetWeakPtr()); | |
96 | |
97 in_move_loop_ = true; | |
Tom (Use chromium acct)
2016/10/12 20:38:08
There's duplicate code between here and x11_whole_
Elliot Glaysher
2016/10/12 20:48:06
Eyeballing it, it's less than 20 lines and is only
Tom (Use chromium acct)
2016/10/12 22:35:18
Acknowledged.
| |
98 base::MessageLoopForUI* loop = base::MessageLoopForUI::current(); | |
99 base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop); | |
100 base::RunLoop run_loop; | |
101 quit_closure_ = run_loop.QuitClosure(); | |
102 run_loop.Run(); | |
103 | |
104 if (!alive) | |
105 return aura::client::MOVE_CANCELED; | |
106 | |
107 nested_dispatcher_ = std::move(old_dispatcher); | |
108 return aura::client::MOVE_SUCCESSFUL; | |
109 } | |
110 | |
111 void X11DesktopWindowMoveClientManaged::EndMoveLoop() { | |
112 if (!in_move_loop_) | |
113 return; | |
114 | |
115 MoveResizeWindowManaged(window_, gfx::Point(), ui::NetWmMoveResize::CANCEL); | |
116 SelectButtonReleaseEvents(false); | |
117 | |
118 quit_closure_.Run(); | |
119 } | |
120 | |
121 } // namespace views | |
OLD | NEW |