0

x11: Ensure XEvent translation is equivalent to ui::Event ctors

This is part of the patch series migrating PlatformEvent to ui::Event
(formerly using XEvent) in Aura/X11 in order to eliminate this
fundamental difference/incompatibility between Ozone and non-Ozone X11
ports. Design doc [1] describes in details such effort.

This CL, particularly, is meant to ensure XEvent => ui::Event
translation code (x11_event_translation.{h,cc}) is equivalent to
constructing ui::*Event using the PlatformEvent ctors, the mechanism
used so far to do such "translation".

To achieve it, events_unittests have been modified to use the brand new
X11 event translation code as well as fixing discrepancies found along
the way. Most of them are trivial and this change does not bring any
behavioral change.

[1] https://docs.google.com/document/d/1Neh2p6f8pew9SPuEAtnJMafozAY7uhAIfhwd43CLETc

Bug: 965991
Change-Id: I1b738fd20c21233a611a0661b76da7fcdf176613
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2022322
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Thomas Anderson <thomasanderson@chromium.org>
Reviewed-by: Sadrul Chowdhury <sadrul@chromium.org>
Cr-Commit-Position: refs/heads/master@{#736213}
This commit is contained in:
Nick Diego Yamane
2020-01-29 03:24:31 +00:00
committed by Commit Bot
parent df130530a5
commit 9733253484
9 changed files with 273 additions and 248 deletions

@ -123,6 +123,7 @@
#include "ui/events/keycodes/keyboard_code_conversion.h"
#include "ui/events/test/events_test_utils.h"
#include "ui/events/test/events_test_utils_x11.h"
#include "ui/events/x/x11_event_translation.h"
#include "ui/gfx/x/x11.h"
#endif
@ -371,8 +372,8 @@ class RenderViewImplTest : public RenderViewTest {
xevent.InitKeyEvent(ui::ET_KEY_PRESSED,
static_cast<ui::KeyboardCode>(key_code),
flags);
ui::KeyEvent event1(xevent);
NativeWebKeyboardEvent keydown_event(event1);
auto event1 = ui::BuildKeyEventFromXEvent(*xevent);
NativeWebKeyboardEvent keydown_event(*event1);
SendNativeKeyEvent(keydown_event);
// X11 doesn't actually have native character events, but give the test
@ -380,19 +381,19 @@ class RenderViewImplTest : public RenderViewTest {
xevent.InitKeyEvent(ui::ET_KEY_PRESSED,
static_cast<ui::KeyboardCode>(key_code),
flags);
ui::KeyEvent event2(xevent);
event2.set_character(
DomCodeToUsLayoutCharacter(event2.code(), event2.flags()));
ui::KeyEventTestApi test_event2(&event2);
auto event2 = ui::BuildKeyEventFromXEvent(*xevent);
event2->set_character(
DomCodeToUsLayoutCharacter(event2->code(), event2->flags()));
ui::KeyEventTestApi test_event2(event2.get());
test_event2.set_is_char(true);
NativeWebKeyboardEvent char_event(event2);
NativeWebKeyboardEvent char_event(*event2);
SendNativeKeyEvent(char_event);
xevent.InitKeyEvent(ui::ET_KEY_RELEASED,
static_cast<ui::KeyboardCode>(key_code),
flags);
ui::KeyEvent event3(xevent);
NativeWebKeyboardEvent keyup_event(event3);
auto event3 = ui::BuildKeyEventFromXEvent(*xevent);
NativeWebKeyboardEvent keyup_event(*event3);
SendNativeKeyEvent(keyup_event);
long c = DomCodeToUsLayoutCharacter(

@ -18,6 +18,7 @@
#include "ui/events/keycodes/dom/dom_key.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/events/test/keyboard_layout.h"
#include "ui/events/x/x11_event_translation.h"
#if defined(USE_X11)
#include "ui/events/test/events_test_utils_x11.h"
@ -81,8 +82,8 @@ TEST(WebInputEventTest, TestMakeWebKeyboardEvent) {
{
// Press Ctrl.
xev.InitKeyEvent(ET_KEY_PRESSED, VKEY_CONTROL, 0);
KeyEvent event(xev);
blink::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(event);
auto event = ui::BuildKeyEventFromXEvent(*xev);
blink::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(*event);
// However, modifier bit for Control in |webkit_event| should be set.
EXPECT_EQ(blink::WebInputEvent::kControlKey,
webkit_event.GetModifiers() & ~kLocationModifiers);
@ -90,8 +91,8 @@ TEST(WebInputEventTest, TestMakeWebKeyboardEvent) {
{
// Release Ctrl.
xev.InitKeyEvent(ET_KEY_RELEASED, VKEY_CONTROL, ControlMask);
KeyEvent event(xev);
blink::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(event);
auto event = ui::BuildKeyEventFromXEvent(*xev);
blink::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(*event);
// However, modifier bit for Control in |webkit_event| shouldn't be set.
EXPECT_EQ(0, webkit_event.GetModifiers() & ~kLocationModifiers);
}
@ -107,8 +108,8 @@ TEST(WebInputEventTest, TestMakeWebKeyboardEventWindowsKeyCode) {
XEvent* xevent = xev;
xevent->xkey.keycode =
KeycodeConverter::DomCodeToNativeKeycode(DomCode::CONTROL_LEFT);
KeyEvent event(xev);
blink::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(event);
auto event = ui::BuildKeyEventFromXEvent(*xev);
blink::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(*event);
EXPECT_EQ(VKEY_CONTROL, webkit_event.windows_key_code);
}
{
@ -117,8 +118,8 @@ TEST(WebInputEventTest, TestMakeWebKeyboardEventWindowsKeyCode) {
XEvent* xevent = xev;
xevent->xkey.keycode =
KeycodeConverter::DomCodeToNativeKeycode(DomCode::CONTROL_RIGHT);
KeyEvent event(xev);
blink::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(event);
auto event = ui::BuildKeyEventFromXEvent(*xev);
blink::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(*event);
EXPECT_EQ(VKEY_CONTROL, webkit_event.windows_key_code);
}
#elif defined(OS_WIN)
@ -225,8 +226,8 @@ TEST(WebInputEventTest, TestMakeWebKeyboardEventKeyPadKeyCode) {
XKeysymToKeycode(gfx::GetXDisplay(), test_case.x_keysym);
if (!xevent->xkey.keycode)
continue;
KeyEvent event(xev);
blink::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(event);
auto event = ui::BuildKeyEventFromXEvent(*xev);
blink::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(*event);
EXPECT_EQ(test_case.expected_result, (webkit_event.GetModifiers() &
blink::WebInputEvent::kIsKeyPad) != 0)
<< "Failed in " << i << "th test case: "

@ -44,17 +44,6 @@
namespace ui {
namespace {
#if defined(USE_X11)
bool X11EventHasNonStandardState(const PlatformEvent& event) {
const unsigned int kAllStateMask =
Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask |
Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask | ShiftMask |
LockMask | ControlMask | AnyModifier;
return event && (event->xkey.state & ~kAllStateMask) != 0;
}
#endif
constexpr int kChangedButtonFlagMask =
ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON |
ui::EF_RIGHT_MOUSE_BUTTON | ui::EF_BACK_MOUSE_BUTTON |
@ -478,8 +467,7 @@ MouseEvent::MouseEvent(const PlatformEvent& native_event)
latency()->AddLatencyNumberWithTimestamp(
INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, time_stamp());
latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT);
if (type() == ET_MOUSE_PRESSED || type() == ET_MOUSE_RELEASED)
SetClickCount(GetRepeatCount(*this));
InitializeNative();
#if defined(USE_X11)
SetProperties(GetEventPropertiesFromXEvent(type(), *native_event));
#endif
@ -523,6 +511,12 @@ MouseEvent::MouseEvent(const MouseEvent& other) = default;
MouseEvent::~MouseEvent() = default;
void MouseEvent::InitializeNative() {
if (type() == ET_MOUSE_PRESSED || type() == ET_MOUSE_RELEASED) {
SetClickCount(GetRepeatCount(*this));
}
}
// static
bool MouseEvent::IsRepeatedClickEvent(const MouseEvent& event1,
const MouseEvent& event2) {
@ -816,36 +810,7 @@ KeyEvent::KeyEvent(const PlatformEvent& native_event, int event_flags)
key_code_(KeyboardCodeFromNative(native_event)),
code_(CodeFromNative(native_event)),
is_char_(IsCharFromNative(native_event)) {
latency()->AddLatencyNumberWithTimestamp(
INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, time_stamp());
latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT);
KeyEvent** last_key_event = &last_key_event_;
#if defined(USE_X11)
// Use a different static variable for key events that have non standard
// state masks as it may be reposted by an IME. IBUS-GTK uses this field
// to detect the re-posted event for example. crbug.com/385873.
if (X11EventHasNonStandardState(native_event))
last_key_event = &last_ibus_key_event_;
NormalizeFlags();
key_ = GetDomKeyFromXEvent(native_event);
SetProperties(GetEventPropertiesFromXEvent(type(), *native_event));
#elif defined(OS_WIN)
// Only Windows has native character events.
if (is_char_) {
key_ = DomKey::FromCharacter(static_cast<int32_t>(native_event.wParam));
set_flags(PlatformKeyMap::ReplaceControlAndAltWithAltGraph(flags()));
} else {
int adjusted_flags = flags();
key_ = PlatformKeyMap::DomKeyFromKeyboardCode(key_code(), &adjusted_flags);
set_flags(adjusted_flags);
}
#endif
if (IsRepeated(last_key_event))
set_flags(flags() | ui::EF_IS_REPEAT);
InitializeNative();
}
KeyEvent::KeyEvent(EventType type,
@ -911,7 +876,38 @@ KeyEvent& KeyEvent::operator=(const KeyEvent& rhs) {
return *this;
}
KeyEvent::~KeyEvent() {}
KeyEvent::~KeyEvent() = default;
void KeyEvent::InitializeNative() {
latency()->AddLatencyNumberWithTimestamp(
INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, time_stamp());
latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT);
KeyEvent** last_key_event = &last_key_event_;
#if defined(USE_X11)
// Use a different static variable for key events that have non standard
// state masks as it may be reposted by an IME. IBUS-GTK uses this field
// to detect the re-posted event for example. crbug.com/385873.
if (properties() && properties()->contains(kPropertyKeyboardIBusFlag)) {
last_key_event = &last_ibus_key_event_;
}
#elif defined(OS_WIN)
// Only Windows has native character events.
if (is_char_) {
key_ = DomKey::FromCharacter(static_cast<int32_t>(native_event().wParam));
set_flags(PlatformKeyMap::ReplaceControlAndAltWithAltGraph(flags()));
} else {
int adjusted_flags = flags();
key_ = PlatformKeyMap::DomKeyFromKeyboardCode(key_code(), &adjusted_flags);
set_flags(adjusted_flags);
}
#endif
NormalizeFlags();
if (IsRepeated(last_key_event))
set_flags(flags() | ui::EF_IS_REPEAT);
}
void KeyEvent::ApplyLayout() const {
ui::DomCode code = code_;

@ -486,6 +486,8 @@ class EVENTS_EXPORT MouseEvent : public LocatedEvent {
MouseEvent(const MouseEvent& copy);
~MouseEvent() override;
void InitializeNative();
class DispatcherApi {
public:
explicit DispatcherApi(MouseEvent* event) : event_(event) {}
@ -804,6 +806,8 @@ class EVENTS_EXPORT KeyEvent : public Event {
~KeyEvent() override;
void InitializeNative();
// This bypasses the normal mapping from keystroke events to characters,
// which allows an I18N virtual keyboard to fabricate a keyboard event that
// does not have a corresponding KeyboardCode (example: U+00E1 Latin small

@ -21,6 +21,7 @@
#include "ui/events/test/events_test_utils.h"
#include "ui/events/test/keyboard_layout.h"
#include "ui/events/test/test_event_target.h"
#include "ui/events/x/x11_event_translation.h"
#include "ui/gfx/transform.h"
#if defined(USE_X11)
@ -44,8 +45,8 @@ TEST(EventTest, NativeEvent) {
#elif defined(USE_X11)
ScopedXI2Event event;
event.InitKeyEvent(ET_KEY_RELEASED, VKEY_A, EF_NONE);
KeyEvent keyev(event);
EXPECT_TRUE(keyev.HasNativeEvent());
auto keyev = ui::BuildKeyEventFromXEvent(*event);
EXPECT_FALSE(keyev->HasNativeEvent());
#endif
}
@ -63,12 +64,12 @@ TEST(EventTest, GetCharacter) {
// For X11, test the functions with native_event() as well. crbug.com/107837
ScopedXI2Event event;
event.InitKeyEvent(ET_KEY_PRESSED, VKEY_RETURN, EF_CONTROL_DOWN);
KeyEvent keyev3(event);
EXPECT_EQ(10, keyev3.GetCharacter());
auto keyev3 = ui::BuildKeyEventFromXEvent(*event);
EXPECT_EQ(10, keyev3->GetCharacter());
event.InitKeyEvent(ET_KEY_PRESSED, VKEY_RETURN, EF_NONE);
KeyEvent keyev4(event);
EXPECT_EQ(13, keyev4.GetCharacter());
auto keyev4 = ui::BuildKeyEventFromXEvent(*event);
EXPECT_EQ(13, keyev4->GetCharacter());
#endif
// Check if expected Unicode character was returned for a key combination
@ -295,33 +296,33 @@ TEST(EventTest, NormalizeKeyEventFlags) {
ScopedXI2Event event;
{
event.InitKeyEvent(ET_KEY_PRESSED, VKEY_SHIFT, EF_SHIFT_DOWN);
KeyEvent keyev(event);
EXPECT_EQ(EF_SHIFT_DOWN, keyev.flags());
auto keyev = ui::BuildKeyEventFromXEvent(*event);
EXPECT_EQ(EF_SHIFT_DOWN, keyev->flags());
}
{
event.InitKeyEvent(ET_KEY_RELEASED, VKEY_SHIFT, EF_SHIFT_DOWN);
KeyEvent keyev(event);
EXPECT_EQ(EF_NONE, keyev.flags());
auto keyev = ui::BuildKeyEventFromXEvent(*event);
EXPECT_EQ(EF_NONE, keyev->flags());
}
{
event.InitKeyEvent(ET_KEY_PRESSED, VKEY_CONTROL, EF_CONTROL_DOWN);
KeyEvent keyev(event);
EXPECT_EQ(EF_CONTROL_DOWN, keyev.flags());
auto keyev = ui::BuildKeyEventFromXEvent(*event);
EXPECT_EQ(EF_CONTROL_DOWN, keyev->flags());
}
{
event.InitKeyEvent(ET_KEY_RELEASED, VKEY_CONTROL, EF_CONTROL_DOWN);
KeyEvent keyev(event);
EXPECT_EQ(EF_NONE, keyev.flags());
auto keyev = ui::BuildKeyEventFromXEvent(*event);
EXPECT_EQ(EF_NONE, keyev->flags());
}
{
event.InitKeyEvent(ET_KEY_PRESSED, VKEY_MENU, EF_ALT_DOWN);
KeyEvent keyev(event);
EXPECT_EQ(EF_ALT_DOWN, keyev.flags());
auto keyev = ui::BuildKeyEventFromXEvent(*event);
EXPECT_EQ(EF_ALT_DOWN, keyev->flags());
}
{
event.InitKeyEvent(ET_KEY_RELEASED, VKEY_MENU, EF_ALT_DOWN);
KeyEvent keyev(event);
EXPECT_EQ(EF_NONE, keyev.flags());
auto keyev = ui::BuildKeyEventFromXEvent(*event);
EXPECT_EQ(EF_NONE, keyev->flags());
}
#endif
@ -398,8 +399,8 @@ TEST(EventTest, KeyEventCode) {
// KeyEvent converts from the native keycode (XKB) to the code.
ScopedXI2Event xevent;
xevent.InitKeyEvent(ET_KEY_PRESSED, VKEY_SPACE, kNativeCodeSpace);
KeyEvent key(xevent);
EXPECT_EQ(kCodeForSpace, key.GetCodeString());
auto keyev = ui::BuildKeyEventFromXEvent(*xevent);
EXPECT_EQ(kCodeForSpace, keyev->GetCodeString());
}
#endif // USE_X11
#if defined(OS_WIN)
@ -477,77 +478,78 @@ TEST(EventTest, AutoRepeat) {
SetKeyEventTimestamp(native_event_a_pressed_3000, ticks_base + 3000);
{
KeyEvent key_a1(native_event_a_pressed);
EXPECT_FALSE(key_a1.is_repeat());
auto key_a1 = BuildKeyEventFromXEvent(*native_event_a_pressed);
EXPECT_FALSE(key_a1->is_repeat());
KeyEvent key_a1_released(native_event_a_released);
EXPECT_FALSE(key_a1_released.is_repeat());
auto key_a1_released = BuildKeyEventFromXEvent(*native_event_a_released);
EXPECT_FALSE(key_a1_released->is_repeat());
KeyEvent key_a2(native_event_a_pressed);
EXPECT_FALSE(key_a2.is_repeat());
auto key_a2 = BuildKeyEventFromXEvent(*native_event_a_pressed);
EXPECT_FALSE(key_a2->is_repeat());
AdvanceKeyEventTimestamp(native_event_a_pressed);
KeyEvent key_a2_repeated(native_event_a_pressed);
EXPECT_TRUE(key_a2_repeated.is_repeat());
auto key_a2_repeated = BuildKeyEventFromXEvent(*native_event_a_pressed);
EXPECT_TRUE(key_a2_repeated->is_repeat());
KeyEvent key_a2_released(native_event_a_released);
EXPECT_FALSE(key_a2_released.is_repeat());
auto key_a2_released = BuildKeyEventFromXEvent(*native_event_a_released);
EXPECT_FALSE(key_a2_released->is_repeat());
}
// Interleaved with different key press.
{
KeyEvent key_a3(native_event_a_pressed);
EXPECT_FALSE(key_a3.is_repeat());
auto key_a3 = BuildKeyEventFromXEvent(*native_event_a_pressed);
EXPECT_FALSE(key_a3->is_repeat());
KeyEvent key_b(native_event_b_pressed);
EXPECT_FALSE(key_b.is_repeat());
auto key_b = BuildKeyEventFromXEvent(*native_event_b_pressed);
EXPECT_FALSE(key_b->is_repeat());
AdvanceKeyEventTimestamp(native_event_a_pressed);
KeyEvent key_a3_again(native_event_a_pressed);
EXPECT_FALSE(key_a3_again.is_repeat());
auto key_a3_again = BuildKeyEventFromXEvent(*native_event_a_pressed);
EXPECT_FALSE(key_a3_again->is_repeat());
AdvanceKeyEventTimestamp(native_event_a_pressed);
KeyEvent key_a3_repeated(native_event_a_pressed);
EXPECT_TRUE(key_a3_repeated.is_repeat());
auto key_a3_repeated = BuildKeyEventFromXEvent(*native_event_a_pressed);
EXPECT_TRUE(key_a3_repeated->is_repeat());
AdvanceKeyEventTimestamp(native_event_a_pressed);
KeyEvent key_a3_repeated2(native_event_a_pressed);
EXPECT_TRUE(key_a3_repeated2.is_repeat());
auto key_a3_repeated2 = BuildKeyEventFromXEvent(*native_event_a_pressed);
EXPECT_TRUE(key_a3_repeated2->is_repeat());
KeyEvent key_a3_released(native_event_a_released);
EXPECT_FALSE(key_a3_released.is_repeat());
auto key_a3_released = BuildKeyEventFromXEvent(*native_event_a_released);
EXPECT_FALSE(key_a3_released->is_repeat());
}
// Hold the key longer than max auto repeat timeout.
{
KeyEvent key_a4_0(native_event_a_pressed);
EXPECT_FALSE(key_a4_0.is_repeat());
auto key_a4_0 = BuildKeyEventFromXEvent(*native_event_a_pressed);
EXPECT_FALSE(key_a4_0->is_repeat());
KeyEvent key_a4_1500(native_event_a_pressed_1500);
EXPECT_TRUE(key_a4_1500.is_repeat());
auto key_a4_1500 = BuildKeyEventFromXEvent(*native_event_a_pressed_1500);
EXPECT_TRUE(key_a4_1500->is_repeat());
KeyEvent key_a4_3000(native_event_a_pressed_3000);
EXPECT_TRUE(key_a4_3000.is_repeat());
auto key_a4_3000 = BuildKeyEventFromXEvent(*native_event_a_pressed_3000);
EXPECT_TRUE(key_a4_3000->is_repeat());
KeyEvent key_a4_released(native_event_a_released);
EXPECT_FALSE(key_a4_released.is_repeat());
auto key_a4_released = BuildKeyEventFromXEvent(*native_event_a_released);
EXPECT_FALSE(key_a4_released->is_repeat());
}
{
KeyEvent key_a4_pressed(native_event_a_pressed);
EXPECT_FALSE(key_a4_pressed.is_repeat());
auto key_a4_pressed = BuildKeyEventFromXEvent(*native_event_a_pressed);
EXPECT_FALSE(key_a4_pressed->is_repeat());
KeyEvent key_a4_pressed_nonstandard_state(
native_event_a_pressed_nonstandard_state);
EXPECT_FALSE(key_a4_pressed_nonstandard_state.is_repeat());
auto key_a4_pressed_nonstandard_state =
BuildKeyEventFromXEvent(*native_event_a_pressed_nonstandard_state);
EXPECT_FALSE(key_a4_pressed_nonstandard_state->is_repeat());
}
{
KeyEvent key_a1(native_event_a_pressed);
EXPECT_FALSE(key_a1.is_repeat());
auto key_a1 = BuildKeyEventFromXEvent(*native_event_a_pressed);
EXPECT_FALSE(key_a1->is_repeat());
KeyEvent key_a1_with_same_event(native_event_a_pressed);
EXPECT_FALSE(key_a1_with_same_event.is_repeat());
auto key_a1_with_same_event =
BuildKeyEventFromXEvent(*native_event_a_pressed);
EXPECT_FALSE(key_a1_with_same_event->is_repeat());
}
}
#endif // USE_X11
@ -788,17 +790,14 @@ TEST(EventTest, EventLatencyOSTouchHistograms) {
ui::SetUpTouchDevicesForTest(devices);
// Init touch begin, update, and end events with tracking id 5, touch id 0.
scoped_xevent.InitTouchEvent(
0, XI_TouchBegin, 5, gfx::Point(10, 10), std::vector<Valuator>());
TouchEvent touch_begin(scoped_xevent);
scoped_xevent.InitTouchEvent(0, XI_TouchBegin, 5, gfx::Point(10, 10), {});
auto touch_begin = ui::BuildTouchEventFromXEvent(*scoped_xevent);
histogram_tester.ExpectTotalCount("Event.Latency.OS.TOUCH_PRESSED", 1);
scoped_xevent.InitTouchEvent(
0, XI_TouchUpdate, 5, gfx::Point(20, 20), std::vector<Valuator>());
TouchEvent touch_update(scoped_xevent);
scoped_xevent.InitTouchEvent(0, XI_TouchUpdate, 5, gfx::Point(20, 20), {});
auto touch_update = ui::BuildTouchEventFromXEvent(*scoped_xevent);
histogram_tester.ExpectTotalCount("Event.Latency.OS.TOUCH_MOVED", 1);
scoped_xevent.InitTouchEvent(
0, XI_TouchEnd, 5, gfx::Point(30, 30), std::vector<Valuator>());
TouchEvent touch_end(scoped_xevent);
scoped_xevent.InitTouchEvent(0, XI_TouchEnd, 5, gfx::Point(30, 30), {});
auto touch_end = ui::BuildTouchEventFromXEvent(*scoped_xevent);
histogram_tester.ExpectTotalCount("Event.Latency.OS.TOUCH_RELEASED", 1);
}
#endif
@ -820,8 +819,7 @@ TEST(EventTest, EventLatencyOSMouseWheelHistogram) {
XButtonEvent* button_event = &(native_event.xbutton);
button_event->type = ButtonPress;
button_event->button = 4; // A valid wheel button number between min and max.
MouseWheelEvent mouse_ev(&native_event);
auto mouse_ev = ui::BuildMouseWheelEventFromXEvent(native_event);
histogram_tester.ExpectTotalCount("Event.Latency.OS.MOUSE_WHEEL", 1);
#endif
}

@ -10,7 +10,9 @@
#include "base/macros.h"
#include "ui/events/devices/x11/device_data_manager_x11.h"
#include "ui/events/event_constants.h"
#include "ui/events/keycodes/keyboard_code_conversion_x.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/events/x/events_x_utils.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/x/x11_types.h"

@ -23,6 +23,7 @@
#include "ui/events/test/events_test_utils_x11.h"
#include "ui/events/test/scoped_event_test_tick_clock.h"
#include "ui/events/x/events_x_utils.h"
#include "ui/events/x/x11_event_translation.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/x/x11.h"
@ -76,6 +77,11 @@ float ComputeRotationAngle(float twist) {
return rotation_angle;
}
std::string FlooredEventLocationString(const XEvent& xev) {
return gfx::ToFlooredPoint(gfx::PointF(ui::EventLocationFromXEvent(xev)))
.ToString();
}
} // namespace
class EventsXTest : public testing::Test {
@ -100,65 +106,65 @@ TEST_F(EventsXTest, ButtonEvents) {
gfx::Vector2d offset;
InitButtonEvent(&event, true, location, 1, 0);
EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromNative(&event));
EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, ui::EventFlagsFromNative(&event));
EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromXEvent(event));
EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, ui::EventFlagsFromXEvent(event));
EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON,
ui::GetChangedMouseButtonFlagsFromNative(&event));
EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative(&event)));
ui::GetChangedMouseButtonFlagsFromXEvent(event));
EXPECT_EQ(location, ui::EventLocationFromXEvent(event));
InitButtonEvent(&event, true, location, 2, Button1Mask | ShiftMask);
EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromNative(&event));
EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON |
ui::EF_SHIFT_DOWN,
ui::EventFlagsFromNative(&event));
EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromXEvent(event));
EXPECT_EQ(
ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON | ui::EF_SHIFT_DOWN,
ui::EventFlagsFromXEvent(event));
EXPECT_EQ(ui::EF_MIDDLE_MOUSE_BUTTON,
ui::GetChangedMouseButtonFlagsFromNative(&event));
EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative(&event)));
ui::GetChangedMouseButtonFlagsFromXEvent(event));
EXPECT_EQ(location, ui::EventLocationFromXEvent(event));
InitButtonEvent(&event, false, location, 3, 0);
EXPECT_EQ(ui::ET_MOUSE_RELEASED, ui::EventTypeFromNative(&event));
EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, ui::EventFlagsFromNative(&event));
EXPECT_EQ(ui::ET_MOUSE_RELEASED, ui::EventTypeFromXEvent(event));
EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, ui::EventFlagsFromXEvent(event));
EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON,
ui::GetChangedMouseButtonFlagsFromNative(&event));
EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative(&event)));
ui::GetChangedMouseButtonFlagsFromXEvent(event));
EXPECT_EQ(location, ui::EventLocationFromXEvent(event));
// Scroll up.
InitButtonEvent(&event, true, location, 4, 0);
EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromNative(&event));
EXPECT_EQ(0, ui::EventFlagsFromNative(&event));
EXPECT_EQ(ui::EF_NONE, ui::GetChangedMouseButtonFlagsFromNative(&event));
EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative(&event)));
offset = ui::GetMouseWheelOffset(&event);
EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromXEvent(event));
EXPECT_EQ(0, ui::EventFlagsFromXEvent(event));
EXPECT_EQ(ui::EF_NONE, ui::GetChangedMouseButtonFlagsFromXEvent(event));
EXPECT_EQ(location, ui::EventLocationFromXEvent(event));
offset = ui::GetMouseWheelOffsetFromXEvent(event);
EXPECT_GT(offset.y(), 0);
EXPECT_EQ(0, offset.x());
// Scroll down.
InitButtonEvent(&event, true, location, 5, 0);
EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromNative(&event));
EXPECT_EQ(0, ui::EventFlagsFromNative(&event));
EXPECT_EQ(ui::EF_NONE, ui::GetChangedMouseButtonFlagsFromNative(&event));
EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative(&event)));
offset = ui::GetMouseWheelOffset(&event);
EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromXEvent(event));
EXPECT_EQ(0, ui::EventFlagsFromXEvent(event));
EXPECT_EQ(ui::EF_NONE, ui::GetChangedMouseButtonFlagsFromXEvent(event));
EXPECT_EQ(location, ui::EventLocationFromXEvent(event));
offset = ui::GetMouseWheelOffsetFromXEvent(event);
EXPECT_LT(offset.y(), 0);
EXPECT_EQ(0, offset.x());
// Scroll left.
InitButtonEvent(&event, true, location, 6, 0);
EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromNative(&event));
EXPECT_EQ(0, ui::EventFlagsFromNative(&event));
EXPECT_EQ(ui::EF_NONE, ui::GetChangedMouseButtonFlagsFromNative(&event));
EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative(&event)));
offset = ui::GetMouseWheelOffset(&event);
EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromXEvent(event));
EXPECT_EQ(0, ui::EventFlagsFromXEvent(event));
EXPECT_EQ(ui::EF_NONE, ui::GetChangedMouseButtonFlagsFromXEvent(event));
EXPECT_EQ(location, ui::EventLocationFromXEvent(event));
offset = ui::GetMouseWheelOffsetFromXEvent(event);
EXPECT_EQ(0, offset.y());
EXPECT_GT(offset.x(), 0);
// Scroll right.
InitButtonEvent(&event, true, location, 7, 0);
EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromNative(&event));
EXPECT_EQ(0, ui::EventFlagsFromNative(&event));
EXPECT_EQ(ui::EF_NONE, ui::GetChangedMouseButtonFlagsFromNative(&event));
EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative(&event)));
offset = ui::GetMouseWheelOffset(&event);
EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromXEvent(event));
EXPECT_EQ(0, ui::EventFlagsFromXEvent(event));
EXPECT_EQ(ui::EF_NONE, ui::GetChangedMouseButtonFlagsFromXEvent(event));
EXPECT_EQ(location, ui::EventLocationFromXEvent(event));
offset = ui::GetMouseWheelOffsetFromXEvent(event);
EXPECT_EQ(0, offset.y());
EXPECT_LT(offset.x(), 0);
@ -170,12 +176,12 @@ TEST_F(EventsXTest, AvoidExtraEventsOnWheelRelease) {
gfx::Point location(5, 10);
InitButtonEvent(&event, true, location, 4, 0);
EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromNative(&event));
EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromXEvent(event));
// We should return ET_UNKNOWN for the release event instead of returning
// ET_MOUSEWHEEL; otherwise we'll scroll twice for each scrollwheel step.
InitButtonEvent(&event, false, location, 4, 0);
EXPECT_EQ(ui::ET_UNKNOWN, ui::EventTypeFromNative(&event));
EXPECT_EQ(ui::ET_UNKNOWN, ui::EventTypeFromXEvent(event));
// TODO(derat): Test XInput code.
}
@ -190,24 +196,20 @@ TEST_F(EventsXTest, EnterLeaveEvent) {
// Mouse enter events are converted to mouse move events to be consistent with
// the way views handle mouse enter. See comments for EnterNotify case in
// ui::EventTypeFromNative for more details.
EXPECT_EQ(ui::ET_MOUSE_MOVED, ui::EventTypeFromNative(&event));
EXPECT_TRUE(ui::EventFlagsFromNative(&event) & ui::EF_IS_SYNTHESIZED);
EXPECT_EQ(
"10,20",
gfx::ToFlooredPoint(ui::EventLocationFromNative(&event)).ToString());
EXPECT_EQ("110,120", ui::EventSystemLocationFromNative(&event).ToString());
// ui::EventTypeFromXEvent for more details.
EXPECT_EQ(ui::ET_MOUSE_MOVED, ui::EventTypeFromXEvent(event));
EXPECT_TRUE(ui::EventFlagsFromXEvent(event) & ui::EF_IS_SYNTHESIZED);
EXPECT_EQ("10,20", ui::EventLocationFromXEvent(event).ToString());
EXPECT_EQ("110,120", ui::EventSystemLocationFromXEvent(event).ToString());
event.xcrossing.type = LeaveNotify;
event.xcrossing.x = 30;
event.xcrossing.y = 40;
event.xcrossing.x_root = 230;
event.xcrossing.y_root = 240;
EXPECT_EQ(ui::ET_MOUSE_EXITED, ui::EventTypeFromNative(&event));
EXPECT_EQ(
"30,40",
gfx::ToFlooredPoint(ui::EventLocationFromNative(&event)).ToString());
EXPECT_EQ("230,240", ui::EventSystemLocationFromNative(&event).ToString());
EXPECT_EQ(ui::ET_MOUSE_EXITED, ui::EventTypeFromXEvent(event));
EXPECT_EQ("30,40", ui::EventLocationFromXEvent(event).ToString());
EXPECT_EQ("230,240", ui::EventSystemLocationFromXEvent(event).ToString());
}
TEST_F(EventsXTest, ClickCount) {
@ -220,17 +222,17 @@ TEST_F(EventsXTest, ClickCount) {
InitButtonEvent(&event, true, location, 1, 0);
{
event.xbutton.time = time_stamp.InMilliseconds() & UINT32_MAX;
MouseEvent mouseev(&event);
EXPECT_EQ(ui::ET_MOUSE_PRESSED, mouseev.type());
EXPECT_EQ(i, mouseev.GetClickCount());
auto mouseev = ui::BuildMouseEventFromXEvent(event);
EXPECT_EQ(ui::ET_MOUSE_PRESSED, mouseev->type());
EXPECT_EQ(i, mouseev->GetClickCount());
}
InitButtonEvent(&event, false, location, 1, 0);
{
event.xbutton.time = time_stamp.InMilliseconds();
MouseEvent mouseev(&event);
EXPECT_EQ(ui::ET_MOUSE_RELEASED, mouseev.type());
EXPECT_EQ(i, mouseev.GetClickCount());
auto mouseev = ui::BuildMouseEventFromXEvent(event);
EXPECT_EQ(ui::ET_MOUSE_RELEASED, mouseev->type());
EXPECT_EQ(i, mouseev->GetClickCount());
}
time_stamp += base::TimeDelta::FromMilliseconds(1);
}
@ -250,13 +252,11 @@ TEST_F(EventsXTest, TouchEventBasic) {
ui::ScopedXI2Event scoped_xevent;
scoped_xevent.InitTouchEvent(
0, XI_TouchBegin, 5, gfx::Point(10, 10), valuators);
EXPECT_EQ(ui::ET_TOUCH_PRESSED, ui::EventTypeFromNative(scoped_xevent));
EXPECT_EQ("10,10",
gfx::ToFlooredPoint(ui::EventLocationFromNative(scoped_xevent))
.ToString());
EXPECT_EQ(ui::ET_TOUCH_PRESSED, ui::EventTypeFromXEvent(*scoped_xevent));
EXPECT_EQ("10,10", FlooredEventLocationString(*scoped_xevent));
EXPECT_EQ(GetTouchIdFromXEvent(*scoped_xevent), 0);
PointerDetails pointer_details =
GetTouchPointerDetailsFromNative(scoped_xevent);
GetTouchPointerDetailsFromXEvent(*scoped_xevent);
EXPECT_FLOAT_EQ(ComputeRotationAngle(pointer_details.twist), 0.15f);
EXPECT_FLOAT_EQ(pointer_details.radius_x, 10.0f);
EXPECT_FLOAT_EQ(pointer_details.force, 0.1f);
@ -267,12 +267,10 @@ TEST_F(EventsXTest, TouchEventBasic) {
Valuator(DeviceDataManagerX11::DT_TOUCH_ORIENTATION, 0.5f));
scoped_xevent.InitTouchEvent(
0, XI_TouchUpdate, 5, gfx::Point(20, 20), valuators);
EXPECT_EQ(ui::ET_TOUCH_MOVED, ui::EventTypeFromNative(scoped_xevent));
EXPECT_EQ("20,20",
gfx::ToFlooredPoint(ui::EventLocationFromNative(scoped_xevent))
.ToString());
EXPECT_EQ(ui::ET_TOUCH_MOVED, ui::EventTypeFromXEvent(*scoped_xevent));
EXPECT_EQ("20,20", FlooredEventLocationString(*scoped_xevent));
EXPECT_EQ(GetTouchIdFromXEvent(*scoped_xevent), 0);
pointer_details = GetTouchPointerDetailsFromNative(scoped_xevent);
pointer_details = GetTouchPointerDetailsFromXEvent(*scoped_xevent);
EXPECT_FLOAT_EQ(ComputeRotationAngle(pointer_details.twist), 0.25f);
EXPECT_FLOAT_EQ(pointer_details.radius_x, 10.0f);
EXPECT_FLOAT_EQ(pointer_details.force, 0.1f);
@ -285,12 +283,10 @@ TEST_F(EventsXTest, TouchEventBasic) {
valuators.push_back(Valuator(DeviceDataManagerX11::DT_TOUCH_PRESSURE, 500));
scoped_xevent.InitTouchEvent(
0, XI_TouchBegin, 6, gfx::Point(200, 200), valuators);
EXPECT_EQ(ui::ET_TOUCH_PRESSED, ui::EventTypeFromNative(scoped_xevent));
EXPECT_EQ("200,200",
gfx::ToFlooredPoint(ui::EventLocationFromNative(scoped_xevent))
.ToString());
EXPECT_EQ(ui::ET_TOUCH_PRESSED, ui::EventTypeFromXEvent(*scoped_xevent));
EXPECT_EQ("200,200", FlooredEventLocationString(*scoped_xevent));
EXPECT_EQ(GetTouchIdFromXEvent(*scoped_xevent), 1);
pointer_details = GetTouchPointerDetailsFromNative(scoped_xevent);
pointer_details = GetTouchPointerDetailsFromXEvent(*scoped_xevent);
EXPECT_FLOAT_EQ(ComputeRotationAngle(pointer_details.twist), 0.45f);
EXPECT_FLOAT_EQ(pointer_details.radius_x, 50.0f);
EXPECT_FLOAT_EQ(pointer_details.force, 0.5f);
@ -301,12 +297,10 @@ TEST_F(EventsXTest, TouchEventBasic) {
valuators.push_back(Valuator(DeviceDataManagerX11::DT_TOUCH_PRESSURE, 50));
scoped_xevent.InitTouchEvent(
0, XI_TouchEnd, 5, gfx::Point(30, 30), valuators);
EXPECT_EQ(ui::ET_TOUCH_RELEASED, ui::EventTypeFromNative(scoped_xevent));
EXPECT_EQ("30,30",
gfx::ToFlooredPoint(ui::EventLocationFromNative(scoped_xevent))
.ToString());
EXPECT_EQ(ui::ET_TOUCH_RELEASED, ui::EventTypeFromXEvent(*scoped_xevent));
EXPECT_EQ("30,30", FlooredEventLocationString(*scoped_xevent));
EXPECT_EQ(GetTouchIdFromXEvent(*scoped_xevent), 0);
pointer_details = GetTouchPointerDetailsFromNative(scoped_xevent);
pointer_details = GetTouchPointerDetailsFromXEvent(*scoped_xevent);
EXPECT_FLOAT_EQ(ComputeRotationAngle(pointer_details.twist), 0.25f);
EXPECT_FLOAT_EQ(pointer_details.radius_x, 10.0f);
EXPECT_FLOAT_EQ(pointer_details.force, 0.f);
@ -317,12 +311,10 @@ TEST_F(EventsXTest, TouchEventBasic) {
valuators.push_back(Valuator(DeviceDataManagerX11::DT_TOUCH_MAJOR, 50));
scoped_xevent.InitTouchEvent(
0, XI_TouchEnd, 6, gfx::Point(200, 200), valuators);
EXPECT_EQ(ui::ET_TOUCH_RELEASED, ui::EventTypeFromNative(scoped_xevent));
EXPECT_EQ("200,200",
gfx::ToFlooredPoint(ui::EventLocationFromNative(scoped_xevent))
.ToString());
EXPECT_EQ(ui::ET_TOUCH_RELEASED, ui::EventTypeFromXEvent(*scoped_xevent));
EXPECT_EQ("200,200", FlooredEventLocationString(*scoped_xevent));
EXPECT_EQ(GetTouchIdFromXEvent(*scoped_xevent), 1);
pointer_details = GetTouchPointerDetailsFromNative(scoped_xevent);
pointer_details = GetTouchPointerDetailsFromXEvent(*scoped_xevent);
EXPECT_FLOAT_EQ(ComputeRotationAngle(pointer_details.twist), 0.45f);
EXPECT_FLOAT_EQ(pointer_details.radius_x, 25.0f);
EXPECT_FLOAT_EQ(pointer_details.force, 0.f);
@ -349,13 +341,13 @@ TEST_F(EventsXTest, TouchEventNotRemovingFromNativeMapping) {
ui::ScopedXI2Event xpress0;
xpress0.InitTouchEvent(kDeviceId, XI_TouchBegin, kTrackingId,
gfx::Point(10, 10), valuators);
std::unique_ptr<ui::TouchEvent> upress0(new ui::TouchEvent(xpress0));
auto upress0 = ui::BuildTouchEventFromXEvent(*xpress0);
EXPECT_EQ(kDeviceId, GetTouchIdForTrackingId(kTrackingId));
ui::ScopedXI2Event xpress1;
xpress1.InitTouchEvent(kDeviceId, XI_TouchBegin, kTrackingId,
gfx::Point(20, 20), valuators);
ui::TouchEvent upress1(xpress1);
auto upress1 = ui::BuildTouchEventFromXEvent(*xpress1);
EXPECT_EQ(kDeviceId, GetTouchIdForTrackingId(kTrackingId));
// The second touch release should clear the mapping from the
@ -363,16 +355,14 @@ TEST_F(EventsXTest, TouchEventNotRemovingFromNativeMapping) {
ui::ScopedXI2Event xrelease1;
xrelease1.InitTouchEvent(kDeviceId, XI_TouchEnd, kTrackingId,
gfx::Point(10, 10), valuators);
{
ui::TouchEvent urelease1(xrelease1);
}
{ auto urelease1 = ui::BuildTouchEventFromXEvent(*xrelease1); }
EXPECT_EQ(-1, GetTouchIdForTrackingId(kTrackingId));
}
// Copied events should not remove native touch id mappings, as this causes a
// crash (crbug.com/467102). Copied events do not contain a proper
// PlatformEvent and should not attempt to access it.
TEST_F(EventsXTest, CopiedTouchEventNotRemovingFromNativeMapping) {
TEST_F(EventsXTest, CopiedTouchEventNotRemovingFromXEventMapping) {
std::vector<int> devices;
devices.push_back(0);
ui::SetUpTouchDevicesForTest(devices);
@ -381,11 +371,11 @@ TEST_F(EventsXTest, CopiedTouchEventNotRemovingFromNativeMapping) {
// Create a release event which has a native touch id mapping.
ui::ScopedXI2Event xrelease0;
xrelease0.InitTouchEvent(0, XI_TouchEnd, 0, gfx::Point(10, 10), valuators);
ui::TouchEvent urelease0(xrelease0);
auto urelease0 = ui::BuildTouchEventFromXEvent(*xrelease0);
{
// When the copy is destructed it should not attempt to remove the mapping.
// Exiting this scope should not cause a crash.
ui::TouchEvent copy = urelease0;
TouchEvent copy = *urelease0;
}
}
@ -412,7 +402,7 @@ TEST_F(EventsXTest, DisableKeyboard) {
ui::ET_KEY_PRESSED,
ui::VKEY_A,
0);
EXPECT_EQ(ui::ET_UNKNOWN, ui::EventTypeFromNative(xev));
EXPECT_EQ(ui::ET_UNKNOWN, ui::EventTypeFromXEvent(*xev));
// The B key is allowed as an exception, and should return KEY_PRESSED.
xev.InitGenericKeyEvent(master_device_id,
@ -420,7 +410,7 @@ TEST_F(EventsXTest, DisableKeyboard) {
ui::ET_KEY_PRESSED,
ui::VKEY_B,
0);
EXPECT_EQ(ui::ET_KEY_PRESSED, ui::EventTypeFromNative(xev));
EXPECT_EQ(ui::ET_KEY_PRESSED, ui::EventTypeFromXEvent(*xev));
// Both A and B are allowed on an unblocked keyboard device.
xev.InitGenericKeyEvent(master_device_id,
@ -428,13 +418,13 @@ TEST_F(EventsXTest, DisableKeyboard) {
ui::ET_KEY_PRESSED,
ui::VKEY_A,
0);
EXPECT_EQ(ui::ET_KEY_PRESSED, ui::EventTypeFromNative(xev));
EXPECT_EQ(ui::ET_KEY_PRESSED, ui::EventTypeFromXEvent(*xev));
xev.InitGenericKeyEvent(master_device_id,
other_device_id,
ui::ET_KEY_PRESSED,
ui::VKEY_B,
0);
EXPECT_EQ(ui::ET_KEY_PRESSED, ui::EventTypeFromNative(xev));
EXPECT_EQ(ui::ET_KEY_PRESSED, ui::EventTypeFromXEvent(*xev));
device_data_manager->EnableDevice(blocked_device_id);
device_data_manager->SetDisabledKeyboardAllowedKeys(nullptr);
@ -445,7 +435,7 @@ TEST_F(EventsXTest, DisableKeyboard) {
ui::ET_KEY_PRESSED,
ui::VKEY_A,
0);
EXPECT_EQ(ui::ET_KEY_PRESSED, ui::EventTypeFromNative(xev));
EXPECT_EQ(ui::ET_KEY_PRESSED, ui::EventTypeFromXEvent(*xev));
}
// Verifies that the type of events from a disabled mouse is ET_UNKNOWN.
@ -465,17 +455,17 @@ TEST_F(EventsXTest, DisableMouse) {
ScopedXI2Event xev;
xev.InitGenericButtonEvent(blocked_device_id, ET_MOUSE_PRESSED, gfx::Point(),
EF_LEFT_MOUSE_BUTTON);
EXPECT_EQ(ui::ET_UNKNOWN, ui::EventTypeFromNative(xev));
EXPECT_EQ(ui::ET_UNKNOWN, ui::EventTypeFromXEvent(*xev));
xev.InitGenericButtonEvent(other_device_id, ET_MOUSE_PRESSED, gfx::Point(),
EF_LEFT_MOUSE_BUTTON);
EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromNative(xev));
EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromXEvent(*xev));
device_data_manager->EnableDevice(blocked_device_id);
xev.InitGenericButtonEvent(blocked_device_id, ET_MOUSE_PRESSED, gfx::Point(),
EF_LEFT_MOUSE_BUTTON);
EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromNative(xev));
EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromXEvent(*xev));
}
#if !defined(OS_CHROMEOS)
@ -490,12 +480,12 @@ TEST_F(EventsXTest, ImeFabricatedKeyEvents) {
for (int is_char = 0; is_char < 2; ++is_char) {
XEvent x_event;
InitKeyEvent(display, &x_event, true, 0, state);
ui::KeyEvent key_event(&x_event);
auto key_event = ui::BuildKeyEventFromXEvent(x_event);
if (is_char) {
KeyEventTestApi test_event(&key_event);
KeyEventTestApi test_event(key_event.get());
test_event.set_is_char(true);
}
EXPECT_TRUE(key_event.flags() & ui::EF_IME_FABRICATED_KEY);
EXPECT_TRUE(key_event->flags() & ui::EF_IME_FABRICATED_KEY);
}
}
@ -507,12 +497,12 @@ TEST_F(EventsXTest, ImeFabricatedKeyEvents) {
for (int is_char = 0; is_char < 2; ++is_char) {
XEvent x_event;
InitKeyEvent(display, &x_event, true, 0, state);
ui::KeyEvent key_event(&x_event);
auto key_event = ui::BuildKeyEventFromXEvent(x_event);
if (is_char) {
KeyEventTestApi test_event(&key_event);
KeyEventTestApi test_event(key_event.get());
test_event.set_is_char(true);
}
EXPECT_FALSE(key_event.flags() & ui::EF_IME_FABRICATED_KEY);
EXPECT_FALSE(key_event->flags() & ui::EF_IME_FABRICATED_KEY);
}
}
}
@ -528,7 +518,7 @@ TEST_F(EventsXTest, IgnoresMotionEventForMouseWheelScroll) {
xev.InitScrollEvent(device_id, 1, 2, 3, 4, 1);
// We shouldn't produce a mouse move event on a mouse wheel
// scroll. These events are only produced for some mice.
EXPECT_EQ(ui::ET_UNKNOWN, ui::EventTypeFromNative(xev));
EXPECT_EQ(ui::ET_UNKNOWN, ui::EventTypeFromXEvent(*xev));
}
namespace {
@ -549,14 +539,14 @@ TEST_F(EventsXTest, TimestampRolloverAndAdjustWhenDecreasing) {
ResetTimestampRolloverCountersForTesting();
event.xbutton.time = 0xFFFFFFFF;
EXPECT_EQ(TimeTicksFromMillis(0xFFFFFFFF), ui::EventTimeFromNative(&event));
EXPECT_EQ(TimeTicksFromMillis(0xFFFFFFFF), ui::EventTimeFromXEvent(event));
clock.SetNowTicks(TimeTicksFromMillis(0x100000007));
ResetTimestampRolloverCountersForTesting();
event.xbutton.time = 3;
EXPECT_EQ(TimeTicksFromMillis(0x100000000 + 3),
ui::EventTimeFromNative(&event));
ui::EventTimeFromXEvent(event));
}
TEST_F(EventsXTest, NoTimestampRolloverWhenMonotonicIncreasing) {
@ -568,15 +558,15 @@ TEST_F(EventsXTest, NoTimestampRolloverWhenMonotonicIncreasing) {
ResetTimestampRolloverCountersForTesting();
event.xbutton.time = 6;
EXPECT_EQ(TimeTicksFromMillis(6), ui::EventTimeFromNative(&event));
EXPECT_EQ(TimeTicksFromMillis(6), ui::EventTimeFromXEvent(event));
event.xbutton.time = 7;
EXPECT_EQ(TimeTicksFromMillis(7), ui::EventTimeFromNative(&event));
EXPECT_EQ(TimeTicksFromMillis(7), ui::EventTimeFromXEvent(event));
clock.SetNowTicks(TimeTicksFromMillis(0x100000005));
ResetTimestampRolloverCountersForTesting();
event.xbutton.time = 0xFFFFFFFF;
EXPECT_EQ(TimeTicksFromMillis(0xFFFFFFFF), ui::EventTimeFromNative(&event));
EXPECT_EQ(TimeTicksFromMillis(0xFFFFFFFF), ui::EventTimeFromXEvent(event));
}
} // namespace ui

@ -24,7 +24,7 @@ std::unique_ptr<KeyEvent> CreateKeyEvent(EventType event_type,
// in KeyEvent::ApplyLayout() which makes it possible for CrOS/Linux, for
// example, to support host system keyboard layouts.
#if defined(USE_OZONE)
auto event = std::make_unique<KeyEvent>(event_type, key_code, event_flags);
return std::make_unique<KeyEvent>(event_type, key_code, event_flags);
#else
DomCode dom_code = CodeFromXEvent(&xev);
DomKey dom_key = GetDomKeyFromXEvent(&xev);
@ -32,11 +32,20 @@ std::unique_ptr<KeyEvent> CreateKeyEvent(EventType event_type,
ValidateEventTimeClock(&timestamp);
auto event = std::make_unique<KeyEvent>(event_type, key_code, dom_code,
event_flags, dom_key, timestamp);
#endif
DCHECK(event);
event->SetProperties(GetEventPropertiesFromXEvent(event_type, xev));
event->InitializeNative();
return event;
#endif
}
void SetEventSourceDeviceId(MouseEvent* event, const XEvent& xev) {
DCHECK(event);
if (xev.type == GenericEvent) {
XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
event->set_source_device_id(xiev->sourceid);
}
}
std::unique_ptr<MouseEvent> CreateMouseEvent(EventType type,
@ -56,6 +65,9 @@ std::unique_ptr<MouseEvent> CreateMouseEvent(EventType type,
details);
DCHECK(event);
SetEventSourceDeviceId(event.get(), xev);
event->SetProperties(GetEventPropertiesFromXEvent(type, xev));
event->InitializeNative();
return event;
}
@ -69,6 +81,7 @@ std::unique_ptr<MouseWheelEvent> CreateMouseWheelEvent(const XEvent& xev) {
EventFlagsFromXEvent(xev), button_flags);
DCHECK(event);
event->InitializeNative();
return event;
}
@ -79,7 +92,6 @@ std::unique_ptr<TouchEvent> CreateTouchEvent(EventType type,
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.
@ -106,7 +118,12 @@ std::unique_ptr<ScrollEvent> CreateScrollEvent(EventType type,
y_offset_ordinal, finger_count);
DCHECK(event);
return event;
// We need to filter zero scroll offset here. Because MouseWheelEventQueue
// assumes we'll never get a zero scroll offset event and we need delta to
// determine which element to scroll on phaseBegan.
return (event->x_offset() != 0.0 || event->y_offset() != 0.0)
? std::move(event)
: nullptr;
}
// Translates XI2 XEvent into a ui::Event.
@ -120,6 +137,8 @@ std::unique_ptr<ui::Event> TranslateFromXI2Event(const XEvent& xev) {
case ET_MOUSE_RELEASED:
case ET_MOUSE_MOVED:
case ET_MOUSE_DRAGGED:
case ET_MOUSE_ENTERED:
case ET_MOUSE_EXITED:
return CreateMouseEvent(event_type, xev);
case ET_MOUSEWHEEL:
return CreateMouseWheelEvent(xev);
@ -145,6 +164,7 @@ std::unique_ptr<Event> TranslateFromXEvent(const XEvent& xev) {
switch (xev.type) {
case LeaveNotify:
case EnterNotify:
case MotionNotify:
return CreateMouseEvent(event_type, xev);
case KeyPress:
case KeyRelease:
@ -176,7 +196,16 @@ std::unique_ptr<Event> TranslateFromXEvent(const XEvent& xev) {
// Translates a XEvent into a ui::Event.
std::unique_ptr<Event> BuildEventFromXEvent(const XEvent& xev) {
return TranslateFromXEvent(xev);
auto event = TranslateFromXEvent(xev);
if (event) {
#if defined(USE_X11)
// TODO(crbug.com/965991): Remove once PlatformEvent migration is done.
ui::ComputeEventLatencyOS(const_cast<XEvent*>(&xev));
#else
ui::ComputeEventLatencyOS(event.get());
#endif
}
return event;
}
// Convenience function that translates XEvent into ui::KeyEvent
@ -230,15 +259,18 @@ Event::Properties GetEventPropertiesFromXEvent(EventType type,
// IBus-gtk specific flags
uint8_t ibus_flags = (xev.xkey.state >> kPropertyKeyboardIBusFlagOffset) &
kPropertyKeyboardIBusFlagMask;
properties.emplace(kPropertyKeyboardIBusFlag, Values{ibus_flags});
if (ibus_flags)
properties.emplace(kPropertyKeyboardIBusFlag, Values{ibus_flags});
} else if (type == ET_MOUSE_EXITED) {
// NotifyVirtual events are created for intermediate windows that the
// pointer crosses through. These occur when middle clicking.
// Change these into mouse move events.
bool crossing_intermediate_window = xev.xcrossing.detail == NotifyVirtual;
properties.emplace(kPropertyMouseCrossedIntermediateWindow,
crossing_intermediate_window);
if (crossing_intermediate_window) {
properties.emplace(kPropertyMouseCrossedIntermediateWindow,
crossing_intermediate_window);
}
}
return properties;
}

@ -1013,6 +1013,7 @@ jumbo_source_set("test_support") {
}
if (use_x11) {
deps += [
"//ui/events/platform/x11",
"//ui/events/x",
"//ui/gfx/x",
]