Index: ui/events/platform/x11/x11_event_source_libevent.cc |
diff --git a/ui/events/platform/x11/x11_event_source_libevent.cc b/ui/events/platform/x11/x11_event_source_libevent.cc |
index a3ff7a50f94486676686ff6308f08c8938b7335a..41be11cca9abb23a231c495088b48f5bb976498b 100644 |
--- a/ui/events/platform/x11/x11_event_source_libevent.cc |
+++ b/ui/events/platform/x11/x11_event_source_libevent.cc |
@@ -2,67 +2,200 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "ui/events/platform/x11/x11_event_source.h" |
+#include "ui/events/platform/x11/x11_event_source_libevent.h" |
#include <X11/Xlib.h> |
+#include <X11/extensions/XInput2.h> |
-#include "base/macros.h" |
#include "base/message_loop/message_loop.h" |
-#include "base/message_loop/message_pump_libevent.h" |
+#include "ui/events/event.h" |
+#include "ui/events/keycodes/keyboard_code_conversion_x.h" |
+#include "ui/events/platform/platform_event_dispatcher.h" |
+#include "ui/events/x/events_x_utils.h" |
namespace ui { |
namespace { |
-class X11EventSourceLibevent : public X11EventSource, |
- public base::MessagePumpLibevent::Watcher { |
- public: |
- explicit X11EventSourceLibevent(XDisplay* display) |
- : X11EventSource(display), |
- initialized_(false) { |
- AddEventWatcher(); |
+// Translates XI2 XEvent into a ui::Event. |
+ui::Event* TranslateXI2EventToEvent(const XEvent& xev) { |
+ XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev.xcookie.data); |
+ EventType event_type = EventTypeFromXEvent(xev); |
+ gfx::Point location = gfx::Point(xievent->event_x, xievent->event_y); |
+ 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
|
+ int flags = EventFlagsFromXEvent(xev); |
+ switch (event_type) { |
+ case ET_KEY_PRESSED: |
+ case ET_KEY_RELEASED: |
+ return new KeyEvent(event_type, KeyboardCodeFromXKeyEvent(&xev), flags); |
+ case ET_MOUSE_PRESSED: |
+ case ET_MOUSE_MOVED: |
+ case ET_MOUSE_DRAGGED: |
+ case ET_MOUSE_RELEASED: |
+ return new MouseEvent(event_type, location, root_location, |
+ EventTimeFromXEvent(xev), flags, |
+ GetChangedMouseButtonFlagsFromXEvent(xev)); |
+ case ET_MOUSEWHEEL: |
+ return new MouseWheelEvent(GetMouseWheelOffsetFromXEvent(xev), location, |
+ root_location, EventTimeFromXEvent(xev), flags, |
+ GetChangedMouseButtonFlagsFromXEvent(xev)); |
+ case ET_SCROLL_FLING_START: |
+ case ET_SCROLL_FLING_CANCEL: { |
+ float x_offset, y_offset, x_offset_ordinal, y_offset_ordinal; |
+ GetFlingDataFromXEvent(xev, &x_offset, &y_offset, &x_offset_ordinal, |
+ &y_offset_ordinal, nullptr); |
+ return new ScrollEvent(event_type, location, EventTimeFromXEvent(xev), |
+ flags, x_offset, y_offset, x_offset_ordinal, |
+ y_offset_ordinal, 0); |
+ } |
+ case ET_SCROLL: { |
+ float x_offset, y_offset, x_offset_ordinal, y_offset_ordinal; |
+ int finger_count; |
+ GetScrollOffsetsFromXEvent(xev, &x_offset, &y_offset, &x_offset_ordinal, |
+ &y_offset_ordinal, &finger_count); |
+ return new ScrollEvent(event_type, location, EventTimeFromXEvent(xev), |
+ flags, x_offset, y_offset, x_offset_ordinal, |
+ y_offset_ordinal, finger_count); |
+ } |
+ case ET_TOUCH_MOVED: |
+ case ET_TOUCH_PRESSED: |
+ case ET_TOUCH_CANCELLED: |
+ case ET_TOUCH_RELEASED: |
+ return new TouchEvent(event_type, location, GetTouchIdFromXEvent(xev), |
+ EventTimeFromXEvent(xev)); |
+ case ET_UNKNOWN: |
+ return nullptr; |
+ default: |
+ break; |
} |
+ return nullptr; |
+} |
- ~X11EventSourceLibevent() override { |
+// Translates a XEvent into a ui::Event. |
+ui::Event* TranslateXEventToEvent(const XEvent& xev) { |
+ int flags = EventFlagsFromXEvent(xev); |
+ switch (xev.type) { |
+ case LeaveNotify: |
+ case EnterNotify: |
+ // EnterNotify creates ET_MOUSE_MOVED. Mark as synthesized as this is |
+ // not real mouse move event. |
+ // int flags = GetEventFlagsFromXState(xev.xcrossing.state); |
+ if (xev.type == EnterNotify) |
+ flags |= EF_IS_SYNTHESIZED; |
+ return new MouseEvent( |
+ ET_MOUSE_MOVED, gfx::Point(xev.xcrossing.x, xev.xcrossing.y), |
+ gfx::Point(xev.xcrossing.x_root, xev.xcrossing.y_root), |
+ EventTimeFromXEvent(xev), flags, 0); |
+ |
+ case KeyPress: |
+ case KeyRelease: |
+ return new KeyEvent(EventTypeFromXEvent(xev), |
+ KeyboardCodeFromXKeyEvent(&xev), flags); |
+ |
+ case ButtonPress: |
+ case ButtonRelease: { |
+ gfx::Point location = gfx::Point(xev.xbutton.x, xev.xbutton.y); |
+ gfx::Point root_location = |
+ gfx::Point(xev.xbutton.x_root, xev.xbutton.y_root); |
+ switch (EventTypeFromXEvent(xev)) { |
+ case ET_MOUSEWHEEL: |
+ return new MouseWheelEvent(GetMouseWheelOffsetFromXEvent(xev), |
+ location, root_location, |
+ EventTimeFromXEvent(xev), flags, 0); |
+ case ET_MOUSE_PRESSED: |
+ case ET_MOUSE_RELEASED: |
+ return new MouseEvent(EventTypeFromXEvent(xev), location, |
+ root_location, EventTimeFromXEvent(xev), flags, |
+ GetChangedMouseButtonFlagsFromXEvent(xev)); |
+ case ET_UNKNOWN: |
+ // No event is created for X11-release events for mouse-wheel |
+ // buttons. |
+ break; |
+ default: |
+ NOTREACHED(); |
+ } |
+ break; |
+ } |
+ |
+ case GenericEvent: |
+ return TranslateXI2EventToEvent(xev); |
} |
sadrul
2016/02/08 17:28:32
Use Event[System]LocationFromXEvent in this functi
kylechar
2016/02/08 19:08:09
Done.
|
+ return nullptr; |
+} |
- private: |
- void AddEventWatcher() { |
- if (initialized_) |
- return; |
- if (!base::MessageLoop::current()) |
- return; |
- |
- int fd = ConnectionNumber(display()); |
- base::MessageLoopForUI::current()->WatchFileDescriptor(fd, true, |
- base::MessagePumpLibevent::WATCH_READ, &watcher_controller_, this); |
- initialized_ = true; |
- } |
+} // namespace |
- // PlatformEventSource: |
- void OnDispatcherListChanged() override { |
- AddEventWatcher(); |
- } |
+X11EventSourceLibevent::X11EventSourceLibevent(XDisplay* display) { |
+ event_source_.reset(new X11EventSource(this, display)); |
+ AddEventWatcher(); |
+} |
- // base::MessagePumpLibevent::Watcher: |
- void OnFileCanReadWithoutBlocking(int fd) override { |
- DispatchXEvents(); |
- } |
+X11EventSourceLibevent::~X11EventSourceLibevent() {} |
+ |
+// static |
+X11EventSourceLibevent* X11EventSourceLibevent::GetInstance() { |
+ return static_cast<X11EventSourceLibevent*>( |
+ PlatformEventSource::GetInstance()); |
+} |
- void OnFileCanWriteWithoutBlocking(int fd) override { |
- NOTREACHED(); |
+void X11EventSourceLibevent::ProcessXEvent(XEvent* xevent) { |
+ 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.
|
+ if (translated_event) { |
+ DispatchEvent(translated_event); |
+ } else { |
+ // Only if we can't translate XEvent into ui::Event, try to dispatch XEvent |
+ // directly to XEventDispatchers. |
+ DispatchXEventToXEventDispatchers(xevent); |
} |
+} |
- base::MessagePumpLibevent::FileDescriptorWatcher watcher_controller_; |
- bool initialized_; |
+void X11EventSourceLibevent::AddXEventDispatcher(XEventDispatcher* dispatcher) { |
+ dispatchers_xevent_.AddObserver(dispatcher); |
+} |
- DISALLOW_COPY_AND_ASSIGN(X11EventSourceLibevent); |
-}; |
+void X11EventSourceLibevent::RemoveXEventDispatcher( |
+ XEventDispatcher* dispatcher) { |
+ dispatchers_xevent_.RemoveObserver(dispatcher); |
+} |
-} // namespace |
+void X11EventSourceLibevent::StopCurrentEventStream() { |
+ event_source_->StopCurrentEventStream(); |
+} |
+ |
+void X11EventSourceLibevent::OnDispatcherListChanged() { |
+ AddEventWatcher(); |
+ event_source_->OnDispatcherListChanged(); |
+} |
+ |
+void X11EventSourceLibevent::AddEventWatcher() { |
+ if (initialized_) |
+ return; |
+ if (!base::MessageLoop::current()) |
+ return; |
+ |
+ int fd = ConnectionNumber(event_source_->display()); |
+ base::MessageLoopForUI::current()->WatchFileDescriptor( |
+ fd, true, base::MessagePumpLibevent::WATCH_READ, &watcher_controller_, |
+ this); |
+ initialized_ = true; |
+} |
+ |
+void X11EventSourceLibevent::DispatchXEventToXEventDispatchers(XEvent* xevent) { |
+ if (dispatchers_xevent_.might_have_observers()) { |
+ base::ObserverList<XEventDispatcher>::Iterator iter(&dispatchers_xevent_); |
+ while (XEventDispatcher* dispatcher = iter.GetNext()) { |
+ if (dispatcher->DispatchXEvent(xevent)) |
+ break; |
+ } |
+ } |
+} |
+ |
+void X11EventSourceLibevent::OnFileCanReadWithoutBlocking(int fd) { |
+ event_source_->DispatchXEvents(); |
+} |
-scoped_ptr<PlatformEventSource> PlatformEventSource::CreateDefault() { |
- return make_scoped_ptr(new X11EventSourceLibevent(gfx::GetXDisplay())); |
+void X11EventSourceLibevent::OnFileCanWriteWithoutBlocking(int fd) { |
+ NOTREACHED(); |
} |
} // namespace ui |