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/events/platform/x11/x11_event_source_ozone.h" | |
6 | |
7 #include <X11/Xlib.h> | |
8 #include <X11/extensions/XInput2.h> | |
9 | |
10 #include "base/message_loop/message_loop.h" | |
11 #include "ui/events/event.h" | |
12 #include "ui/events/keycodes/keyboard_code_conversion_x.h" | |
13 #include "ui/events/platform/platform_event_dispatcher.h" | |
14 #include "ui/events/x/events_x_utils.h" | |
15 | |
16 namespace ui { | |
17 | |
18 namespace { | |
19 | |
20 // Translates XI2 XEvent into a ui::Event. | |
21 ui::Event* TranslateXI2EventToEvent(const XEvent& xev) { | |
22 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev.xcookie.data); | |
23 EventType event_type = EventTypeFromXEvent(xev); | |
24 gfx::Point location = gfx::Point(xievent->event_x, xievent->event_y); | |
25 gfx::Point root_location = gfx::Point(xievent->root_x, xievent->root_y); | |
26 int flags = EventFlagsFromXEvent(xev); | |
27 switch (event_type) { | |
28 case ET_KEY_PRESSED: | |
29 case ET_KEY_RELEASED: | |
30 return new KeyEvent(event_type, KeyboardCodeFromXKeyEvent(&xev), flags); | |
31 case ET_MOUSE_PRESSED: | |
32 case ET_MOUSE_MOVED: | |
33 case ET_MOUSE_DRAGGED: | |
34 case ET_MOUSE_RELEASED: | |
35 return new MouseEvent(event_type, location, root_location, | |
36 EventTimeFromXEvent(xev), flags, | |
37 GetChangedMouseButtonFlagsFromXEvent(xev)); | |
38 case ET_MOUSEWHEEL: | |
39 return new MouseWheelEvent(GetMouseWheelOffsetFromXEvent(xev), location, | |
40 root_location, EventTimeFromXEvent(xev), flags, | |
41 GetChangedMouseButtonFlagsFromXEvent(xev)); | |
42 case ET_SCROLL_FLING_START: | |
43 case ET_SCROLL_FLING_CANCEL: { | |
44 float x_offset, y_offset, x_offset_ordinal, y_offset_ordinal; | |
45 GetFlingDataFromXEvent(xev, &x_offset, &y_offset, &x_offset_ordinal, | |
46 &y_offset_ordinal, nullptr); | |
47 return new ScrollEvent(event_type, location, EventTimeFromXEvent(xev), | |
48 flags, x_offset, y_offset, x_offset_ordinal, | |
49 y_offset_ordinal, 0); | |
50 } | |
51 case ET_SCROLL: { | |
52 float x_offset, y_offset, x_offset_ordinal, y_offset_ordinal; | |
53 int finger_count; | |
54 GetScrollOffsetsFromXEvent(xev, &x_offset, &y_offset, &x_offset_ordinal, | |
55 &y_offset_ordinal, &finger_count); | |
56 return new ScrollEvent(event_type, location, EventTimeFromXEvent(xev), | |
57 flags, x_offset, y_offset, x_offset_ordinal, | |
58 y_offset_ordinal, finger_count); | |
59 } | |
60 case ET_TOUCH_MOVED: | |
61 case ET_TOUCH_PRESSED: | |
62 case ET_TOUCH_CANCELLED: | |
63 case ET_TOUCH_RELEASED: | |
64 return new TouchEvent(event_type, location, GetTouchIdFromXEvent(xev), | |
65 EventTimeFromXEvent(xev)); | |
66 case ET_UNKNOWN: | |
67 return nullptr; | |
68 default: | |
69 break; | |
70 } | |
71 return nullptr; | |
72 } | |
73 | |
74 // Translates a XEvent into a ui::Event. | |
75 ui::Event* TranslateXEventToEvent(const XEvent& xev) { | |
76 int flags = EventFlagsFromXEvent(xev); | |
77 switch (xev.type) { | |
78 case LeaveNotify: | |
79 case EnterNotify: | |
80 // EnterNotify creates ET_MOUSE_MOVED. Mark as synthesized as this is | |
81 // not real mouse move event. | |
82 // int flags = GetEventFlagsFromXState(xev.xcrossing.state); | |
83 if (xev.type == EnterNotify) | |
84 flags |= EF_IS_SYNTHESIZED; | |
85 return new MouseEvent( | |
86 ET_MOUSE_MOVED, gfx::Point(xev.xcrossing.x, xev.xcrossing.y), | |
87 gfx::Point(xev.xcrossing.x_root, xev.xcrossing.y_root), | |
88 EventTimeFromXEvent(xev), flags, 0); | |
89 | |
90 case KeyPress: | |
91 case KeyRelease: | |
92 return new KeyEvent(EventTypeFromXEvent(xev), | |
93 KeyboardCodeFromXKeyEvent(&xev), flags); | |
94 | |
95 case ButtonPress: | |
96 case ButtonRelease: { | |
97 gfx::Point location = gfx::Point(xev.xbutton.x, xev.xbutton.y); | |
98 gfx::Point root_location = | |
99 gfx::Point(xev.xbutton.x_root, xev.xbutton.y_root); | |
100 switch (EventTypeFromXEvent(xev)) { | |
101 case ET_MOUSEWHEEL: | |
102 return new MouseWheelEvent(GetMouseWheelOffsetFromXEvent(xev), | |
103 location, root_location, | |
104 EventTimeFromXEvent(xev), flags, 0); | |
105 case ET_MOUSE_PRESSED: | |
106 case ET_MOUSE_RELEASED: | |
107 return new MouseEvent(EventTypeFromXEvent(xev), location, | |
108 root_location, EventTimeFromXEvent(xev), flags, | |
109 GetChangedMouseButtonFlagsFromXEvent(xev)); | |
110 case ET_UNKNOWN: | |
111 // No event is created for X11-release events for mouse-wheel | |
112 // buttons. | |
113 break; | |
114 default: | |
115 NOTREACHED(); | |
116 } | |
117 break; | |
118 } | |
119 | |
120 case GenericEvent: | |
121 return TranslateXI2EventToEvent(xev); | |
122 } | |
123 return nullptr; | |
124 } | |
125 | |
126 } // namespace | |
127 | |
128 X11EventSourceOzone::X11EventSourceOzone(XDisplay* display) | |
129 : X11EventSource(display) { | |
130 AddEventWatcher(); | |
131 } | |
132 | |
133 X11EventSourceOzone::~X11EventSourceOzone() {} | |
134 | |
135 X11EventSourceOzone* X11EventSourceOzone::GetInstance() { | |
136 return static_cast<X11EventSourceOzone*>(PlatformEventSource::GetInstance()); | |
137 } | |
138 | |
139 void X11EventSourceOzone::AddXEventDispatcher(XEventDispatcher* dispatcher) { | |
140 dispatchers_xevent_.AddObserver(dispatcher); | |
141 } | |
142 | |
143 void X11EventSourceOzone::RemoveXEventDispatcher(XEventDispatcher* dispatcher) { | |
144 dispatchers_xevent_.RemoveObserver(dispatcher); | |
145 } | |
146 | |
147 uint32_t X11EventSourceOzone::DispatchEvent(base::NativeEvent native_event) { | |
148 XEvent* xevent = static_cast<XEvent*>(native_event); | |
sadrul
2016/02/04 22:29:32
In ozone, NativeEvent is a ui::Event, and not an X
kylechar
2016/02/05 18:21:46
I avoided this initially because of how it expands
| |
149 uint32_t action = POST_DISPATCH_STOP_PROPAGATION; | |
150 base::NativeEvent translated_event = TranslateXEventToEvent(*xevent); | |
151 if (translated_event) { | |
152 action = PlatformEventSource::DispatchEvent(translated_event); | |
153 } else { | |
154 // Only if we can't translate XEvent into ui::Event, try to dispatch XEvent | |
155 // directly to XEventDispatchers. | |
156 DispatchXEventToXEventDispatchers(xevent); | |
157 } | |
158 PostDispatchEvent(xevent); | |
159 return action; | |
160 } | |
161 | |
162 void X11EventSourceOzone::OnDispatcherListChanged() { | |
163 AddEventWatcher(); | |
164 X11EventSource::OnDispatcherListChanged(); | |
165 } | |
166 | |
167 void X11EventSourceOzone::AddEventWatcher() { | |
168 if (initialized_) | |
169 return; | |
170 if (!base::MessageLoop::current()) | |
171 return; | |
172 | |
173 int fd = ConnectionNumber(display()); | |
174 base::MessageLoopForUI::current()->WatchFileDescriptor( | |
175 fd, true, base::MessagePumpLibevent::WATCH_READ, &watcher_controller_, | |
176 this); | |
177 initialized_ = true; | |
178 } | |
179 | |
180 void X11EventSourceOzone::DispatchXEventToXEventDispatchers(XEvent* xevent) { | |
181 if (dispatchers_xevent_.might_have_observers()) { | |
182 base::ObserverList<XEventDispatcher>::Iterator iter(&dispatchers_xevent_); | |
183 while (XEventDispatcher* dispatcher = iter.GetNext()) { | |
184 if (dispatcher->DispatchXEvent(xevent)) | |
185 break; | |
186 } | |
187 } | |
188 } | |
189 | |
190 void X11EventSourceOzone::OnFileCanReadWithoutBlocking(int fd) { | |
191 DispatchXEvents(); | |
192 } | |
193 | |
194 void X11EventSourceOzone::OnFileCanWriteWithoutBlocking(int fd) { | |
195 NOTREACHED(); | |
196 } | |
197 | |
198 } // namespace ui | |
OLD | NEW |