OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/events/platform/x11/x11_event_source.h" | 5 #include "ui/events/platform/x11/x11_event_source_libevent.h" |
6 | 6 |
7 #include <X11/Xlib.h> | 7 #include <X11/Xlib.h> |
8 | 8 #include <X11/extensions/XInput2.h> |
9 #include "base/macros.h" | 9 |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
11 #include "base/message_loop/message_pump_libevent.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" | |
12 | 15 |
13 namespace ui { | 16 namespace ui { |
14 | 17 |
15 namespace { | 18 namespace { |
16 | 19 |
17 class X11EventSourceLibevent : public X11EventSource, | 20 // Translates XI2 XEvent into a ui::Event. |
18 public base::MessagePumpLibevent::Watcher { | 21 ui::Event* TranslateXI2EventToEvent(const XEvent& xev) { |
19 public: | 22 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev.xcookie.data); |
20 explicit X11EventSourceLibevent(XDisplay* display) | 23 EventType event_type = EventTypeFromXEvent(xev); |
21 : X11EventSource(display), | 24 gfx::Point location = gfx::Point(xievent->event_x, xievent->event_y); |
22 initialized_(false) { | 25 gfx::Point root_location = gfx::Point(xievent->root_x, xievent->root_y); |
sadrul
2016/02/08 17:28:32
Can you use Event[System]LocationFromXEvent instea
kylechar
2016/02/08 19:08:09
Yep, Event[System]LocationFromXEvent works fine. A
| |
23 AddEventWatcher(); | 26 int flags = EventFlagsFromXEvent(xev); |
24 } | 27 switch (event_type) { |
25 | 28 case ET_KEY_PRESSED: |
26 ~X11EventSourceLibevent() override { | 29 case ET_KEY_RELEASED: |
27 } | 30 return new KeyEvent(event_type, KeyboardCodeFromXKeyEvent(&xev), flags); |
28 | 31 case ET_MOUSE_PRESSED: |
29 private: | 32 case ET_MOUSE_MOVED: |
30 void AddEventWatcher() { | 33 case ET_MOUSE_DRAGGED: |
31 if (initialized_) | 34 case ET_MOUSE_RELEASED: |
32 return; | 35 return new MouseEvent(event_type, location, root_location, |
33 if (!base::MessageLoop::current()) | 36 EventTimeFromXEvent(xev), flags, |
34 return; | 37 GetChangedMouseButtonFlagsFromXEvent(xev)); |
35 | 38 case ET_MOUSEWHEEL: |
36 int fd = ConnectionNumber(display()); | 39 return new MouseWheelEvent(GetMouseWheelOffsetFromXEvent(xev), location, |
37 base::MessageLoopForUI::current()->WatchFileDescriptor(fd, true, | 40 root_location, EventTimeFromXEvent(xev), flags, |
38 base::MessagePumpLibevent::WATCH_READ, &watcher_controller_, this); | 41 GetChangedMouseButtonFlagsFromXEvent(xev)); |
39 initialized_ = true; | 42 case ET_SCROLL_FLING_START: |
40 } | 43 case ET_SCROLL_FLING_CANCEL: { |
41 | 44 float x_offset, y_offset, x_offset_ordinal, y_offset_ordinal; |
42 // PlatformEventSource: | 45 GetFlingDataFromXEvent(xev, &x_offset, &y_offset, &x_offset_ordinal, |
43 void OnDispatcherListChanged() override { | 46 &y_offset_ordinal, nullptr); |
44 AddEventWatcher(); | 47 return new ScrollEvent(event_type, location, EventTimeFromXEvent(xev), |
45 } | 48 flags, x_offset, y_offset, x_offset_ordinal, |
46 | 49 y_offset_ordinal, 0); |
47 // base::MessagePumpLibevent::Watcher: | 50 } |
48 void OnFileCanReadWithoutBlocking(int fd) override { | 51 case ET_SCROLL: { |
49 DispatchXEvents(); | 52 float x_offset, y_offset, x_offset_ordinal, y_offset_ordinal; |
50 } | 53 int finger_count; |
51 | 54 GetScrollOffsetsFromXEvent(xev, &x_offset, &y_offset, &x_offset_ordinal, |
52 void OnFileCanWriteWithoutBlocking(int fd) override { | 55 &y_offset_ordinal, &finger_count); |
53 NOTREACHED(); | 56 return new ScrollEvent(event_type, location, EventTimeFromXEvent(xev), |
54 } | 57 flags, x_offset, y_offset, x_offset_ordinal, |
55 | 58 y_offset_ordinal, finger_count); |
56 base::MessagePumpLibevent::FileDescriptorWatcher watcher_controller_; | 59 } |
57 bool initialized_; | 60 case ET_TOUCH_MOVED: |
58 | 61 case ET_TOUCH_PRESSED: |
59 DISALLOW_COPY_AND_ASSIGN(X11EventSourceLibevent); | 62 case ET_TOUCH_CANCELLED: |
60 }; | 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 } | |
sadrul
2016/02/08 17:28:32
Use Event[System]LocationFromXEvent in this functi
kylechar
2016/02/08 19:08:09
Done.
| |
123 return nullptr; | |
124 } | |
61 | 125 |
62 } // namespace | 126 } // namespace |
63 | 127 |
64 scoped_ptr<PlatformEventSource> PlatformEventSource::CreateDefault() { | 128 X11EventSourceLibevent::X11EventSourceLibevent(XDisplay* display) { |
65 return make_scoped_ptr(new X11EventSourceLibevent(gfx::GetXDisplay())); | 129 event_source_.reset(new X11EventSource(this, display)); |
130 AddEventWatcher(); | |
131 } | |
132 | |
133 X11EventSourceLibevent::~X11EventSourceLibevent() {} | |
134 | |
135 // static | |
136 X11EventSourceLibevent* X11EventSourceLibevent::GetInstance() { | |
137 return static_cast<X11EventSourceLibevent*>( | |
138 PlatformEventSource::GetInstance()); | |
139 } | |
140 | |
141 void X11EventSourceLibevent::ProcessXEvent(XEvent* xevent) { | |
142 base::NativeEvent translated_event = TranslateXEventToEvent(*xevent); | |
sadrul
2016/02/08 17:28:32
Looks like |translated_event| here is leaking? Upd
kylechar
2016/02/08 19:08:09
Yeah, good catch. Done.
| |
143 if (translated_event) { | |
144 DispatchEvent(translated_event); | |
145 } else { | |
146 // Only if we can't translate XEvent into ui::Event, try to dispatch XEvent | |
147 // directly to XEventDispatchers. | |
148 DispatchXEventToXEventDispatchers(xevent); | |
149 } | |
150 } | |
151 | |
152 void X11EventSourceLibevent::AddXEventDispatcher(XEventDispatcher* dispatcher) { | |
153 dispatchers_xevent_.AddObserver(dispatcher); | |
154 } | |
155 | |
156 void X11EventSourceLibevent::RemoveXEventDispatcher( | |
157 XEventDispatcher* dispatcher) { | |
158 dispatchers_xevent_.RemoveObserver(dispatcher); | |
159 } | |
160 | |
161 void X11EventSourceLibevent::StopCurrentEventStream() { | |
162 event_source_->StopCurrentEventStream(); | |
163 } | |
164 | |
165 void X11EventSourceLibevent::OnDispatcherListChanged() { | |
166 AddEventWatcher(); | |
167 event_source_->OnDispatcherListChanged(); | |
168 } | |
169 | |
170 void X11EventSourceLibevent::AddEventWatcher() { | |
171 if (initialized_) | |
172 return; | |
173 if (!base::MessageLoop::current()) | |
174 return; | |
175 | |
176 int fd = ConnectionNumber(event_source_->display()); | |
177 base::MessageLoopForUI::current()->WatchFileDescriptor( | |
178 fd, true, base::MessagePumpLibevent::WATCH_READ, &watcher_controller_, | |
179 this); | |
180 initialized_ = true; | |
181 } | |
182 | |
183 void X11EventSourceLibevent::DispatchXEventToXEventDispatchers(XEvent* xevent) { | |
184 if (dispatchers_xevent_.might_have_observers()) { | |
185 base::ObserverList<XEventDispatcher>::Iterator iter(&dispatchers_xevent_); | |
186 while (XEventDispatcher* dispatcher = iter.GetNext()) { | |
187 if (dispatcher->DispatchXEvent(xevent)) | |
188 break; | |
189 } | |
190 } | |
191 } | |
192 | |
193 void X11EventSourceLibevent::OnFileCanReadWithoutBlocking(int fd) { | |
194 event_source_->DispatchXEvents(); | |
195 } | |
196 | |
197 void X11EventSourceLibevent::OnFileCanWriteWithoutBlocking(int fd) { | |
198 NOTREACHED(); | |
66 } | 199 } |
67 | 200 |
68 } // namespace ui | 201 } // namespace ui |
OLD | NEW |