X11 and Ozone: fix use_x11 && use_x11 build for UIControlsAura
When use_x11 && use_ozone are set to true at the same
time, compiler throws an error about multiple definitions
of the CreateUIControlsAura.
Thus, to fix that, create a separate source file for
is_linux case that will choose what class to
use based on the IsUsingOzonePlatform feature flag.
Please note that this is a temp solution and it will
be removed once use_x11 goes away.
PS: this patch uses the same approach used in other patches.
For example, https://crrev.com/c/2247719
PPS: I didn't spot that in the beginning as linux-rel bot
couldn't compile use_x11 && use_ozone because of failures
in the chrome installer step. But after we fixed the sysroot,
I spotted some problems and fixing them now.
Bug: 1085700
Change-Id: I1c2f3a0762df4b195775d30f580df09090f13999
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2362698
Reviewed-by: Scott Violet <sky@chromium.org>
Commit-Queue: Maksim Sisov (GMT+3) <msisov@igalia.com>
Cr-Commit-Position: refs/heads/master@{#799289}
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn
index 5edf943..0b7516f 100644
--- a/ui/aura/BUILD.gn
+++ b/ui/aura/BUILD.gn
@@ -247,9 +247,14 @@
sources += [ "test/ui_controls_factory_aurawin.cc" ]
}
+ if (is_linux) {
+ sources += [ "test/ui_controls_factory_aura_linux.cc" ]
+ }
+
if (use_x11) {
sources += [
- "test/ui_controls_factory_aurax11.cc",
+ "test/ui_controls_aurax11.cc",
+ "test/ui_controls_aurax11.h",
"test/x11_event_sender.cc",
"test/x11_event_sender.h",
]
@@ -264,7 +269,10 @@
if (is_fuchsia) {
deps += [ "//ui/ozone" ]
}
- sources += [ "test/ui_controls_factory_ozone.cc" ]
+ sources += [
+ "test/ui_controls_ozone.cc",
+ "test/ui_controls_ozone.h",
+ ]
}
if (is_linux || is_chromeos) {
diff --git a/ui/aura/test/ui_controls_aurax11.cc b/ui/aura/test/ui_controls_aurax11.cc
new file mode 100644
index 0000000..c0ef179
--- /dev/null
+++ b/ui/aura/test/ui_controls_aurax11.cc
@@ -0,0 +1,207 @@
+// 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/aura/test/ui_controls_aurax11.h"
+
+namespace aura {
+namespace test {
+namespace {
+
+using ui_controls::DOWN;
+using ui_controls::LEFT;
+using ui_controls::MIDDLE;
+using ui_controls::MouseButton;
+using ui_controls::RIGHT;
+using ui_controls::UIControlsAura;
+using ui_controls::UP;
+
+// Mask of the buttons currently down.
+unsigned button_down_mask = 0;
+
+} // namespace
+
+UIControlsX11::UIControlsX11(WindowTreeHost* host) : host_(host) {}
+
+UIControlsX11::~UIControlsX11() = default;
+
+bool UIControlsX11::SendKeyPress(gfx::NativeWindow window,
+ ui::KeyboardCode key,
+ bool control,
+ bool shift,
+ bool alt,
+ bool command) {
+ return SendKeyPressNotifyWhenDone(window, key, control, shift, alt, command,
+ base::OnceClosure());
+}
+
+bool UIControlsX11::SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
+ ui::KeyboardCode key,
+ bool control,
+ bool shift,
+ bool alt,
+ bool command,
+ base::OnceClosure closure) {
+ XEvent xevent;
+ xevent.xkey = {};
+ xevent.xkey.type = x11::KeyEvent::Press;
+ if (control)
+ SetKeycodeAndSendThenMask(&xevent, XK_Control_L, ControlMask);
+ if (shift)
+ SetKeycodeAndSendThenMask(&xevent, XK_Shift_L, ShiftMask);
+ if (alt)
+ SetKeycodeAndSendThenMask(&xevent, XK_Alt_L, Mod1Mask);
+ if (command)
+ SetKeycodeAndSendThenMask(&xevent, XK_Meta_L, Mod4Mask);
+ xevent.xkey.keycode = XKeysymToKeycode(
+ gfx::GetXDisplay(), ui::XKeysymForWindowsKeyCode(key, shift));
+ PostEventToWindowTreeHost(xevent, host_);
+
+ // Send key release events.
+ xevent.xkey.type = x11::KeyEvent::Release;
+ PostEventToWindowTreeHost(xevent, host_);
+ if (alt)
+ UnmaskAndSetKeycodeThenSend(&xevent, Mod1Mask, XK_Alt_L);
+ if (shift)
+ UnmaskAndSetKeycodeThenSend(&xevent, ShiftMask, XK_Shift_L);
+ if (control)
+ UnmaskAndSetKeycodeThenSend(&xevent, ControlMask, XK_Control_L);
+ if (command)
+ UnmaskAndSetKeycodeThenSend(&xevent, Mod4Mask, XK_Meta_L);
+ DCHECK(!xevent.xkey.state);
+ RunClosureAfterAllPendingUIEvents(std::move(closure));
+ return true;
+}
+
+bool UIControlsX11::SendMouseMove(int screen_x, int screen_y) {
+ return SendMouseMoveNotifyWhenDone(screen_x, screen_y, base::OnceClosure());
+}
+
+bool UIControlsX11::SendMouseMoveNotifyWhenDone(int screen_x,
+ int screen_y,
+ base::OnceClosure closure) {
+ gfx::Point root_location(screen_x, screen_y);
+ aura::client::ScreenPositionClient* screen_position_client =
+ aura::client::GetScreenPositionClient(host_->window());
+ if (screen_position_client) {
+ screen_position_client->ConvertPointFromScreen(host_->window(),
+ &root_location);
+ }
+ gfx::Point root_current_location =
+ QueryLatestMousePositionRequestInHost(host_);
+ host_->ConvertPixelsToDIP(&root_current_location);
+
+ if (root_location != root_current_location && button_down_mask == 0) {
+ // Move the cursor because EnterNotify/LeaveNotify are generated with the
+ // current mouse position as a result of XGrabPointer()
+ host_->window()->MoveCursorTo(root_location);
+ } else {
+ XEvent xevent;
+ xevent.xmotion = {};
+ XMotionEvent* xmotion = &xevent.xmotion;
+ xmotion->type = MotionNotify;
+ xmotion->x = root_location.x();
+ xmotion->y = root_location.y();
+ xmotion->state = button_down_mask;
+ xmotion->same_screen = x11::True;
+ // WindowTreeHost will take care of other necessary fields.
+ PostEventToWindowTreeHost(xevent, host_);
+ }
+ RunClosureAfterAllPendingUIEvents(std::move(closure));
+ return true;
+}
+
+bool UIControlsX11::SendMouseEvents(MouseButton type,
+ int button_state,
+ int accelerator_state) {
+ return SendMouseEventsNotifyWhenDone(type, button_state, base::OnceClosure(),
+ accelerator_state);
+}
+
+bool UIControlsX11::SendMouseEventsNotifyWhenDone(MouseButton type,
+ int button_state,
+ base::OnceClosure closure,
+ int accelerator_state) {
+ XEvent xevent;
+ xevent.xbutton = {};
+ XButtonEvent* xbutton = &xevent.xbutton;
+ gfx::Point mouse_loc = Env::GetInstance()->last_mouse_location();
+ aura::client::ScreenPositionClient* screen_position_client =
+ aura::client::GetScreenPositionClient(host_->window());
+ if (screen_position_client) {
+ screen_position_client->ConvertPointFromScreen(host_->window(), &mouse_loc);
+ }
+ xbutton->x = mouse_loc.x();
+ xbutton->y = mouse_loc.y();
+ xbutton->same_screen = x11::True;
+ switch (type) {
+ case LEFT:
+ xbutton->button = 1;
+ xbutton->state = Button1Mask;
+ break;
+ case MIDDLE:
+ xbutton->button = 2;
+ xbutton->state = Button2Mask;
+ break;
+ case RIGHT:
+ xbutton->button = 3;
+ xbutton->state = Button3Mask;
+ break;
+ }
+
+ // Process accelerator key state.
+ if (accelerator_state & ui_controls::kShift)
+ xbutton->state |= ShiftMask;
+ if (accelerator_state & ui_controls::kControl)
+ xbutton->state |= ControlMask;
+ if (accelerator_state & ui_controls::kAlt)
+ xbutton->state |= Mod1Mask;
+ if (accelerator_state & ui_controls::kCommand)
+ xbutton->state |= Mod4Mask;
+
+ // WindowEventDispatcher will take care of other necessary fields.
+ if (button_state & DOWN) {
+ xevent.xbutton.type = x11::ButtonEvent::Press;
+ PostEventToWindowTreeHost(xevent, host_);
+ button_down_mask |= xbutton->state;
+ }
+ if (button_state & UP) {
+ xevent.xbutton.type = x11::ButtonEvent::Release;
+ PostEventToWindowTreeHost(xevent, host_);
+ button_down_mask = (button_down_mask | xbutton->state) ^ xbutton->state;
+ }
+ RunClosureAfterAllPendingUIEvents(std::move(closure));
+ return true;
+}
+
+bool UIControlsX11::SendMouseClick(MouseButton type) {
+ return SendMouseEvents(type, UP | DOWN, ui_controls::kNoAccelerator);
+}
+
+void UIControlsX11::RunClosureAfterAllPendingUIEvents(
+ base::OnceClosure closure) {
+ if (closure.is_null())
+ return;
+ ui::XEventWaiter::Create(
+ static_cast<x11::Window>(host_->GetAcceleratedWidget()),
+ std::move(closure));
+}
+
+void UIControlsX11::SetKeycodeAndSendThenMask(XEvent* xevent,
+ KeySym keysym,
+ unsigned int mask) {
+ xevent->xkey.keycode = XKeysymToKeycode(gfx::GetXDisplay(), keysym);
+ PostEventToWindowTreeHost(*xevent, host_);
+ xevent->xkey.state |= mask;
+}
+
+void UIControlsX11::UnmaskAndSetKeycodeThenSend(XEvent* xevent,
+ unsigned int mask,
+ KeySym keysym) {
+ xevent->xkey.state ^= mask;
+ xevent->xkey.keycode = XKeysymToKeycode(gfx::GetXDisplay(), keysym);
+ PostEventToWindowTreeHost(*xevent, host_);
+}
+
+} // namespace test
+} // namespace aura
diff --git a/ui/aura/test/ui_controls_aurax11.h b/ui/aura/test/ui_controls_aurax11.h
new file mode 100644
index 0000000..71cbf13
--- /dev/null
+++ b/ui/aura/test/ui_controls_aurax11.h
@@ -0,0 +1,80 @@
+// 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_AURA_TEST_UI_CONTROLS_AURAX11_H_
+#define UI_AURA_TEST_UI_CONTROLS_AURAX11_H_
+
+#include "base/bind.h"
+#include "base/check.h"
+#include "base/location.h"
+#include "base/macros.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "ui/aura/client/screen_position_client.h"
+#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.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/base/test/ui_controls_aura.h"
+#include "ui/compositor/dip_util.h"
+#include "ui/events/keycodes/keyboard_code_conversion_x.h"
+#include "ui/events/test/x11_event_waiter.h"
+#include "ui/gfx/x/x11.h"
+
+namespace aura {
+namespace test {
+
+class UIControlsX11 : public ui_controls::UIControlsAura {
+ public:
+ explicit UIControlsX11(WindowTreeHost* host);
+ UIControlsX11(const UIControlsX11&) = delete;
+ UIControlsX11& operator=(const UIControlsX11&) = delete;
+ ~UIControlsX11() override;
+
+ // UIControlsAura overrides:
+ bool SendKeyPress(gfx::NativeWindow window,
+ ui::KeyboardCode key,
+ bool control,
+ bool shift,
+ bool alt,
+ bool command) override;
+ bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
+ ui::KeyboardCode key,
+ bool control,
+ bool shift,
+ bool alt,
+ bool command,
+ base::OnceClosure closure) override;
+ bool SendMouseMove(int screen_x, int screen_y) override;
+ bool SendMouseMoveNotifyWhenDone(int screen_x,
+ int screen_y,
+ base::OnceClosure closure) override;
+ bool SendMouseEvents(ui_controls::MouseButton type,
+ int button_state,
+ int accelerator_state) override;
+ bool SendMouseEventsNotifyWhenDone(ui_controls::MouseButton type,
+ int button_state,
+ base::OnceClosure closure,
+ int accelerator_state) override;
+ bool SendMouseClick(ui_controls::MouseButton type) override;
+
+ void RunClosureAfterAllPendingUIEvents(base::OnceClosure closure);
+
+ private:
+ void SetKeycodeAndSendThenMask(XEvent* xevent,
+ KeySym keysym,
+ unsigned int mask);
+
+ void UnmaskAndSetKeycodeThenSend(XEvent* xevent,
+ unsigned int mask,
+ KeySym keysym);
+ WindowTreeHost* const host_;
+};
+
+} // namespace test
+} // namespace aura
+
+#endif // UI_AURA_TEST_UI_CONTROLS_AURAX11_H_
diff --git a/ui/aura/test/ui_controls_factory_aura_linux.cc b/ui/aura/test/ui_controls_factory_aura_linux.cc
new file mode 100644
index 0000000..0edbd74
--- /dev/null
+++ b/ui/aura/test/ui_controls_factory_aura_linux.cc
@@ -0,0 +1,34 @@
+// Copyright 2013 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/aura/test/ui_controls_factory_aura.h"
+
+#include "base/notreached.h"
+
+#if defined(USE_X11)
+#include "ui/aura/test/ui_controls_aurax11.h"
+#endif
+
+#if defined(USE_OZONE)
+#include "ui/aura/test/ui_controls_ozone.h"
+#include "ui/base/ui_base_features.h"
+#endif
+
+namespace aura {
+namespace test {
+
+ui_controls::UIControlsAura* CreateUIControlsAura(WindowTreeHost* host) {
+#if defined(USE_OZONE)
+ if (features::IsUsingOzonePlatform())
+ return new UIControlsOzone(host);
+#endif
+#if defined(USE_X11)
+ return new UIControlsX11(host);
+#endif
+ NOTREACHED();
+ return nullptr;
+}
+
+} // namespace test
+} // namespace aura
diff --git a/ui/aura/test/ui_controls_factory_aurax11.cc b/ui/aura/test/ui_controls_factory_aurax11.cc
deleted file mode 100644
index bacd6978..0000000
--- a/ui/aura/test/ui_controls_factory_aurax11.cc
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright 2013 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 "base/bind.h"
-#include "base/check.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "ui/aura/client/screen_position_client.h"
-#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.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/base/test/ui_controls_aura.h"
-#include "ui/compositor/dip_util.h"
-#include "ui/events/keycodes/keyboard_code_conversion_x.h"
-#include "ui/events/test/x11_event_waiter.h"
-#include "ui/gfx/x/x11.h"
-
-namespace aura {
-namespace test {
-namespace {
-
-using ui_controls::DOWN;
-using ui_controls::LEFT;
-using ui_controls::MIDDLE;
-using ui_controls::MouseButton;
-using ui_controls::RIGHT;
-using ui_controls::UIControlsAura;
-using ui_controls::UP;
-
-// Mask of the buttons currently down.
-unsigned button_down_mask = 0;
-
-class UIControlsX11 : public UIControlsAura {
- public:
- explicit UIControlsX11(WindowTreeHost* host) : host_(host) {}
-
- bool SendKeyPress(gfx::NativeWindow window,
- ui::KeyboardCode key,
- bool control,
- bool shift,
- bool alt,
- bool command) override {
- return SendKeyPressNotifyWhenDone(window, key, control, shift, alt, command,
- base::OnceClosure());
- }
- bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
- ui::KeyboardCode key,
- bool control,
- bool shift,
- bool alt,
- bool command,
- base::OnceClosure closure) override {
- XEvent xevent;
- xevent.xkey = {};
- xevent.xkey.type = x11::KeyEvent::Press;
- if (control)
- SetKeycodeAndSendThenMask(&xevent, XK_Control_L, ControlMask);
- if (shift)
- SetKeycodeAndSendThenMask(&xevent, XK_Shift_L, ShiftMask);
- if (alt)
- SetKeycodeAndSendThenMask(&xevent, XK_Alt_L, Mod1Mask);
- if (command)
- SetKeycodeAndSendThenMask(&xevent, XK_Meta_L, Mod4Mask);
- xevent.xkey.keycode = XKeysymToKeycode(
- gfx::GetXDisplay(), ui::XKeysymForWindowsKeyCode(key, shift));
- PostEventToWindowTreeHost(xevent, host_);
-
- // Send key release events.
- xevent.xkey.type = x11::KeyEvent::Release;
- PostEventToWindowTreeHost(xevent, host_);
- if (alt)
- UnmaskAndSetKeycodeThenSend(&xevent, Mod1Mask, XK_Alt_L);
- if (shift)
- UnmaskAndSetKeycodeThenSend(&xevent, ShiftMask, XK_Shift_L);
- if (control)
- UnmaskAndSetKeycodeThenSend(&xevent, ControlMask, XK_Control_L);
- if (command)
- UnmaskAndSetKeycodeThenSend(&xevent, Mod4Mask, XK_Meta_L);
- DCHECK(!xevent.xkey.state);
- RunClosureAfterAllPendingUIEvents(std::move(closure));
- return true;
- }
-
- bool SendMouseMove(int screen_x, int screen_y) override {
- return SendMouseMoveNotifyWhenDone(screen_x, screen_y, base::OnceClosure());
- }
- bool SendMouseMoveNotifyWhenDone(int screen_x,
- int screen_y,
- base::OnceClosure closure) override {
- gfx::Point root_location(screen_x, screen_y);
- aura::client::ScreenPositionClient* screen_position_client =
- aura::client::GetScreenPositionClient(host_->window());
- if (screen_position_client) {
- screen_position_client->ConvertPointFromScreen(host_->window(),
- &root_location);
- }
- gfx::Point root_current_location =
- QueryLatestMousePositionRequestInHost(host_);
- host_->ConvertPixelsToDIP(&root_current_location);
-
- if (root_location != root_current_location && button_down_mask == 0) {
- // Move the cursor because EnterNotify/LeaveNotify are generated with the
- // current mouse position as a result of XGrabPointer()
- host_->window()->MoveCursorTo(root_location);
- } else {
- XEvent xevent;
- xevent.xmotion = {};
- XMotionEvent* xmotion = &xevent.xmotion;
- xmotion->type = MotionNotify;
- xmotion->x = root_location.x();
- xmotion->y = root_location.y();
- xmotion->state = button_down_mask;
- xmotion->same_screen = x11::True;
- // WindowTreeHost will take care of other necessary fields.
- PostEventToWindowTreeHost(xevent, host_);
- }
- RunClosureAfterAllPendingUIEvents(std::move(closure));
- return true;
- }
- bool SendMouseEvents(MouseButton type,
- int button_state,
- int accelerator_state) override {
- return SendMouseEventsNotifyWhenDone(
- type, button_state, base::OnceClosure(), accelerator_state);
- }
- bool SendMouseEventsNotifyWhenDone(MouseButton type,
- int button_state,
- base::OnceClosure closure,
- int accelerator_state) override {
- XEvent xevent;
- xevent.xbutton = {};
- XButtonEvent* xbutton = &xevent.xbutton;
- gfx::Point mouse_loc = Env::GetInstance()->last_mouse_location();
- aura::client::ScreenPositionClient* screen_position_client =
- aura::client::GetScreenPositionClient(host_->window());
- if (screen_position_client) {
- screen_position_client->ConvertPointFromScreen(host_->window(),
- &mouse_loc);
- }
- xbutton->x = mouse_loc.x();
- xbutton->y = mouse_loc.y();
- xbutton->same_screen = x11::True;
- switch (type) {
- case LEFT:
- xbutton->button = 1;
- xbutton->state = Button1Mask;
- break;
- case MIDDLE:
- xbutton->button = 2;
- xbutton->state = Button2Mask;
- break;
- case RIGHT:
- xbutton->button = 3;
- xbutton->state = Button3Mask;
- break;
- }
-
- // Process accelerator key state.
- if (accelerator_state & ui_controls::kShift)
- xbutton->state |= ShiftMask;
- if (accelerator_state & ui_controls::kControl)
- xbutton->state |= ControlMask;
- if (accelerator_state & ui_controls::kAlt)
- xbutton->state |= Mod1Mask;
- if (accelerator_state & ui_controls::kCommand)
- xbutton->state |= Mod4Mask;
-
- // WindowEventDispatcher will take care of other necessary fields.
- if (button_state & DOWN) {
- xevent.xbutton.type = x11::ButtonEvent::Press;
- PostEventToWindowTreeHost(xevent, host_);
- button_down_mask |= xbutton->state;
- }
- if (button_state & UP) {
- xevent.xbutton.type = x11::ButtonEvent::Release;
- PostEventToWindowTreeHost(xevent, host_);
- button_down_mask = (button_down_mask | xbutton->state) ^ xbutton->state;
- }
- RunClosureAfterAllPendingUIEvents(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(
- static_cast<x11::Window>(host_->GetAcceleratedWidget()),
- std::move(closure));
- }
-
- private:
- void SetKeycodeAndSendThenMask(XEvent* xevent,
- KeySym keysym,
- unsigned int mask) {
- xevent->xkey.keycode = XKeysymToKeycode(gfx::GetXDisplay(), keysym);
- PostEventToWindowTreeHost(*xevent, host_);
- xevent->xkey.state |= mask;
- }
-
- void UnmaskAndSetKeycodeThenSend(XEvent* xevent,
- unsigned int mask,
- KeySym keysym) {
- xevent->xkey.state ^= mask;
- xevent->xkey.keycode = XKeysymToKeycode(gfx::GetXDisplay(), keysym);
- PostEventToWindowTreeHost(*xevent, host_);
- }
-
- WindowTreeHost* host_;
-
- DISALLOW_COPY_AND_ASSIGN(UIControlsX11);
-};
-
-} // namespace
-
-UIControlsAura* CreateUIControlsAura(WindowTreeHost* host) {
- return new UIControlsX11(host);
-}
-
-} // namespace test
-} // namespace aura
diff --git a/ui/aura/test/ui_controls_factory_ozone.cc b/ui/aura/test/ui_controls_factory_ozone.cc
deleted file mode 100644
index dce2708..0000000
--- a/ui/aura/test/ui_controls_factory_ozone.cc
+++ /dev/null
@@ -1,381 +0,0 @@
-// Copyright 2014 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 "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "ui/aura/env.h"
-#include "ui/aura/test/aura_test_utils.h"
-#include "ui/aura/test/env_test_helper.h"
-#include "ui/aura/test/ui_controls_factory_aura.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/base/test/ui_controls_aura.h"
-#include "ui/display/display.h"
-#include "ui/display/screen.h"
-#include "ui/events/event_utils.h"
-#include "ui/events/test/events_test_utils.h"
-#include "ui/gfx/geometry/point_conversions.h"
-
-namespace aura {
-namespace test {
-namespace {
-
-class UIControlsOzone : public ui_controls::UIControlsAura {
- public:
- UIControlsOzone(WindowTreeHost* host) : host_(host) {
- }
- ~UIControlsOzone() override = default;
-
- private:
- // ui_controls::UIControlsAura:
- bool SendKeyPress(gfx::NativeWindow window,
- ui::KeyboardCode key,
- bool control,
- bool shift,
- bool alt,
- bool command) override {
- return SendKeyPressNotifyWhenDone(window, key, control, shift, alt, command,
- base::OnceClosure());
- }
- bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
- ui::KeyboardCode key,
- bool control,
- bool shift,
- bool alt,
- bool command,
- base::OnceClosure closure) override {
- WindowTreeHost* optional_host = nullptr;
- // Send the key event to the window's host, which may not match |host_|.
- // This logic should probably exist for the non-aura path as well.
- // TODO(https://crbug.com/1116649) Support non-aura path.
-#if defined(USE_AURA)
- if (window != nullptr && window->GetHost() != nullptr &&
- window->GetHost() != host_)
- optional_host = window->GetHost();
-#endif
-
- int flags = button_down_mask_;
- int64_t display_id =
- display::Screen::GetScreen()->GetDisplayNearestWindow(window).id();
-
- if (control) {
- flags |= ui::EF_CONTROL_DOWN;
- PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, flags, display_id,
- base::OnceClosure(), optional_host);
- }
-
- if (shift) {
- flags |= ui::EF_SHIFT_DOWN;
- PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, flags, display_id,
- base::OnceClosure(), optional_host);
- }
-
- if (alt) {
- flags |= ui::EF_ALT_DOWN;
- PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_MENU, flags, display_id,
- base::OnceClosure(), optional_host);
- }
-
- if (command) {
- flags |= ui::EF_COMMAND_DOWN;
- PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_LWIN, flags, display_id,
- base::OnceClosure(), optional_host);
- }
-
- PostKeyEvent(ui::ET_KEY_PRESSED, key, flags, display_id,
- base::OnceClosure(), optional_host);
- const bool has_modifier = control || shift || alt || command;
- // Pass the real closure to the last generated KeyEvent.
- PostKeyEvent(ui::ET_KEY_RELEASED, key, flags, display_id,
- has_modifier ? base::OnceClosure() : std::move(closure),
- optional_host);
-
- if (alt) {
- flags &= ~ui::EF_ALT_DOWN;
- PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_MENU, flags, display_id,
- (shift || control || command) ? base::OnceClosure()
- : std::move(closure),
- optional_host);
- }
-
- if (shift) {
- flags &= ~ui::EF_SHIFT_DOWN;
- PostKeyEvent(
- ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, flags, display_id,
- (control || command) ? base::OnceClosure() : std::move(closure),
- optional_host);
- }
-
- if (control) {
- flags &= ~ui::EF_CONTROL_DOWN;
- PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL, flags, display_id,
- command ? base::OnceClosure() : std::move(closure),
- optional_host);
- }
-
- if (command) {
- flags &= ~ui::EF_COMMAND_DOWN;
- PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_LWIN, flags, display_id,
- std::move(closure), optional_host);
- }
-
- return true;
- }
-
- bool SendMouseMove(int screen_x, int screen_y) override {
- return SendMouseMoveNotifyWhenDone(screen_x, screen_y, base::OnceClosure());
- }
- bool SendMouseMoveNotifyWhenDone(int screen_x,
- int screen_y,
- base::OnceClosure closure) override {
- gfx::PointF host_location(screen_x, screen_y);
- int64_t display_id = display::kInvalidDisplayId;
- if (!ScreenDIPToHostPixels(&host_location, &display_id))
- return false;
- ui::EventType event_type;
-
- if (button_down_mask_)
- event_type = ui::ET_MOUSE_DRAGGED;
- else
- event_type = ui::ET_MOUSE_MOVED;
-
- PostMouseEvent(event_type, host_location, button_down_mask_, 0, display_id,
- std::move(closure));
-
- return true;
- }
- bool SendMouseEvents(ui_controls::MouseButton type,
- int button_state,
- int accelerator_state) override {
- return SendMouseEventsNotifyWhenDone(
- type, button_state, base::OnceClosure(), accelerator_state);
- }
- bool SendMouseEventsNotifyWhenDone(ui_controls::MouseButton type,
- int button_state,
- base::OnceClosure closure,
- int accelerator_state) override {
- gfx::PointF host_location(Env::GetInstance()->last_mouse_location());
- int64_t display_id = display::kInvalidDisplayId;
- if (!ScreenDIPToHostPixels(&host_location, &display_id))
- return false;
-
- int changed_button_flag = 0;
-
- switch (type) {
- case ui_controls::LEFT:
- changed_button_flag = ui::EF_LEFT_MOUSE_BUTTON;
- break;
- case ui_controls::MIDDLE:
- changed_button_flag = ui::EF_MIDDLE_MOUSE_BUTTON;
- break;
- case ui_controls::RIGHT:
- changed_button_flag = ui::EF_RIGHT_MOUSE_BUTTON;
- break;
- default:
- NOTREACHED();
- break;
- }
-
- // Process the accelerator key state.
- int flag = changed_button_flag;
- if (accelerator_state & ui_controls::kShift)
- flag |= ui::EF_SHIFT_DOWN;
- if (accelerator_state & ui_controls::kControl)
- flag |= ui::EF_CONTROL_DOWN;
- if (accelerator_state & ui_controls::kAlt)
- flag |= ui::EF_ALT_DOWN;
- if (accelerator_state & ui_controls::kCommand)
- flag |= ui::EF_COMMAND_DOWN;
-
- if (button_state & ui_controls::DOWN) {
- button_down_mask_ |= flag;
- // Pass the real closure to the last generated MouseEvent.
- PostMouseEvent(ui::ET_MOUSE_PRESSED, host_location,
- button_down_mask_ | flag, changed_button_flag, display_id,
- (button_state & ui_controls::UP) ? base::OnceClosure()
- : std::move(closure));
- }
- if (button_state & ui_controls::UP) {
- button_down_mask_ &= ~flag;
- PostMouseEvent(ui::ET_MOUSE_RELEASED, host_location,
- button_down_mask_ | flag, changed_button_flag, display_id,
- std::move(closure));
- }
-
- return true;
- }
- bool SendMouseClick(ui_controls::MouseButton type) override {
- return SendMouseEvents(type, ui_controls::UP | ui_controls::DOWN,
- ui_controls::kNoAccelerator);
- }
-#if defined(OS_CHROMEOS)
- bool SendTouchEvents(int action, int id, int x, int y) override {
- return SendTouchEventsNotifyWhenDone(action, id, x, y, base::OnceClosure());
- }
- bool SendTouchEventsNotifyWhenDone(int action,
- int id,
- int x,
- int y,
- base::OnceClosure task) override {
- DCHECK_NE(0, action);
- gfx::PointF host_location(x, y);
- int64_t display_id = display::kInvalidDisplayId;
- if (!ScreenDIPToHostPixels(&host_location, &display_id))
- return false;
- bool has_move = action & ui_controls::MOVE;
- bool has_release = action & ui_controls::RELEASE;
- if (action & ui_controls::PRESS) {
- PostTouchEvent(
- ui::ET_TOUCH_PRESSED, host_location, id, display_id,
- (has_move || has_release) ? base::OnceClosure() : std::move(task));
- }
- if (has_move) {
- PostTouchEvent(ui::ET_TOUCH_MOVED, host_location, id, display_id,
- has_release ? base::OnceClosure() : std::move(task));
- }
- if (has_release) {
- PostTouchEvent(ui::ET_TOUCH_RELEASED, host_location, id, display_id,
- std::move(task));
- }
- return true;
- }
-#endif
-
- // Use |optional_host| to specify the host.
- // When |optional_host| is not null, event will be sent to |optional_host|.
- // When |optional_host| is null, event will be sent to the default host.
- void SendEventToSink(ui::Event* event,
- int64_t display_id,
- base::OnceClosure closure,
- WindowTreeHost* optional_host = nullptr) {
- // Post the task before processing the event. This is necessary in case
- // processing the event results in a nested message loop.
- if (closure) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- std::move(closure));
- }
- WindowTreeHost* host = optional_host ? optional_host : host_;
- ui::EventSourceTestApi event_source_test(host->GetEventSource());
- ignore_result(event_source_test.SendEventToSink(event));
- }
-
- void PostKeyEvent(ui::EventType type,
- ui::KeyboardCode key_code,
- int flags,
- int64_t display_id,
- base::OnceClosure closure,
- WindowTreeHost* optional_host = nullptr) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(&UIControlsOzone::PostKeyEventTask,
- base::Unretained(this), type, key_code, flags,
- display_id, std::move(closure), optional_host));
- }
-
- void PostKeyEventTask(ui::EventType type,
- ui::KeyboardCode key_code,
- int flags,
- int64_t display_id,
- base::OnceClosure closure,
- WindowTreeHost* optional_host) {
- // Do not rewrite injected events. See crbug.com/136465.
- flags |= ui::EF_FINAL;
-
- ui::KeyEvent key_event(type, key_code, flags);
- SendEventToSink(&key_event, display_id, std::move(closure), optional_host);
- }
-
- void PostMouseEvent(ui::EventType type,
- const gfx::PointF& host_location,
- int flags,
- int changed_button_flags,
- int64_t display_id,
- base::OnceClosure closure) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(&UIControlsOzone::PostMouseEventTask,
- base::Unretained(this), type, host_location, flags,
- changed_button_flags, display_id, std::move(closure)));
- }
-
- void PostMouseEventTask(ui::EventType type,
- const gfx::PointF& host_location,
- int flags,
- int changed_button_flags,
- int64_t display_id,
- base::OnceClosure closure) {
- ui::MouseEvent mouse_event(type, host_location, host_location,
- ui::EventTimeForNow(), flags,
- changed_button_flags);
-
- // This hack is necessary to set the repeat count for clicks.
- ui::MouseEvent mouse_event2(&mouse_event);
-
- SendEventToSink(&mouse_event2, display_id, std::move(closure));
- }
-
- void PostTouchEvent(ui::EventType type,
- const gfx::PointF& host_location,
- int id,
- int64_t display_id,
- base::OnceClosure closure) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&UIControlsOzone::PostTouchEventTask,
- base::Unretained(this), type, host_location,
- id, display_id, std::move(closure)));
- }
-
- void PostTouchEventTask(ui::EventType type,
- const gfx::PointF& host_location,
- int id,
- int64_t display_id,
- base::OnceClosure closure) {
- ui::PointerDetails details(ui::EventPointerType::kTouch, id, 1.0f, 1.0f,
- 0.0f);
- ui::TouchEvent touch_event(type, host_location, host_location,
- ui::EventTimeForNow(), details);
- SendEventToSink(&touch_event, display_id, std::move(closure));
- }
-
- bool ScreenDIPToHostPixels(gfx::PointF* location, int64_t* display_id) {
- // The location needs to be in display's coordinate.
- display::Display display =
- display::Screen::GetScreen()->GetDisplayNearestPoint(
- gfx::ToFlooredPoint(*location));
- if (!display.is_valid()) {
- LOG(ERROR) << "Failed to find the display for " << location->ToString();
- return false;
- }
- *display_id = display.id();
- *location -= display.bounds().OffsetFromOrigin();
- location->Scale(display.device_scale_factor());
- return true;
- }
-
- // This is the default host used for events that are not scoped to a window.
- // Events scoped to a window always use the window's host.
- WindowTreeHost* host_;
-
- // Mask of the mouse buttons currently down. This is static as it needs to
- // track the state globally for all displays. A UIControlsOzone instance is
- // created for each display host.
- static unsigned button_down_mask_;
-
- DISALLOW_COPY_AND_ASSIGN(UIControlsOzone);
-};
-
-// static
-unsigned UIControlsOzone::button_down_mask_ = 0;
-
-} // namespace
-
-ui_controls::UIControlsAura* CreateUIControlsAura(WindowTreeHost* host) {
- return new UIControlsOzone(host);
-}
-
-} // namespace test
-} // namespace aura
diff --git a/ui/aura/test/ui_controls_ozone.cc b/ui/aura/test/ui_controls_ozone.cc
new file mode 100644
index 0000000..93ee63a8
--- /dev/null
+++ b/ui/aura/test/ui_controls_ozone.cc
@@ -0,0 +1,358 @@
+// 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/aura/test/ui_controls_ozone.h"
+
+#include "build/build_config.h"
+
+namespace aura {
+namespace test {
+
+// static
+unsigned UIControlsOzone::button_down_mask_ = 0;
+
+UIControlsOzone::UIControlsOzone(WindowTreeHost* host) : host_(host) {}
+
+UIControlsOzone::~UIControlsOzone() = default;
+
+bool UIControlsOzone::SendKeyPress(gfx::NativeWindow window,
+ ui::KeyboardCode key,
+ bool control,
+ bool shift,
+ bool alt,
+ bool command) {
+ return SendKeyPressNotifyWhenDone(window, key, control, shift, alt, command,
+ base::OnceClosure());
+}
+
+bool UIControlsOzone::SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
+ ui::KeyboardCode key,
+ bool control,
+ bool shift,
+ bool alt,
+ bool command,
+ base::OnceClosure closure) {
+ WindowTreeHost* optional_host = nullptr;
+ // Send the key event to the window's host, which may not match |host_|.
+ // This logic should probably exist for the non-aura path as well.
+ // TODO(https://crbug.com/1116649) Support non-aura path.
+#if defined(USE_AURA)
+ if (window != nullptr && window->GetHost() != nullptr &&
+ window->GetHost() != host_)
+ optional_host = window->GetHost();
+#endif
+
+ int flags = button_down_mask_;
+ int64_t display_id =
+ display::Screen::GetScreen()->GetDisplayNearestWindow(window).id();
+
+ if (control) {
+ flags |= ui::EF_CONTROL_DOWN;
+ PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, flags, display_id,
+ base::OnceClosure(), optional_host);
+ }
+
+ if (shift) {
+ flags |= ui::EF_SHIFT_DOWN;
+ PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, flags, display_id,
+ base::OnceClosure(), optional_host);
+ }
+
+ if (alt) {
+ flags |= ui::EF_ALT_DOWN;
+ PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_MENU, flags, display_id,
+ base::OnceClosure(), optional_host);
+ }
+
+ if (command) {
+ flags |= ui::EF_COMMAND_DOWN;
+ PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_LWIN, flags, display_id,
+ base::OnceClosure(), optional_host);
+ }
+
+ PostKeyEvent(ui::ET_KEY_PRESSED, key, flags, display_id, base::OnceClosure(),
+ optional_host);
+ const bool has_modifier = control || shift || alt || command;
+ // Pass the real closure to the last generated KeyEvent.
+ PostKeyEvent(ui::ET_KEY_RELEASED, key, flags, display_id,
+ has_modifier ? base::OnceClosure() : std::move(closure),
+ optional_host);
+
+ if (alt) {
+ flags &= ~ui::EF_ALT_DOWN;
+ PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_MENU, flags, display_id,
+ (shift || control || command) ? base::OnceClosure()
+ : std::move(closure),
+ optional_host);
+ }
+
+ if (shift) {
+ flags &= ~ui::EF_SHIFT_DOWN;
+ PostKeyEvent(
+ ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, flags, display_id,
+ (control || command) ? base::OnceClosure() : std::move(closure),
+ optional_host);
+ }
+
+ if (control) {
+ flags &= ~ui::EF_CONTROL_DOWN;
+ PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL, flags, display_id,
+ command ? base::OnceClosure() : std::move(closure),
+ optional_host);
+ }
+
+ if (command) {
+ flags &= ~ui::EF_COMMAND_DOWN;
+ PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_LWIN, flags, display_id,
+ std::move(closure), optional_host);
+ }
+
+ return true;
+}
+
+bool UIControlsOzone::SendMouseMove(int screen_x, int screen_y) {
+ return SendMouseMoveNotifyWhenDone(screen_x, screen_y, base::OnceClosure());
+}
+
+bool UIControlsOzone::SendMouseMoveNotifyWhenDone(int screen_x,
+ int screen_y,
+ base::OnceClosure closure) {
+ gfx::PointF host_location(screen_x, screen_y);
+ int64_t display_id = display::kInvalidDisplayId;
+ if (!ScreenDIPToHostPixels(&host_location, &display_id))
+ return false;
+ ui::EventType event_type;
+
+ if (button_down_mask_)
+ event_type = ui::ET_MOUSE_DRAGGED;
+ else
+ event_type = ui::ET_MOUSE_MOVED;
+
+ PostMouseEvent(event_type, host_location, button_down_mask_, 0, display_id,
+ std::move(closure));
+
+ return true;
+}
+
+bool UIControlsOzone::SendMouseEvents(ui_controls::MouseButton type,
+ int button_state,
+ int accelerator_state) {
+ return SendMouseEventsNotifyWhenDone(type, button_state, base::OnceClosure(),
+ accelerator_state);
+}
+
+bool UIControlsOzone::SendMouseEventsNotifyWhenDone(
+ ui_controls::MouseButton type,
+ int button_state,
+ base::OnceClosure closure,
+ int accelerator_state) {
+ gfx::PointF host_location(Env::GetInstance()->last_mouse_location());
+ int64_t display_id = display::kInvalidDisplayId;
+ if (!ScreenDIPToHostPixels(&host_location, &display_id))
+ return false;
+
+ int changed_button_flag = 0;
+
+ switch (type) {
+ case ui_controls::LEFT:
+ changed_button_flag = ui::EF_LEFT_MOUSE_BUTTON;
+ break;
+ case ui_controls::MIDDLE:
+ changed_button_flag = ui::EF_MIDDLE_MOUSE_BUTTON;
+ break;
+ case ui_controls::RIGHT:
+ changed_button_flag = ui::EF_RIGHT_MOUSE_BUTTON;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+
+ // Process the accelerator key state.
+ int flag = changed_button_flag;
+ if (accelerator_state & ui_controls::kShift)
+ flag |= ui::EF_SHIFT_DOWN;
+ if (accelerator_state & ui_controls::kControl)
+ flag |= ui::EF_CONTROL_DOWN;
+ if (accelerator_state & ui_controls::kAlt)
+ flag |= ui::EF_ALT_DOWN;
+ if (accelerator_state & ui_controls::kCommand)
+ flag |= ui::EF_COMMAND_DOWN;
+
+ if (button_state & ui_controls::DOWN) {
+ button_down_mask_ |= flag;
+ // Pass the real closure to the last generated MouseEvent.
+ PostMouseEvent(ui::ET_MOUSE_PRESSED, host_location,
+ button_down_mask_ | flag, changed_button_flag, display_id,
+ (button_state & ui_controls::UP) ? base::OnceClosure()
+ : std::move(closure));
+ }
+ if (button_state & ui_controls::UP) {
+ button_down_mask_ &= ~flag;
+ PostMouseEvent(ui::ET_MOUSE_RELEASED, host_location,
+ button_down_mask_ | flag, changed_button_flag, display_id,
+ std::move(closure));
+ }
+
+ return true;
+}
+
+bool UIControlsOzone::SendMouseClick(ui_controls::MouseButton type) {
+ return SendMouseEvents(type, ui_controls::UP | ui_controls::DOWN,
+ ui_controls::kNoAccelerator);
+}
+
+#if defined(OS_CHROMEOS)
+bool UIControlsOzone::SendTouchEvents(int action, int id, int x, int y) {
+ return SendTouchEventsNotifyWhenDone(action, id, x, y, base::OnceClosure());
+}
+
+bool UIControlsOzone::SendTouchEventsNotifyWhenDone(int action,
+ int id,
+ int x,
+ int y,
+ base::OnceClosure task) {
+ DCHECK_NE(0, action);
+ gfx::PointF host_location(x, y);
+ int64_t display_id = display::kInvalidDisplayId;
+ if (!ScreenDIPToHostPixels(&host_location, &display_id))
+ return false;
+ bool has_move = action & ui_controls::MOVE;
+ bool has_release = action & ui_controls::RELEASE;
+ if (action & ui_controls::PRESS) {
+ PostTouchEvent(
+ ui::ET_TOUCH_PRESSED, host_location, id, display_id,
+ (has_move || has_release) ? base::OnceClosure() : std::move(task));
+ }
+ if (has_move) {
+ PostTouchEvent(ui::ET_TOUCH_MOVED, host_location, id, display_id,
+ has_release ? base::OnceClosure() : std::move(task));
+ }
+ if (has_release) {
+ PostTouchEvent(ui::ET_TOUCH_RELEASED, host_location, id, display_id,
+ std::move(task));
+ }
+ return true;
+}
+#endif
+
+void UIControlsOzone::SendEventToSink(ui::Event* event,
+ int64_t display_id,
+ base::OnceClosure closure,
+ WindowTreeHost* optional_host) {
+ // Post the task before processing the event. This is necessary in case
+ // processing the event results in a nested message loop.
+ if (closure) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ std::move(closure));
+ }
+ WindowTreeHost* host = optional_host ? optional_host : host_;
+ ui::EventSourceTestApi event_source_test(host->GetEventSource());
+ ignore_result(event_source_test.SendEventToSink(event));
+}
+
+void UIControlsOzone::PostKeyEvent(ui::EventType type,
+ ui::KeyboardCode key_code,
+ int flags,
+ int64_t display_id,
+ base::OnceClosure closure,
+ WindowTreeHost* optional_host) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&UIControlsOzone::PostKeyEventTask,
+ base::Unretained(this), type, key_code, flags,
+ display_id, std::move(closure), optional_host));
+}
+
+void UIControlsOzone::PostKeyEventTask(ui::EventType type,
+ ui::KeyboardCode key_code,
+ int flags,
+ int64_t display_id,
+ base::OnceClosure closure,
+ WindowTreeHost* optional_host) {
+ // Do not rewrite injected events. See crbug.com/136465.
+ flags |= ui::EF_FINAL;
+
+ ui::KeyEvent key_event(type, key_code, flags);
+ SendEventToSink(&key_event, display_id, std::move(closure), optional_host);
+}
+
+void UIControlsOzone::PostMouseEvent(ui::EventType type,
+ const gfx::PointF& host_location,
+ int flags,
+ int changed_button_flags,
+ int64_t display_id,
+ base::OnceClosure closure) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&UIControlsOzone::PostMouseEventTask,
+ base::Unretained(this), type, host_location, flags,
+ changed_button_flags, display_id, std::move(closure)));
+}
+
+void UIControlsOzone::PostMouseEventTask(ui::EventType type,
+ const gfx::PointF& host_location,
+ int flags,
+ int changed_button_flags,
+ int64_t display_id,
+ base::OnceClosure closure) {
+ ui::MouseEvent mouse_event(type, host_location, host_location,
+ ui::EventTimeForNow(), flags,
+ changed_button_flags);
+
+ // This hack is necessary to set the repeat count for clicks.
+ ui::MouseEvent mouse_event2(&mouse_event);
+
+ SendEventToSink(&mouse_event2, display_id, std::move(closure));
+}
+
+void UIControlsOzone::PostTouchEvent(ui::EventType type,
+ const gfx::PointF& host_location,
+ int id,
+ int64_t display_id,
+ base::OnceClosure closure) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&UIControlsOzone::PostTouchEventTask,
+ base::Unretained(this), type, host_location, id,
+ display_id, std::move(closure)));
+}
+
+void UIControlsOzone::PostTouchEventTask(ui::EventType type,
+ const gfx::PointF& host_location,
+ int id,
+ int64_t display_id,
+ base::OnceClosure closure) {
+ ui::PointerDetails details(ui::EventPointerType::kTouch, id, 1.0f, 1.0f,
+ 0.0f);
+ ui::TouchEvent touch_event(type, host_location, host_location,
+ ui::EventTimeForNow(), details);
+ SendEventToSink(&touch_event, display_id, std::move(closure));
+}
+
+bool UIControlsOzone::ScreenDIPToHostPixels(gfx::PointF* location,
+ int64_t* display_id) {
+ // The location needs to be in display's coordinate.
+ display::Display display =
+ display::Screen::GetScreen()->GetDisplayNearestPoint(
+ gfx::ToFlooredPoint(*location));
+ if (!display.is_valid()) {
+ LOG(ERROR) << "Failed to find the display for " << location->ToString();
+ return false;
+ }
+ *display_id = display.id();
+ *location -= display.bounds().OffsetFromOrigin();
+ location->Scale(display.device_scale_factor());
+ return true;
+}
+
+// To avoid multiple definitions when use_x11 && use_ozone is true, disable this
+// factory method for OS_LINUX as Linux has a factory method that decides what
+// UIControls to use based on IsUsingOzonePlatform feature flag.
+#if !defined(OS_LINUX)
+ui_controls::UIControlsAura* CreateUIControlsAura(WindowTreeHost* host) {
+ return new UIControlsOzone(host);
+}
+#endif
+
+} // namespace test
+} // namespace aura
diff --git a/ui/aura/test/ui_controls_ozone.h b/ui/aura/test/ui_controls_ozone.h
new file mode 100644
index 0000000..e85844f
--- /dev/null
+++ b/ui/aura/test/ui_controls_ozone.h
@@ -0,0 +1,135 @@
+// 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_AURA_TEST_UI_CONTROLS_OZONE_H_
+#define UI_AURA_TEST_UI_CONTROLS_OZONE_H_
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "ui/aura/env.h"
+#include "ui/aura/test/aura_test_utils.h"
+#include "ui/aura/test/env_test_helper.h"
+#include "ui/aura/test/ui_controls_factory_aura.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/base/test/ui_controls_aura.h"
+#include "ui/display/display.h"
+#include "ui/display/screen.h"
+#include "ui/events/event_utils.h"
+#include "ui/events/test/events_test_utils.h"
+#include "ui/gfx/geometry/point_conversions.h"
+
+namespace aura {
+namespace test {
+
+class UIControlsOzone : public ui_controls::UIControlsAura {
+ public:
+ explicit UIControlsOzone(WindowTreeHost* host);
+ UIControlsOzone(const UIControlsOzone&) = delete;
+ UIControlsOzone& operator=(const UIControlsOzone&) = delete;
+ ~UIControlsOzone() override;
+
+ private:
+ // ui_controls::UIControlsAura:
+ bool SendKeyPress(gfx::NativeWindow window,
+ ui::KeyboardCode key,
+ bool control,
+ bool shift,
+ bool alt,
+ bool command) override;
+ bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
+ ui::KeyboardCode key,
+ bool control,
+ bool shift,
+ bool alt,
+ bool command,
+ base::OnceClosure closure) override;
+ bool SendMouseMove(int screen_x, int screen_y) override;
+ bool SendMouseMoveNotifyWhenDone(int screen_x,
+ int screen_y,
+ base::OnceClosure closure) override;
+ bool SendMouseEvents(ui_controls::MouseButton type,
+ int button_state,
+ int accelerator_state) override;
+ bool SendMouseEventsNotifyWhenDone(ui_controls::MouseButton type,
+ int button_state,
+ base::OnceClosure closure,
+ int accelerator_state) override;
+ bool SendMouseClick(ui_controls::MouseButton type) override;
+#if defined(OS_CHROMEOS)
+ bool SendTouchEvents(int action, int id, int x, int y) override;
+ bool SendTouchEventsNotifyWhenDone(int action,
+ int id,
+ int x,
+ int y,
+ base::OnceClosure task) override;
+#endif
+
+ // Use |optional_host| to specify the host.
+ // When |optional_host| is not null, event will be sent to |optional_host|.
+ // When |optional_host| is null, event will be sent to the default host.
+ void SendEventToSink(ui::Event* event,
+ int64_t display_id,
+ base::OnceClosure closure,
+ WindowTreeHost* optional_host = nullptr);
+
+ void PostKeyEvent(ui::EventType type,
+ ui::KeyboardCode key_code,
+ int flags,
+ int64_t display_id,
+ base::OnceClosure closure,
+ WindowTreeHost* optional_host = nullptr);
+
+ void PostKeyEventTask(ui::EventType type,
+ ui::KeyboardCode key_code,
+ int flags,
+ int64_t display_id,
+ base::OnceClosure closure,
+ WindowTreeHost* optional_host);
+
+ void PostMouseEvent(ui::EventType type,
+ const gfx::PointF& host_location,
+ int flags,
+ int changed_button_flags,
+ int64_t display_id,
+ base::OnceClosure closure);
+
+ void PostMouseEventTask(ui::EventType type,
+ const gfx::PointF& host_location,
+ int flags,
+ int changed_button_flags,
+ int64_t display_id,
+ base::OnceClosure closure);
+
+ void PostTouchEvent(ui::EventType type,
+ const gfx::PointF& host_location,
+ int id,
+ int64_t display_id,
+ base::OnceClosure closure);
+
+ void PostTouchEventTask(ui::EventType type,
+ const gfx::PointF& host_location,
+ int id,
+ int64_t display_id,
+ base::OnceClosure closure);
+
+ bool ScreenDIPToHostPixels(gfx::PointF* location, int64_t* display_id);
+
+ // This is the default host used for events that are not scoped to a window.
+ // Events scoped to a window always use the window's host.
+ WindowTreeHost* const host_;
+
+ // Mask of the mouse buttons currently down. This is static as it needs to
+ // track the state globally for all displays. A UIControlsOzone instance is
+ // created for each display host.
+ static unsigned button_down_mask_;
+};
+
+} // namespace test
+} // namespace aura
+
+#endif // UI_AURA_TEST_UI_CONTROLS_OZONE_H_