| 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..fe22dee9b30081546dc44ffc21abc6127409463a
|
| --- /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);
|
| + 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
|
|
|