Commit 2cc1c99e authored by Nick Diego Yamane's avatar Nick Diego Yamane Committed by Commit Bot

Make XEvent => ui::Event translation code reusable

Since non-Ozone X11 PlatformEvent implementation is meant to be migrated
soon to use ui::Event, as ozone path currently does, it makes sense to
move it to a separate class. This is what this CL does, and in a
follow-up change, tests will be modified to re-use this new class so
that we can ensure ui::EVent's construction is equivalent to the one
used in current Aura/X11 code.

Also, this prepares X11EventSource delegate implementations to be
refactored to use the same interfaces to comunicate about X11 events
(e.g: event translation, XEventDispatcher, etc). Such change will be
sent soon in separate CL.

Bug: 965991, 1008755
Change-Id: I6153ad7ff1e3c2f5baf4b94df6a13af4ca7fe71a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1866752Reviewed-by: default avatarSadrul Chowdhury <sadrul@chromium.org>
Commit-Queue: Nick Yamane <nickdiego@igalia.com>
Cr-Commit-Position: refs/heads/master@{#711619}
parent d436c8e6
......@@ -164,7 +164,7 @@ jumbo_component("events_base") {
"//ui/gfx/geometry",
]
if (use_x11) {
if (use_x11 || ozone_platform_x11) {
public_deps += [ "//ui/events/keycodes:x11" ]
}
......@@ -274,6 +274,11 @@ jumbo_component("events") {
"x/events_x.cc",
"x/keyboard_hook_x11.cc",
]
}
if (use_x11 || ozone_platform_x11) {
public += [ "x/x11_event_translation.h" ]
sources += [ "x/x11_event_translation.cc" ]
configs += [ "//build/config/linux:x11" ]
deps += [
"//ui/events/devices",
......@@ -490,13 +495,10 @@ jumbo_static_library("test_support") {
deps += [
"//ui/events/devices/x11",
"//ui/events/keycodes:x11",
"//ui/events/x",
"//ui/gfx/x",
]
}
if (use_x11 || ozone_platform_x11) {
deps += [ "//ui/events/x" ]
}
}
if (!is_ios) {
......
......@@ -12,6 +12,7 @@
#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"
#include "ui/events/x/x11_event_translation.h"
#include "ui/gfx/x/x11.h"
#if defined(OS_CHROMEOS)
......@@ -20,167 +21,6 @@
namespace ui {
namespace {
Event::Properties GetEventPropertiesFromXKeyEvent(const XKeyEvent& xev) {
using Values = std::vector<uint8_t>;
Event::Properties properties;
// Keyboard group
uint8_t group = XkbGroupForCoreState(xev.state);
properties.emplace(kPropertyKeyboardGroup, Values{group});
// IBus-gtk specific flags
uint8_t ibus_flags = (xev.state >> kPropertyKeyboardIBusFlagOffset) &
kPropertyKeyboardIBusFlagMask;
properties.emplace(kPropertyKeyboardIBusFlag, Values{ibus_flags});
return properties;
}
std::unique_ptr<KeyEvent> CreateKeyEvent(const XEvent& xev) {
// In CrOS/Linux builds, keep DomCode/DomKey unset in KeyEvent translation,
// so they are extracted lazily in KeyEvent::ApplyLayout() which makes it
// possible for CrOS to support host system keyboard layouts.
#if defined(OS_CHROMEOS)
auto key_event = std::make_unique<KeyEvent>(EventTypeFromXEvent(xev),
KeyboardCodeFromXKeyEvent(&xev),
EventFlagsFromXEvent(xev));
#else
base::TimeTicks timestamp = EventTimeFromXEvent(xev);
ValidateEventTimeClock(&timestamp);
auto key_event = std::make_unique<KeyEvent>(
EventTypeFromXEvent(xev), KeyboardCodeFromXKeyEvent(&xev),
CodeFromXEvent(&xev), EventFlagsFromXEvent(xev),
GetDomKeyFromXEvent(&xev), timestamp);
#endif
// Attach keyboard group to |key_event|'s properties
key_event->SetProperties(GetEventPropertiesFromXKeyEvent(xev.xkey));
return key_event;
}
std::unique_ptr<TouchEvent> CreateTouchEvent(EventType event_type,
const XEvent& xev) {
std::unique_ptr<TouchEvent> event = std::make_unique<TouchEvent>(
event_type, EventLocationFromXEvent(xev), EventTimeFromXEvent(xev),
GetTouchPointerDetailsFromXEvent(xev));
// Touch events don't usually have |root_location| set differently than
// |location|, since there is a touch device to display association, but this
// doesn't happen in Ozone X11.
event->set_root_location(EventSystemLocationFromXEvent(xev));
return event;
}
// Translates XI2 XEvent into a ui::Event.
std::unique_ptr<ui::Event> TranslateXI2EventToEvent(const XEvent& xev) {
EventType event_type = EventTypeFromXEvent(xev);
switch (event_type) {
case ET_KEY_PRESSED:
case ET_KEY_RELEASED: {
XEvent xkeyevent;
xkeyevent.xkey = {};
InitXKeyEventFromXIDeviceEvent(xev, &xkeyevent);
return CreateKeyEvent(xkeyevent);
}
case ET_MOUSE_PRESSED:
case ET_MOUSE_MOVED:
case ET_MOUSE_DRAGGED:
case ET_MOUSE_RELEASED:
return std::make_unique<MouseEvent>(
event_type, EventLocationFromXEvent(xev),
EventSystemLocationFromXEvent(xev), EventTimeFromXEvent(xev),
EventFlagsFromXEvent(xev), GetChangedMouseButtonFlagsFromXEvent(xev));
case ET_MOUSEWHEEL:
return std::make_unique<MouseWheelEvent>(
GetMouseWheelOffsetFromXEvent(xev), EventLocationFromXEvent(xev),
EventSystemLocationFromXEvent(xev), EventTimeFromXEvent(xev),
EventFlagsFromXEvent(xev), 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 std::make_unique<ScrollEvent>(
event_type, EventLocationFromXEvent(xev), EventTimeFromXEvent(xev),
EventFlagsFromXEvent(xev), 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 std::make_unique<ScrollEvent>(
event_type, EventLocationFromXEvent(xev), EventTimeFromXEvent(xev),
EventFlagsFromXEvent(xev), 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 CreateTouchEvent(event_type, xev);
case ET_UNKNOWN:
return nullptr;
default:
break;
}
return nullptr;
}
// Translates a XEvent into a ui::Event.
std::unique_ptr<ui::Event> TranslateXEventToEvent(const XEvent& xev) {
int flags = EventFlagsFromXEvent(xev);
switch (xev.type) {
case LeaveNotify:
case EnterNotify:
// Don't generate synthetic mouse move events for EnterNotify/LeaveNotify
// from nested XWindows. https://crbug.com/792322
if (xev.xcrossing.detail == NotifyInferior)
return nullptr;
return std::make_unique<MouseEvent>(EventTypeFromXEvent(xev),
EventLocationFromXEvent(xev),
EventSystemLocationFromXEvent(xev),
EventTimeFromXEvent(xev), flags, 0);
case KeyPress:
case KeyRelease:
return CreateKeyEvent(xev);
case ButtonPress:
case ButtonRelease: {
switch (EventTypeFromXEvent(xev)) {
case ET_MOUSEWHEEL:
return std::make_unique<MouseWheelEvent>(
GetMouseWheelOffsetFromXEvent(xev), EventLocationFromXEvent(xev),
EventSystemLocationFromXEvent(xev), EventTimeFromXEvent(xev),
flags, 0);
case ET_MOUSE_PRESSED:
case ET_MOUSE_RELEASED:
return std::make_unique<MouseEvent>(
EventTypeFromXEvent(xev), EventLocationFromXEvent(xev),
EventSystemLocationFromXEvent(xev), 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
X11EventSourceDefault::X11EventSourceDefault(XDisplay* display)
: event_source_(this, display), watcher_controller_(FROM_HERE) {
AddEventWatcher();
......@@ -235,7 +75,7 @@ void X11EventSourceDefault::RestoreOverridenXEventDispatcher() {
}
void X11EventSourceDefault::ProcessXEvent(XEvent* xevent) {
std::unique_ptr<ui::Event> translated_event = TranslateXEventToEvent(*xevent);
auto translated_event = ui::BuildEventFromXEvent(*xevent);
if (translated_event) {
#if defined(OS_CHROMEOS)
if (translated_event->IsLocatedEvent()) {
......
// Copyright 2019 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/x/x11_event_translation.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/keyboard_code_conversion_x.h"
#include "ui/events/x/events_x_utils.h"
#include "ui/gfx/x/x11.h"
namespace ui {
namespace {
Event::Properties GetEventPropertiesFromXKeyEvent(const XKeyEvent& xev) {
using Values = std::vector<uint8_t>;
Event::Properties properties;
// Keyboard group
uint8_t group = XkbGroupForCoreState(xev.state);
properties.emplace(kPropertyKeyboardGroup, Values{group});
// IBus-gtk specific flags
uint8_t ibus_flags = (xev.state >> kPropertyKeyboardIBusFlagOffset) &
kPropertyKeyboardIBusFlagMask;
properties.emplace(kPropertyKeyboardIBusFlag, Values{ibus_flags});
return properties;
}
std::unique_ptr<KeyEvent> CreateKeyEvent(EventType event_type,
const XEvent& xev) {
auto event = std::make_unique<KeyEvent>(
event_type, KeyboardCodeFromXKeyEvent(&xev), CodeFromXEvent(&xev),
EventFlagsFromXEvent(xev));
DCHECK(event);
event->SetProperties(GetEventPropertiesFromXKeyEvent(xev.xkey));
return event;
}
std::unique_ptr<MouseEvent> CreateMouseEvent(EventType type,
const XEvent& xev) {
// Don't generate synthetic mouse move events for EnterNotify/LeaveNotify
// from nested XWindows. https://crbug.com/792322
bool enter_or_leave = xev.type == LeaveNotify || xev.type == EnterNotify;
if (enter_or_leave && xev.xcrossing.detail == NotifyInferior)
return nullptr;
int button_flags =
(enter_or_leave) ? GetChangedMouseButtonFlagsFromXEvent(xev) : 0;
PointerDetails details{EventPointerType::POINTER_TYPE_MOUSE};
auto event = std::make_unique<MouseEvent>(
type, EventLocationFromXEvent(xev), EventSystemLocationFromXEvent(xev),
EventTimeFromXEvent(xev), EventFlagsFromXEvent(xev), button_flags,
details);
DCHECK(event);
return event;
}
std::unique_ptr<MouseWheelEvent> CreateMouseWheelEvent(const XEvent& xev) {
int button_flags = (xev.type == GenericEvent)
? GetChangedMouseButtonFlagsFromXEvent(xev)
: 0;
auto event = std::make_unique<MouseWheelEvent>(
GetMouseWheelOffsetFromXEvent(xev), EventLocationFromXEvent(xev),
EventSystemLocationFromXEvent(xev), EventTimeFromXEvent(xev),
EventFlagsFromXEvent(xev), button_flags);
DCHECK(event);
return event;
}
std::unique_ptr<TouchEvent> CreateTouchEvent(EventType type,
const XEvent& xev) {
std::unique_ptr<TouchEvent> event = std::make_unique<TouchEvent>(
type, EventLocationFromXEvent(xev), EventTimeFromXEvent(xev),
GetTouchPointerDetailsFromXEvent(xev));
DCHECK(event);
// Touch events don't usually have |root_location| set differently than
// |location|, since there is a touch device to display association, but this
// doesn't happen in Ozone X11.
event->set_root_location(EventSystemLocationFromXEvent(xev));
return event;
}
std::unique_ptr<ScrollEvent> CreateScrollEvent(EventType type,
const XEvent& xev) {
float x_offset, y_offset, x_offset_ordinal, y_offset_ordinal;
int finger_count = 0;
if (type == ET_SCROLL) {
GetScrollOffsetsFromXEvent(xev, &x_offset, &y_offset, &x_offset_ordinal,
&y_offset_ordinal, &finger_count);
} else {
GetFlingDataFromXEvent(xev, &x_offset, &y_offset, &x_offset_ordinal,
&y_offset_ordinal, nullptr);
}
auto event = std::make_unique<ScrollEvent>(
type, EventLocationFromXEvent(xev), EventTimeFromXEvent(xev),
EventFlagsFromXEvent(xev), x_offset, y_offset, x_offset_ordinal,
y_offset_ordinal, finger_count);
DCHECK(event);
return event;
}
// Translates XI2 XEvent into a ui::Event.
std::unique_ptr<ui::Event> TranslateFromXI2Event(const XEvent& xev) {
EventType event_type = EventTypeFromXEvent(xev);
switch (event_type) {
case ET_KEY_PRESSED:
case ET_KEY_RELEASED:
return CreateKeyEvent(event_type, xev);
case ET_MOUSE_PRESSED:
case ET_MOUSE_RELEASED:
case ET_MOUSE_MOVED:
case ET_MOUSE_DRAGGED:
return CreateMouseEvent(event_type, xev);
case ET_MOUSEWHEEL:
return CreateMouseWheelEvent(xev);
case ET_SCROLL_FLING_START:
case ET_SCROLL_FLING_CANCEL:
case ET_SCROLL:
return CreateScrollEvent(event_type, xev);
case ET_TOUCH_MOVED:
case ET_TOUCH_PRESSED:
case ET_TOUCH_CANCELLED:
case ET_TOUCH_RELEASED:
return CreateTouchEvent(event_type, xev);
case ET_UNKNOWN:
return nullptr;
default:
break;
}
return nullptr;
}
std::unique_ptr<Event> TranslateFromXEvent(const XEvent& xev) {
EventType event_type = EventTypeFromXEvent(xev);
switch (xev.type) {
case LeaveNotify:
case EnterNotify:
return CreateMouseEvent(event_type, xev);
case KeyPress:
case KeyRelease:
return CreateKeyEvent(event_type, xev);
case ButtonPress:
case ButtonRelease: {
switch (event_type) {
case ET_MOUSEWHEEL:
return CreateMouseWheelEvent(xev);
case ET_MOUSE_PRESSED:
case ET_MOUSE_RELEASED:
return CreateMouseEvent(event_type, xev);
case ET_UNKNOWN:
// No event is created for X11-release events for mouse-wheel
// buttons.
break;
default:
NOTREACHED();
}
break;
}
case GenericEvent:
return TranslateFromXI2Event(xev);
}
return nullptr;
}
} // namespace
// Translates a XEvent into a ui::Event.
std::unique_ptr<Event> BuildEventFromXEvent(const XEvent& xev) {
return TranslateFromXEvent(xev);
}
// Convenience function that translates XEvent into ui::KeyEvent
std::unique_ptr<KeyEvent> BuildKeyEventFromXEvent(const XEvent& xev) {
auto event = BuildEventFromXEvent(xev);
if (!event || !event->IsKeyEvent())
return nullptr;
return std::unique_ptr<KeyEvent>{event.release()->AsKeyEvent()};
}
// Convenience function that translates XEvent into ui::MouseEvent
std::unique_ptr<MouseEvent> BuildMouseEventFromXEvent(const XEvent& xev) {
auto event = BuildEventFromXEvent(xev);
if (!event || !event->IsMouseEvent())
return nullptr;
return std::unique_ptr<MouseEvent>{event.release()->AsMouseEvent()};
}
// Convenience function that translates XEvent into ui::TouchEvent
std::unique_ptr<TouchEvent> BuildTouchEventFromXEvent(const XEvent& xev) {
auto event = BuildEventFromXEvent(xev);
if (!event || !event->IsTouchEvent())
return nullptr;
return std::unique_ptr<TouchEvent>{event.release()->AsTouchEvent()};
}
// Convenience function that translates XEvent into ui::MouseWheelEvent
std::unique_ptr<MouseWheelEvent> BuildMouseWheelEventFromXEvent(
const XEvent& xev) {
auto event = BuildEventFromXEvent(xev);
if (!event || !event->IsMouseWheelEvent())
return nullptr;
return std::unique_ptr<MouseWheelEvent>{event.release()->AsMouseWheelEvent()};
}
} // namespace ui
// Copyright 2019 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.
#ifndef UI_EVENTS_X_X11_EVENT_TRANSLATION_H_
#define UI_EVENTS_X_X11_EVENT_TRANSLATION_H_
#include <memory>
#include "base/component_export.h"
#include "ui/events/events_export.h"
#include "ui/gfx/x/x11_types.h"
namespace ui {
class Event;
class KeyEvent;
class MouseEvent;
class MouseWheelEvent;
class TouchEvent;
// Translates a XEvent into a ui::Event.
EVENTS_EXPORT std::unique_ptr<Event> BuildEventFromXEvent(const XEvent& xev);
// Convenience function that translates XEvent into ui::KeyEvent
EVENTS_EXPORT std::unique_ptr<KeyEvent> BuildKeyEventFromXEvent(
const XEvent& xev);
// Convenience function that translates XEvent into ui::MouseEvent
EVENTS_EXPORT std::unique_ptr<MouseEvent> BuildMouseEventFromXEvent(
const XEvent& xev);
// Convenience function that translates XEvent into ui::MouseWheelEvent
EVENTS_EXPORT std::unique_ptr<MouseWheelEvent> BuildMouseWheelEventFromXEvent(
const XEvent& xev);
// Convenience function that translates XEvent into ui::TouchEvent
EVENTS_EXPORT std::unique_ptr<TouchEvent> BuildTouchEventFromXEvent(
const XEvent& xev);
} // namespace ui
#endif // UI_EVENTS_X_X11_EVENT_TRANSLATION_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment