Commit 8169ffc3 authored by Maksim Sisov's avatar Maksim Sisov Committed by Commit Bot

X11: move x11 specific calls out of ui_controls

This is required to allow Ozone/X11 later reuse that.

No functional changes are made.

Bug: 1134495
Change-Id: I7cf66fd0fd01d3237e3d3c763cc01bd1c00c26a7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2445109
Commit-Queue: Maksim Sisov (GMT+3) <msisov@igalia.com>
Reviewed-by: default avatarThomas Anderson <thomasanderson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#813634}
parent d1d89d7d
......@@ -118,10 +118,15 @@ source_set("test_support") {
sources = [
"test/x11_property_change_waiter.cc",
"test/x11_property_change_waiter.h",
"test/x11_ui_controls_test_helper.cc",
"test/x11_ui_controls_test_helper.h",
]
deps = [
":x",
"//ui/base:test_support",
"//ui/events:platform_event",
"//ui/events:test_support",
"//ui/events/platform/x11",
"//ui/gfx/x",
]
......
// Copyright 2020 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/base/x/test/x11_ui_controls_test_helper.h"
#include "base/bind.h"
#include "base/check_op.h"
#include "base/location.h"
#include "ui/base/x/x11_util.h"
#include "ui/events/keycodes/keyboard_code_conversion_x.h"
#include "ui/events/test/x11_event_waiter.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/x/keysyms/keysyms.h"
#include "ui/gfx/x/x11_types.h"
#include "ui/gfx/x/xproto.h"
#include "ui/gfx/x/xproto_util.h"
namespace ui {
namespace {
using ui_controls::DOWN;
using ui_controls::LEFT;
using ui_controls::MIDDLE;
using ui_controls::MouseButton;
using ui_controls::RIGHT;
using ui_controls::UP;
// Mask of the buttons currently down.
unsigned button_down_mask = 0;
// The root and time fields of |xevent| may be modified.
template <typename T>
void PostEventToWindowTreeHost(gfx::AcceleratedWidget widget, T* xevent) {
auto* connection = x11::Connection::Get();
x11::Window xwindow = static_cast<x11::Window>(widget);
xevent->event = xwindow;
xevent->root = connection->default_root();
xevent->time = x11::Time::CurrentTime;
x11::SendEvent(*xevent, xwindow, x11::EventMask::NoEvent);
connection->Flush();
}
} // namespace
X11UIControlsTestHelper::X11UIControlsTestHelper()
: connection_(x11::Connection::Get()),
x_root_window_(ui::GetX11RootWindow()),
x_window_(
ui::CreateDummyWindow("Chromium X11UIControlsTestHelper Window")) {}
X11UIControlsTestHelper::~X11UIControlsTestHelper() {
connection_->DestroyWindow({x_window_});
}
unsigned X11UIControlsTestHelper::ButtonDownMask() const {
return button_down_mask;
}
void X11UIControlsTestHelper::SendKeyPressEvent(gfx::AcceleratedWidget widget,
ui::KeyboardCode key,
bool control,
bool shift,
bool alt,
bool command,
base::OnceClosure closure) {
x11::KeyEvent xevent;
xevent.opcode = x11::KeyEvent::Press;
if (control) {
SetKeycodeAndSendThenMask(widget, &xevent, XK_Control_L,
x11::KeyButMask::Control);
}
if (shift)
SetKeycodeAndSendThenMask(widget, &xevent, XK_Shift_L,
x11::KeyButMask::Shift);
if (alt)
SetKeycodeAndSendThenMask(widget, &xevent, XK_Alt_L, x11::KeyButMask::Mod1);
xevent.detail = x11::Connection::Get()->KeysymToKeycode(
static_cast<x11::KeySym>(ui::XKeysymForWindowsKeyCode(key, shift)));
PostEventToWindowTreeHost(widget, &xevent);
// Send key release events.
xevent.opcode = x11::KeyEvent::Release;
PostEventToWindowTreeHost(widget, &xevent);
if (alt)
UnmaskAndSetKeycodeThenSend(widget, &xevent, x11::KeyButMask::Mod1,
XK_Alt_L);
if (shift)
UnmaskAndSetKeycodeThenSend(widget, &xevent, x11::KeyButMask::Shift,
XK_Shift_L);
if (control)
UnmaskAndSetKeycodeThenSend(widget, &xevent, x11::KeyButMask::Control,
XK_Control_L);
DCHECK_EQ(xevent.state, x11::KeyButMask{});
RunClosureAfterAllPendingUIEvents(std::move(closure));
return;
}
void X11UIControlsTestHelper::SendMouseMotionNotifyEvent(
gfx::AcceleratedWidget widget,
const gfx::Point& mouse_loc,
const gfx::Point& mouse_root_loc,
base::OnceClosure closure) {
x11::MotionNotifyEvent xevent{
.root_x = mouse_root_loc.x(),
.root_y = mouse_root_loc.y(),
.event_x = mouse_loc.x(),
.event_y = mouse_loc.y(),
.state = static_cast<x11::KeyButMask>(button_down_mask),
.same_screen = true,
};
// RootWindow will take care of other necessary fields.
PostEventToWindowTreeHost(widget, &xevent);
RunClosureAfterAllPendingUIEvents(std::move(closure));
return;
}
void X11UIControlsTestHelper::SendMouseEvent(gfx::AcceleratedWidget widget,
MouseButton type,
int button_state,
int accelerator_state,
const gfx::Point& mouse_loc,
const gfx::Point& mouse_root_loc,
base::OnceClosure closure) {
x11::ButtonEvent xevent;
xevent.event_x = mouse_loc.x();
xevent.event_y = mouse_loc.y();
xevent.root_x = mouse_root_loc.x();
xevent.root_y = mouse_root_loc.y();
switch (type) {
case LEFT:
xevent.detail = static_cast<x11::Button>(1);
xevent.state = x11::KeyButMask::Button1;
break;
case MIDDLE:
xevent.detail = static_cast<x11::Button>(2);
xevent.state = x11::KeyButMask::Button2;
break;
case RIGHT:
xevent.detail = static_cast<x11::Button>(3);
xevent.state = x11::KeyButMask::Button3;
break;
}
// Process accelerator key state.
if (accelerator_state & ui_controls::kShift)
xevent.state = xevent.state | x11::KeyButMask::Shift;
if (accelerator_state & ui_controls::kControl)
xevent.state = xevent.state | x11::KeyButMask::Control;
if (accelerator_state & ui_controls::kAlt)
xevent.state = xevent.state | x11::KeyButMask::Mod1;
if (accelerator_state & ui_controls::kCommand)
xevent.state = xevent.state | x11::KeyButMask::Mod4;
// RootWindow will take care of other necessary fields.
if (button_state & DOWN) {
xevent.opcode = x11::ButtonEvent::Press;
PostEventToWindowTreeHost(widget, &xevent);
button_down_mask |= static_cast<int>(xevent.state);
}
if (button_state & UP) {
xevent.opcode = x11::ButtonEvent::Release;
PostEventToWindowTreeHost(widget, &xevent);
int state = static_cast<int>(xevent.state);
button_down_mask = (button_down_mask | state) ^ state;
}
RunClosureAfterAllPendingUIEvents(std::move(closure));
return;
}
void X11UIControlsTestHelper::RunClosureAfterAllPendingUIEvents(
base::OnceClosure closure) {
if (closure.is_null())
return;
ui::XEventWaiter::Create(x_window_, std::move(closure));
}
void X11UIControlsTestHelper::SetKeycodeAndSendThenMask(
gfx::AcceleratedWidget widget,
x11::KeyEvent* xevent,
KeySym keysym,
x11::KeyButMask mask) {
xevent->detail =
x11::Connection::Get()->KeysymToKeycode(static_cast<x11::KeySym>(keysym));
PostEventToWindowTreeHost(widget, xevent);
xevent->state = xevent->state | mask;
}
void X11UIControlsTestHelper::UnmaskAndSetKeycodeThenSend(
gfx::AcceleratedWidget widget,
x11::KeyEvent* xevent,
x11::KeyButMask mask,
KeySym keysym) {
xevent->state = static_cast<x11::KeyButMask>(
static_cast<uint32_t>(xevent->state) ^ static_cast<uint32_t>(mask));
xevent->detail =
x11::Connection::Get()->KeysymToKeycode(static_cast<x11::KeySym>(keysym));
PostEventToWindowTreeHost(widget, xevent);
}
} // namespace ui
// Copyright 2020 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_BASE_X_TEST_X11_UI_CONTROLS_TEST_HELPER_H_
#define UI_BASE_X_TEST_X11_UI_CONTROLS_TEST_HELPER_H_
#include "ui/gfx/native_widget_types.h"
#include "base/component_export.h"
#include "ui/base/test/ui_controls_aura.h"
#include "ui/gfx/x/connection.h"
#include "ui/gfx/x/x11.h"
namespace gfx {
class Point;
}
namespace ui {
class COMPONENT_EXPORT(UI_BASE_X) X11UIControlsTestHelper {
public:
X11UIControlsTestHelper();
X11UIControlsTestHelper(const X11UIControlsTestHelper&) = delete;
X11UIControlsTestHelper& operator=(const X11UIControlsTestHelper&) = delete;
~X11UIControlsTestHelper();
unsigned ButtonDownMask() const;
// Sends key press event and executes |closure| when done.
void SendKeyPressEvent(gfx::AcceleratedWidget widget,
ui::KeyboardCode key,
bool control,
bool shift,
bool alt,
bool command,
base::OnceClosure closure);
// Sends mouse motion notify event and executes |closure| when done.
void SendMouseMotionNotifyEvent(gfx::AcceleratedWidget widget,
const gfx::Point& mouse_loc,
const gfx::Point& mouse_root_loc,
base::OnceClosure closure);
// Sends mouse event and executes |closure| when done.
void SendMouseEvent(gfx::AcceleratedWidget widget,
ui_controls::MouseButton type,
int button_state,
int accelerator_state,
const gfx::Point& mouse_loc,
const gfx::Point& mouse_root_loc,
base::OnceClosure closure);
void RunClosureAfterAllPendingUIEvents(base::OnceClosure closure);
private:
void SetKeycodeAndSendThenMask(gfx::AcceleratedWidget widget,
x11::KeyEvent* xevent,
KeySym keysym,
x11::KeyButMask mask);
void UnmaskAndSetKeycodeThenSend(gfx::AcceleratedWidget widget,
x11::KeyEvent* xevent,
x11::KeyButMask mask,
KeySym keysym);
// Our X11 state.
x11::Connection* connection_ = nullptr;
x11::Window x_root_window_;
// Input-only window used for events.
x11::Window x_window_;
};
} // namespace ui
#endif // UI_BASE_X_TEST_X11_UI_CONTROLS_TEST_HELPER_H_
......@@ -1009,6 +1009,7 @@ source_set("test_support") {
"test/ui_controls_factory_desktop_aurax11.cc",
"test/ui_controls_factory_desktop_aurax11.h",
]
deps += [ "//ui/base/x:test_support" ]
}
}
if (use_x11) {
......
......@@ -17,17 +17,9 @@
#include "ui/aura/env.h"
#include "ui/aura/test/aura_test_utils.h"
#include "ui/aura/test/ui_controls_factory_aura.h"
#include "ui/aura/test/x11_event_sender.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/test/ui_controls_aura.h"
#include "ui/base/x/x11_util.h"
#include "ui/events/keycodes/keyboard_code_conversion_x.h"
#include "ui/events/test/x11_event_waiter.h"
#include "ui/gfx/x/connection.h"
#include "ui/gfx/x/keysyms/keysyms.h"
#include "ui/gfx/x/x11.h"
#include "ui/gfx/x/x11_types.h"
#include "ui/gfx/x/xproto.h"
#include "ui/base/x/test/x11_ui_controls_test_helper.h"
#include "ui/views/test/test_desktop_screen_x11.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h"
......@@ -43,18 +35,10 @@ using ui_controls::RIGHT;
using ui_controls::UIControlsAura;
using ui_controls::UP;
// Mask of the buttons currently down.
unsigned button_down_mask = 0;
class UIControlsDesktopX11 : public UIControlsAura {
public:
UIControlsDesktopX11()
: connection_(x11::Connection::Get()),
x_root_window_(ui::GetX11RootWindow()),
x_window_(
ui::CreateDummyWindow("Chromium UIControlsDesktopX11 Window")) {}
~UIControlsDesktopX11() override { connection_->DestroyWindow({x_window_}); }
UIControlsDesktopX11() = default;
~UIControlsDesktopX11() override = default;
bool SendKeyPress(gfx::NativeWindow window,
ui::KeyboardCode key,
......@@ -77,39 +61,9 @@ class UIControlsDesktopX11 : public UIControlsAura {
DCHECK(!command); // No command key on Aura
aura::WindowTreeHost* host = window->GetHost();
x11::KeyEvent xevent;
xevent.opcode = x11::KeyEvent::Press;
if (control) {
SetKeycodeAndSendThenMask(host, &xevent, XK_Control_L,
x11::KeyButMask::Control);
}
if (shift)
SetKeycodeAndSendThenMask(host, &xevent, XK_Shift_L,
x11::KeyButMask::Shift);
if (alt)
SetKeycodeAndSendThenMask(host, &xevent, XK_Alt_L, x11::KeyButMask::Mod1);
xevent.detail = x11::Connection::Get()->KeysymToKeycode(
static_cast<x11::KeySym>(ui::XKeysymForWindowsKeyCode(key, shift)));
aura::test::PostEventToWindowTreeHost(host, &xevent);
// Send key release events.
xevent.opcode = x11::KeyEvent::Release;
aura::test::PostEventToWindowTreeHost(host, &xevent);
if (alt) {
UnmaskAndSetKeycodeThenSend(host, &xevent, x11::KeyButMask::Mod1,
XK_Alt_L);
}
if (shift) {
UnmaskAndSetKeycodeThenSend(host, &xevent, x11::KeyButMask::Shift,
XK_Shift_L);
}
if (control) {
UnmaskAndSetKeycodeThenSend(host, &xevent, x11::KeyButMask::Control,
XK_Control_L);
}
DCHECK_EQ(xevent.state, x11::KeyButMask{});
RunClosureAfterAllPendingUIEvents(std::move(closure));
x11_ui_controls_test_helper_.SendKeyPressEvent(host->GetAcceleratedWidget(),
key, control, shift, alt,
command, std::move(closure));
return true;
}
......@@ -139,21 +93,20 @@ class UIControlsDesktopX11 : public UIControlsAura {
DCHECK_EQ(screen, display::Screen::GetScreen());
screen->set_cursor_screen_point(gfx::Point(screen_x, screen_y));
if (root_location != root_current_location && button_down_mask == 0) {
if (root_location != root_current_location &&
x11_ui_controls_test_helper_.ButtonDownMask() == 0) {
// Move the cursor because EnterNotify/LeaveNotify are generated with the
// current mouse position as a result of XGrabPointer()
root_window->MoveCursorTo(root_location);
} else {
x11::MotionNotifyEvent xevent{
.event_x = root_location.x(),
.event_y = root_location.y(),
.state = static_cast<x11::KeyButMask>(button_down_mask),
.same_screen = true,
};
// RootWindow will take care of other necessary fields.
aura::test::PostEventToWindowTreeHost(host, &xevent);
}
RunClosureAfterAllPendingUIEvents(std::move(closure));
gfx::Point screen_point(root_location);
host->ConvertDIPToScreenInPixels(&screen_point);
x11_ui_controls_test_helper_.SendMouseMotionNotifyEvent(
host->GetAcceleratedWidget(), root_location, screen_point,
std::move(closure));
}
x11_ui_controls_test_helper_.RunClosureAfterAllPendingUIEvents(
std::move(closure));
return true;
}
bool SendMouseEvents(MouseButton type,
......@@ -166,63 +119,23 @@ class UIControlsDesktopX11 : public UIControlsAura {
int button_state,
base::OnceClosure closure,
int accelerator_state) override {
x11::ButtonEvent xevent;
gfx::Point mouse_loc = aura::Env::GetInstance()->last_mouse_location();
aura::Window* root_window = RootWindowForPoint(mouse_loc);
aura::client::ScreenPositionClient* screen_position_client =
aura::client::GetScreenPositionClient(root_window);
if (screen_position_client)
screen_position_client->ConvertPointFromScreen(root_window, &mouse_loc);
xevent.event_x = mouse_loc.x();
xevent.event_y = mouse_loc.y();
switch (type) {
case LEFT:
xevent.detail = static_cast<x11::Button>(1);
xevent.state = x11::KeyButMask::Button1;
break;
case MIDDLE:
xevent.detail = static_cast<x11::Button>(2);
xevent.state = x11::KeyButMask::Button2;
break;
case RIGHT:
xevent.detail = static_cast<x11::Button>(3);
xevent.state = x11::KeyButMask::Button3;
break;
}
// Process accelerator key state.
if (accelerator_state & ui_controls::kShift)
xevent.state = xevent.state | x11::KeyButMask::Shift;
if (accelerator_state & ui_controls::kControl)
xevent.state = xevent.state | x11::KeyButMask::Control;
if (accelerator_state & ui_controls::kAlt)
xevent.state = xevent.state | x11::KeyButMask::Mod1;
if (accelerator_state & ui_controls::kCommand)
xevent.state = xevent.state | x11::KeyButMask::Mod4;
// RootWindow will take care of other necessary fields.
if (button_state & DOWN) {
xevent.opcode = x11::ButtonEvent::Press;
aura::test::PostEventToWindowTreeHost(root_window->GetHost(), &xevent);
button_down_mask |= static_cast<int>(xevent.state);
}
if (button_state & UP) {
xevent.opcode = x11::ButtonEvent::Release;
aura::test::PostEventToWindowTreeHost(root_window->GetHost(), &xevent);
int state = static_cast<int>(xevent.state);
button_down_mask = (button_down_mask | state) ^ state;
}
RunClosureAfterAllPendingUIEvents(std::move(closure));
gfx::Point mouse_root_loc = mouse_loc;
root_window->GetHost()->ConvertDIPToScreenInPixels(&mouse_root_loc);
x11_ui_controls_test_helper_.SendMouseEvent(
root_window->GetHost()->GetAcceleratedWidget(), type, button_state,
accelerator_state, mouse_loc, mouse_root_loc, std::move(closure));
return true;
}
bool SendMouseClick(MouseButton type) override {
return SendMouseEvents(type, UP | DOWN, ui_controls::kNoAccelerator);
}
void RunClosureAfterAllPendingUIEvents(base::OnceClosure closure) {
if (closure.is_null())
return;
ui::XEventWaiter::Create(x_window_, std::move(closure));
}
private:
aura::Window* RootWindowForPoint(const gfx::Point& point) {
......@@ -243,33 +156,7 @@ class UIControlsDesktopX11 : public UIControlsAura {
return (*i)->GetRootWindow();
}
void SetKeycodeAndSendThenMask(aura::WindowTreeHost* host,
x11::KeyEvent* xevent,
KeySym keysym,
x11::KeyButMask mask) {
xevent->detail = x11::Connection::Get()->KeysymToKeycode(
static_cast<x11::KeySym>(keysym));
aura::test::PostEventToWindowTreeHost(host, xevent);
xevent->state = xevent->state | mask;
}
void UnmaskAndSetKeycodeThenSend(aura::WindowTreeHost* host,
x11::KeyEvent* xevent,
x11::KeyButMask mask,
KeySym keysym) {
xevent->state = static_cast<x11::KeyButMask>(
static_cast<uint32_t>(xevent->state) ^ static_cast<uint32_t>(mask));
xevent->detail = x11::Connection::Get()->KeysymToKeycode(
static_cast<x11::KeySym>(keysym));
aura::test::PostEventToWindowTreeHost(host, xevent);
}
// Our X11 state.
x11::Connection* connection_;
x11::Window x_root_window_;
// Input-only window used for events.
x11::Window x_window_;
ui::X11UIControlsTestHelper x11_ui_controls_test_helper_;
DISALLOW_COPY_AND_ASSIGN(UIControlsDesktopX11);
};
......
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