Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(250)

Side by Side Diff: ui/ozone/platform/x11/x11_event_factory.cc

Issue 1602173005: Add PlatformWindow/Event related code for Ozone X11. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixes for comments from spang. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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/ozone/platform/x11/x11_event_factory.h"
6
7 #include <X11/Xlib.h>
8
9 #include "base/logging.h"
10 #include "base/macros.h"
11 #include "ui/events/devices/x11/device_data_manager_x11.h"
12 #include "ui/events/event.h"
13 #include "ui/events/event_utils.h"
14 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
15 #include "ui/events/platform/platform_event_dispatcher.h"
16 #include "ui/events/x/events_x_utils.h"
17 #include "ui/events/x/input_x.h"
18 #include "ui/gfx/x/x11_types.h"
19 #include "ui/ozone/platform/x11/x11_surface_factory.h"
20 #include "ui/ozone/platform/x11/x11_window_ozone.h"
21 #include "ui/ozone/public/ozone_platform.h"
22 #include "ui/ozone/public/surface_factory_ozone.h"
23
24 namespace ui {
25
26 namespace {
27
28 using TimeDelta = base::TimeDelta;
29
30 // Translates XI2 XEvent into a ui::Event.
31 ui::Event* TranslateXI2EventToEvent(const XEvent& xev) {
32 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev.xcookie.data);
33 EventType event_type = EventTypeFromXEvent(xev);
34 gfx::Point location = gfx::Point(xievent->event_x, xievent->event_y);
35 gfx::Point root_location = gfx::Point(xievent->root_x, xievent->root_y);
36 int flags = EventFlagsFromXEvent(xev);
37 switch (event_type) {
38 case ET_KEY_PRESSED:
39 case ET_KEY_RELEASED:
40 return new KeyEvent(event_type, KeyboardCodeFromXKeyEvent(&xev), flags);
41 case ET_MOUSE_PRESSED:
42 case ET_MOUSE_MOVED:
43 case ET_MOUSE_DRAGGED:
44 case ET_MOUSE_RELEASED:
45 return new MouseEvent(event_type, location, root_location, TimeDelta(),
46 flags, GetChangedMouseButtonFlagsFromXEvent(xev));
47 case ET_MOUSEWHEEL:
48 return new MouseWheelEvent(GetMouseWheelOffsetFromXEvent(xev), location,
49 root_location, TimeDelta(), flags,
50 GetChangedMouseButtonFlagsFromXEvent(xev));
51 case ET_SCROLL_FLING_START:
52 case ET_SCROLL_FLING_CANCEL: {
53 float x_offset, y_offset, x_offset_ordinal, y_offset_ordinal;
54 GetFlingDataFromXEvent(xev, &x_offset, &y_offset, &x_offset_ordinal,
55 &y_offset_ordinal, nullptr);
56 return new ScrollEvent(event_type, location, EventTimeFromXEvent(xev),
57 flags, x_offset, y_offset, x_offset_ordinal,
58 y_offset_ordinal, 0);
59 }
60 case ET_SCROLL: {
61 float x_offset, y_offset, x_offset_ordinal, y_offset_ordinal;
62 int finger_count;
63 GetScrollOffsetsFromXEvent(xev, &x_offset, &y_offset, &x_offset_ordinal,
64 &y_offset_ordinal, &finger_count);
65 return new ScrollEvent(event_type, location, EventTimeFromXEvent(xev),
66 flags, x_offset, y_offset, x_offset_ordinal,
67 y_offset_ordinal, finger_count);
68 }
69 case ET_TOUCH_MOVED:
70 case ET_TOUCH_PRESSED:
71 case ET_TOUCH_CANCELLED:
72 case ET_TOUCH_RELEASED:
73 return new TouchEvent(event_type, location, GetTouchIdFromXEvent(xev),
74 EventTimeFromXEvent(xev));
75 case ET_UNKNOWN:
76 return nullptr;
77 default:
78 break;
79 }
80 return nullptr;
81 }
82
83 // Translates a XEvent into a ui::Event.
84 ui::Event* TranslateXEventToEvent(const XEvent& xev) {
85 int flags = EventFlagsFromXEvent(xev);
86 switch (xev.type) {
87 case LeaveNotify:
88 case EnterNotify:
89 // EnterNotify creates ET_MOUSE_MOVED. Mark as synthesized as this is
90 // not real mouse move event.
91 // int flags = GetEventFlagsFromXState(xev.xcrossing.state);
92 if (xev.type == EnterNotify)
93 flags |= EF_IS_SYNTHESIZED;
94 return new MouseEvent(
95 ET_MOUSE_MOVED, gfx::Point(xev.xcrossing.x, xev.xcrossing.y),
96 gfx::Point(xev.xcrossing.x_root, xev.xcrossing.y_root), TimeDelta(),
97 flags, 0);
98
99 case KeyPress:
100 case KeyRelease:
101 return new KeyEvent(EventTypeFromXEvent(xev),
102 KeyboardCodeFromXKeyEvent(&xev), flags);
103
104 case ButtonPress:
105 case ButtonRelease: {
106 gfx::Point location = gfx::Point(xev.xbutton.x, xev.xbutton.y);
107 gfx::Point root_location =
108 gfx::Point(xev.xbutton.x_root, xev.xbutton.y_root);
109 switch (EventTypeFromXEvent(xev)) {
110 case ET_MOUSEWHEEL:
111 return new MouseWheelEvent(GetMouseWheelOffsetFromXEvent(xev),
112 location, root_location, TimeDelta(),
113 flags, 0);
114 case ET_MOUSE_PRESSED:
115 case ET_MOUSE_RELEASED:
116 return new MouseEvent(EventTypeFromXEvent(xev), location,
117 root_location, TimeDelta(), flags,
118 GetChangedMouseButtonFlagsFromXEvent(xev));
119 case ET_UNKNOWN:
120 // No event is created for X11-release events for mouse-wheel
121 // buttons.
122 break;
123 default:
124 NOTREACHED();
125 }
126 break;
127 }
128
129 case GenericEvent:
130 return TranslateXI2EventToEvent(xev);
131 }
132 return nullptr;
133 }
134
135 } // namespace
136
137 X11EventFactory::X11EventFactory(
138 XDisplay* display,
139 scoped_refptr<X11WindowManagerOzone> window_manager)
140 : display_(display), window_manager_(window_manager) {
141 DCHECK(display_);
142 DeviceDataManagerX11::CreateInstance();
143 InitializeXInput2(display_);
144 InitializeXkb(display_);
145 AddEventWatcher();
spang 2016/01/20 22:32:53 Does it need to be called here since it's called i
kylechar 2016/01/21 14:14:52 I'm not sure. It seems like it shouldn't need to b
sadrul 2016/01/21 14:53:01 I think in some tests, the message-loop is created
146 }
147
148 X11EventFactory::~X11EventFactory() {}
149
150 // static
151 X11EventFactory* X11EventFactory::GetInstance() {
152 return static_cast<X11EventFactory*>(PlatformEventSource::GetInstance());
153 }
154
155 ////////////////////////////////////////////////////////////////////////////////
156 // X11EventFactory, public
157
158 void X11EventFactory::DispatchXEvents() {
159 DCHECK(display_);
160 // Handle all pending events.
161 // It may be useful to eventually align this event dispatch with vsync, but
162 // not yet.
163 continue_stream_ = true;
164 while (XPending(display_) && continue_stream_) {
165 XEvent xevent;
166 XNextEvent(display_, &xevent);
167 ExtractCookieDataDispatchEvent(&xevent);
168 }
169 }
170
171 void X11EventFactory::BlockUntilWindowMapped(XID window) {
172 XEvent event;
173 do {
174 // Block until there's a message of |event_mask| type on |w|. Then remove
175 // it from the queue and stuff it in |event|.
176 XWindowEvent(display_, window, StructureNotifyMask, &event);
177 ExtractCookieDataDispatchEvent(&event);
178 } while (event.type != MapNotify);
179 }
180
181 ////////////////////////////////////////////////////////////////////////////////
182 // X11EventFactory, private
183
184 void X11EventFactory::AddEventWatcher() {
185 if (initialized_)
186 return;
187 if (!base::MessageLoop::current())
188 return;
189
190 int fd = ConnectionNumber(display_);
191 base::MessageLoopForUI::current()->WatchFileDescriptor(
192 fd, true, base::MessagePumpLibevent::WATCH_READ, &watcher_controller_,
193 this);
194 initialized_ = true;
195 }
196
197 uint32_t X11EventFactory::ExtractCookieDataDispatchEvent(XEvent* xevent) {
198 bool have_cookie = false;
199 if (xevent->type == GenericEvent &&
200 XGetEventData(xevent->xgeneric.display, &xevent->xcookie)) {
201 have_cookie = true;
202 }
203 uint32_t action = DispatchEvent(xevent);
204 if (have_cookie)
205 XFreeEventData(xevent->xgeneric.display, &xevent->xcookie);
206 return action;
207 }
208
209 uint32_t X11EventFactory::DispatchEvent(base::NativeEvent event) {
210 XEvent* xevent = static_cast<XEvent*>(event);
211 uint32_t action = POST_DISPATCH_STOP_PROPAGATION;
212 base::NativeEvent translated_event = TranslateXEventToEvent(*xevent);
213 if (translated_event) {
214 action = PlatformEventSource::DispatchEvent(translated_event);
215 } else {
216 DispatchXEventToXWindow(*xevent);
spang 2016/01/20 22:32:53 Someday I hope we will be able to take this branch
217 }
218 if (xevent->type == GenericEvent &&
219 xevent->xgeneric.evtype == XI_HierarchyChanged) {
220 // TODO(kylechar): UpdateDeviceList() isn't calling X11 functions.
221 ui::UpdateDeviceList();
222 }
223
224 if (xevent->type == EnterNotify &&
225 xevent->xcrossing.detail != NotifyInferior &&
226 xevent->xcrossing.mode != NotifyUngrab) {
227 // Clear stored scroll data
228 DeviceDataManagerX11::GetInstance()->InvalidateScrollClasses();
229 }
230 return action;
231 }
232
233 void X11EventFactory::StopCurrentEventStream() {
234 continue_stream_ = false;
235 }
236
237 void X11EventFactory::OnDispatcherListChanged() {
238 AddEventWatcher();
239 }
240
241 void X11EventFactory::OnFileCanReadWithoutBlocking(int fd) {
242 DispatchXEvents();
243 }
244
245 void X11EventFactory::OnFileCanWriteWithoutBlocking(int fd) {
246 NOTREACHED();
247 }
248
249 void X11EventFactory::DispatchXEventToXWindow(const XEvent& xev) {
250 switch (xev.type) {
251 case FocusOut:
252 case Expose:
253 case ConfigureNotify:
254 case ClientMessage: {
255 // This is a windowing message that needs to be passed to the platform
256 // window directly.
257 X11WindowOzone* window = window_manager_->FindWindow(xev.xany.window);
258 if (window)
259 window->ProcessXEvent(xev);
260 }
261 }
262 }
263
264 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698