Skip to content

Commit

Permalink
ui_controls: Add SendKeyEvents API to send key press/release separately
Browse files Browse the repository at this point in the history
This CL adds ui_controls::SendKeyEvents().
It enables test to send press and release events separately.
This will unblock TooltipControllerTest on Lacros.

Bug: 1414800
Change-Id: Id56cb604a536308b79293b19341ef6967c9f15c2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4240900
Commit-Queue: Eriko Kurimoto <elkurin@chromium.org>
Reviewed-by: Scott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1105515}
  • Loading branch information
elkurin authored and Chromium LUCI CQ committed Feb 15, 2023
1 parent 011d12f commit 42593c8
Show file tree
Hide file tree
Showing 20 changed files with 470 additions and 332 deletions.
33 changes: 15 additions & 18 deletions ash/test/ui_controls_factory_ash.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,29 +60,26 @@ class UIControlsAsh : public UIControlsAura {
~UIControlsAsh() override = default;

// UIControslAura overrides:
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 SendKeyEvents(gfx::NativeWindow window,
ui::KeyboardCode key,
int key_event_types,
int accelerator_state) override {
return SendKeyEventsNotifyWhenDone(window, key, key_event_types,
base::OnceClosure(), accelerator_state);
}

bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
ui::KeyboardCode key,
bool control,
bool shift,
bool alt,
bool command,
base::OnceClosure closure) override {
bool SendKeyEventsNotifyWhenDone(gfx::NativeWindow window,
ui::KeyboardCode key,
int key_event_types,
base::OnceClosure closure,
int accelerator_state) override {
aura::Window* root = window ? window->GetRootWindow()
: ash::Shell::GetRootWindowForNewWindows();
UIControlsAura* ui_controls = GetUIControlsForRootWindow(root);
return ui_controls &&
ui_controls->SendKeyPressNotifyWhenDone(
window, key, control, shift, alt, command, std::move(closure));

return ui_controls && ui_controls->SendKeyEventsNotifyWhenDone(
window, key, key_event_types, std::move(closure),
accelerator_state);
}

bool SendMouseMove(int x, int y) override {
Expand Down
55 changes: 32 additions & 23 deletions ui/aura/test/ui_controls_factory_aurawin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,31 +32,40 @@ class UIControlsWin : public UIControlsAura {
UIControlsWin& operator=(const UIControlsWin&) = delete;

// UIControlsAura overrides:
bool SendKeyPress(gfx::NativeWindow native_window,
ui::KeyboardCode key,
bool control,
bool shift,
bool alt,
bool command) override {
DCHECK(!command); // No command key on Aura
HWND window =
native_window->GetHost()->GetAcceleratedWidget();
return ui_controls::internal::SendKeyPressImpl(window, key, control, shift,
alt, base::OnceClosure());
bool SendKeyEvents(gfx::NativeWindow native_window,
ui::KeyboardCode key,
int key_event_types,
int accelerator_state) override {
// UIControlsWin only supports key events with both press and release.
// TODO(crbug.com/1414800): Support any `key_event_types` on win.
DCHECK_EQ(key_event_types,
ui_controls::kKeyPress | ui_controls::kKeyRelease);

// No command key on Aura.
DCHECK(!(accelerator_state & ui_controls::kCommand));

HWND window = native_window->GetHost()->GetAcceleratedWidget();
return ui_controls::internal::SendKeyPressImpl(
window, key, accelerator_state, base::OnceClosure());
}
bool SendKeyPressNotifyWhenDone(gfx::NativeWindow native_window,
ui::KeyboardCode key,
bool control,
bool shift,
bool alt,
bool command,
base::OnceClosure task) override {
DCHECK(!command); // No command key on Aura
HWND window =
native_window->GetHost()->GetAcceleratedWidget();
return ui_controls::internal::SendKeyPressImpl(window, key, control, shift,
alt, std::move(task));
bool SendKeyEventsNotifyWhenDone(gfx::NativeWindow native_window,
ui::KeyboardCode key,
int key_event_types,
base::OnceClosure task,
int accelerator_state) override {
// UIControlsWin only supports key events with both press and release.
// TODO(crbug.com/1414800): Support any `key_event_types` on win.
DCHECK_EQ(key_event_types,
ui_controls::kKeyPress | ui_controls::kKeyRelease);

// No command key on Aura.
DCHECK(!(accelerator_state & ui_controls::kCommand));

HWND window = native_window->GetHost()->GetAcceleratedWidget();
return ui_controls::internal::SendKeyPressImpl(
window, key, accelerator_state, std::move(task));
}

bool SendMouseMove(int screen_x, int screen_y) override {
return ui_controls::internal::SendMouseMoveImpl(screen_x, screen_y,
base::OnceClosure());
Expand Down
149 changes: 80 additions & 69 deletions ui/aura/test/ui_controls_ozone.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,19 @@ 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::SendKeyEvents(gfx::NativeWindow window,
ui::KeyboardCode key,
int key_event_types,
int accelerator_state) {
return SendKeyEventsNotifyWhenDone(window, key, key_event_types,
base::OnceClosure(), accelerator_state);
}

bool UIControlsOzone::SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
ui::KeyboardCode key,
bool control,
bool shift,
bool alt,
bool command,
base::OnceClosure closure) {
bool UIControlsOzone::SendKeyEventsNotifyWhenDone(gfx::NativeWindow window,
ui::KeyboardCode key,
int key_event_types,
base::OnceClosure closure,
int accelerator_state) {
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.
Expand All @@ -49,69 +45,84 @@ bool UIControlsOzone::SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
optional_host = window->GetHost();
#endif

bool has_press = key_event_types & ui_controls::kKeyPress;
bool has_release = key_event_types & ui_controls::kKeyRelease;

bool has_control = accelerator_state & ui_controls::kControl;
bool has_shift = accelerator_state & ui_controls::kShift;
bool has_command = accelerator_state & ui_controls::kCommand;
bool has_alt = accelerator_state & ui_controls::kAlt;

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),
if (has_press) {
if (has_control) {
flags |= ui::EF_CONTROL_DOWN;
PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, flags, display_id,
base::OnceClosure(), optional_host);
}

if (has_shift) {
flags |= ui::EF_SHIFT_DOWN;
PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, flags, display_id,
base::OnceClosure(), optional_host);
}

if (has_alt) {
flags |= ui::EF_ALT_DOWN;
PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_MENU, flags, display_id,
base::OnceClosure(), optional_host);
}

if (has_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,
has_release ? 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),
if (has_release) {
PostKeyEvent(ui::ET_KEY_RELEASED, key, flags, display_id,
(has_control || has_shift || has_alt || has_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);
if (has_alt) {
flags &= ~ui::EF_ALT_DOWN;
PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_MENU, flags, display_id,
(has_shift || has_control || has_command)
? base::OnceClosure()
: std::move(closure),
optional_host);
}

if (has_shift) {
flags &= ~ui::EF_SHIFT_DOWN;
PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, flags, display_id,
(has_control || has_command) ? base::OnceClosure()
: std::move(closure),
optional_host);
}

if (has_control) {
flags &= ~ui::EF_CONTROL_DOWN;
PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL, flags, display_id,
has_command ? base::OnceClosure() : std::move(closure),
optional_host);
}

if (has_command) {
flags &= ~ui::EF_COMMAND_DOWN;
PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_LWIN, flags, display_id,
std::move(closure), optional_host);
}
}

return true;
Expand Down
22 changes: 9 additions & 13 deletions ui/aura/test/ui_controls_ozone.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,15 @@ class UIControlsOzone : public ui_controls::UIControlsAura {

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 SendKeyEvents(gfx::NativeWindow window,
ui::KeyboardCode key,
int key_event_types,
int accelerator_state) override;
bool SendKeyEventsNotifyWhenDone(gfx::NativeWindow window,
ui::KeyboardCode key,
int key_event_types,
base::OnceClosure closure,
int accelerator_state) override;
bool SendMouseMove(int screen_x, int screen_y) override;
bool SendMouseMoveNotifyWhenDone(int screen_x,
int screen_y,
Expand Down
1 change: 1 addition & 0 deletions ui/base/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,7 @@ static_library("test_support") {
"test/mock_base_window.h",
"test/test_dialog_model_host.cc",
"test/test_dialog_model_host.h",
"test/ui_controls.cc",
"test/ui_controls.h",
"test/view_tree_validator.h",
]
Expand Down
27 changes: 27 additions & 0 deletions ui/base/test/ui_controls.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/base/test/ui_controls.h"

namespace ui_controls {

int GenerateAcceleratorState(bool control, bool shift, bool alt, bool command) {
int accelerator_state = ui_controls::kNoAccelerator;
if (control) {
accelerator_state |= ui_controls::kControl;
}
if (shift) {
accelerator_state |= ui_controls::kShift;
}
if (alt) {
accelerator_state |= ui_controls::kAlt;
}
if (command) {
accelerator_state |= ui_controls::kCommand;
}

return accelerator_state;
}

} // namespace ui_controls

0 comments on commit 42593c8

Please sign in to comment.