Index: ui/events/platform/x11/x11_event_source_ozone.cc |
diff --git a/ui/events/platform/x11/x11_event_source_ozone.cc b/ui/events/platform/x11/x11_event_source_ozone.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d4a9b51fce49b67d4875fae84e022280cd5565a3 |
--- /dev/null |
+++ b/ui/events/platform/x11/x11_event_source_ozone.cc |
@@ -0,0 +1,198 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// 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_ozone.h" |
+ |
+#include <X11/Xlib.h> |
+#include <X11/extensions/XInput2.h> |
+ |
+#include "base/message_loop/message_loop.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 { |
+ |
+// 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); |
+ 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; |
+} |
+ |
+// 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); |
+ } |
+ return nullptr; |
+} |
+ |
+} // namespace |
+ |
+X11EventSourceOzone::X11EventSourceOzone(XDisplay* display) |
+ : X11EventSource(display) { |
+ AddEventWatcher(); |
+} |
+ |
+X11EventSourceOzone::~X11EventSourceOzone() {} |
+ |
+X11EventSourceOzone* X11EventSourceOzone::GetInstance() { |
+ return static_cast<X11EventSourceOzone*>(PlatformEventSource::GetInstance()); |
+} |
+ |
+void X11EventSourceOzone::AddXEventDispatcher(XEventDispatcher* dispatcher) { |
+ dispatchers_xevent_.AddObserver(dispatcher); |
+} |
+ |
+void X11EventSourceOzone::RemoveXEventDispatcher(XEventDispatcher* dispatcher) { |
+ dispatchers_xevent_.RemoveObserver(dispatcher); |
+} |
+ |
+uint32_t X11EventSourceOzone::DispatchEvent(base::NativeEvent native_event) { |
+ 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
|
+ uint32_t action = POST_DISPATCH_STOP_PROPAGATION; |
+ base::NativeEvent translated_event = TranslateXEventToEvent(*xevent); |
+ if (translated_event) { |
+ action = PlatformEventSource::DispatchEvent(translated_event); |
+ } else { |
+ // Only if we can't translate XEvent into ui::Event, try to dispatch XEvent |
+ // directly to XEventDispatchers. |
+ DispatchXEventToXEventDispatchers(xevent); |
+ } |
+ PostDispatchEvent(xevent); |
+ return action; |
+} |
+ |
+void X11EventSourceOzone::OnDispatcherListChanged() { |
+ AddEventWatcher(); |
+ X11EventSource::OnDispatcherListChanged(); |
+} |
+ |
+void X11EventSourceOzone::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; |
+} |
+ |
+void X11EventSourceOzone::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 X11EventSourceOzone::OnFileCanReadWithoutBlocking(int fd) { |
+ DispatchXEvents(); |
+} |
+ |
+void X11EventSourceOzone::OnFileCanWriteWithoutBlocking(int fd) { |
+ NOTREACHED(); |
+} |
+ |
+} // namespace ui |