Commit 1000bbb0 authored by Alexander Dunaev's avatar Alexander Dunaev Committed by Commit Bot

[ozone/x11] Enabled UserInputMonitor.

The UserInputMonitorLinux depends on X11 directly and cannot be used by
Ozone platforms because of that.

This CL introduces a new platform interface for the user input monitor,
and moves the X11 implementation to //ui/base/x.  The
UserInputMonitorLinux now uses either the X11 implementation directly
(when X11 is enabled but Ozone is not) or requests the platform
implementation when Ozone is enabled.

Bug: 1116414
Change-Id: I0a21074f2fe028fea13c7efb33ddf9d102c9f35c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2489863
Commit-Queue: Alexander Dunaev <adunaev@igalia.com>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarRobert Kroeger <rjkroege@chromium.org>
Reviewed-by: default avatarThomas Anderson <thomasanderson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#821657}
parent 182b48d8
......@@ -123,6 +123,13 @@ component("media") {
if (is_apple) {
public_deps += [ "//media/base/mac" ]
}
if (use_x11) {
deps += [ "//ui/base/x" ]
}
if (use_ozone) {
deps += [ "//ui/ozone" ]
}
}
# Note: This can't be a static_library since it does not have any sources.
......
......@@ -23,6 +23,7 @@ include_rules = [
"+third_party/opus",
"+third_party/skia",
"+ui/base/ui_base_features.h",
"+ui/base/x/x11_user_input_monitor.h",
"+ui/display",
"+ui/events",
"+ui/gfx",
......
......@@ -6,6 +6,7 @@ import("//build/config/android/config.gni")
import("//build/config/arm.gni")
import("//build/config/features.gni")
import("//build/config/linux/pkg_config.gni")
import("//build/config/ozone.gni")
import("//build/config/ui.gni")
import("//media/media_options.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
......@@ -363,6 +364,7 @@ source_set("base") {
"//third_party/libyuv",
"//third_party/widevine/cdm:headers",
"//ui/display:display",
"//ui/events:events",
"//ui/events:events_base",
"//url:url",
]
......@@ -388,7 +390,7 @@ source_set("base") {
deps += [ "//third_party/libvpx" ]
}
if (use_x11) {
if (use_x11 || ozone_platform_x11) {
sources += [ "user_input_monitor_linux.cc" ]
deps += [
"//ui/base:features",
......@@ -409,12 +411,11 @@ source_set("base") {
} else {
defines += [ "DISABLE_USER_INPUT_MONITOR" ]
}
if (is_linux || is_chromeos || is_win) {
sources += [
"keyboard_event_counter.cc",
"keyboard_event_counter.h",
]
if (use_x11) {
deps += [ "//ui/base/x" ]
}
if (use_ozone) {
deps += [ "//ui/ozone" ]
}
# Note: should also work on is_posix || is_fuchsia
......@@ -628,9 +629,6 @@ source_set("unit_tests") {
deps += [ "//media/base/mac:unit_tests" ]
}
if (is_linux || is_chromeos || is_win) {
sources += [ "keyboard_event_counter_unittest.cc" ]
}
if (is_win) {
sources += [ "win/dxgi_device_scope_handle_unittest.cc" ]
deps += [ "//media/base/win:media_foundation_util" ]
......
......@@ -19,55 +19,84 @@
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "base/task/current_thread.h"
#include "media/base/keyboard_event_counter.h"
#include "third_party/skia/include/core/SkPoint.h"
#include "ui/base/ui_base_features.h"
#include "ui/events/devices/x11/xinput_util.h"
#include "ui/events/keyboard_event_counter.h"
#include "ui/events/keycodes/keyboard_code_conversion_x.h"
#include "ui/gfx/x/xinput.h"
#if defined(USE_X11)
#include "ui/base/x/x11_user_input_monitor.h" // nogncheck
#endif
#if defined(USE_OZONE)
#include "ui/base/ui_base_features.h" // nogncheck
#include "ui/ozone/public/ozone_platform.h" // nogncheck
#include "ui/ozone/public/platform_user_input_monitor.h" // nogncheck
#endif
namespace media {
namespace {
// This is the actual implementation of event monitoring. It's separated from
// UserInputMonitorLinux since it needs to be deleted on the IO thread.
class UserInputMonitorLinuxCore
: public base::SupportsWeakPtr<UserInputMonitorLinuxCore>,
public base::CurrentThread::DestructionObserver,
public x11::Connection::Delegate {
public:
explicit UserInputMonitorLinuxCore(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
~UserInputMonitorLinuxCore() override;
// base::CurrentThread::DestructionObserver:
void WillDestroyCurrentMessageLoop() override;
using WriteKeyPressCallback =
base::RepeatingCallback<void(const base::WritableSharedMemoryMapping& shmem,
uint32_t count)>;
// x11::Connection::Delegate:
bool ShouldContinueStream() const override;
void DispatchXEvent(x11::Event* event) override;
// Provides a unified interface for using user input monitors of unrelated
// classes.
// TODO(crbug.com/1096425): remove this when non-Ozone path is deprecated.
class UserInputMonitorAdapter
: public base::SupportsWeakPtr<UserInputMonitorAdapter> {
public:
UserInputMonitorAdapter() = default;
UserInputMonitorAdapter(const UserInputMonitorAdapter&) = delete;
UserInputMonitorAdapter& operator=(const UserInputMonitorAdapter&) = delete;
virtual ~UserInputMonitorAdapter() = default;
virtual uint32_t GetKeyPressCount() const = 0;
virtual void StartMonitor(WriteKeyPressCallback callback) = 0;
virtual void StartMonitorWithMapping(
WriteKeyPressCallback callback,
base::WritableSharedMemoryMapping mapping) = 0;
virtual void StopMonitor() = 0;
};
uint32_t GetKeyPressCount() const;
void StartMonitor();
void StartMonitorWithMapping(base::WritableSharedMemoryMapping mapping);
void StopMonitor();
// Wraps a specific user input monitor into UserInputMonitorAdapter interface.
template <typename Impl>
class UserInputMonitorLinuxCore : public UserInputMonitorAdapter {
public:
explicit UserInputMonitorLinuxCore(std::unique_ptr<Impl> user_input_monitor)
: user_input_monitor_(std::move(user_input_monitor)) {}
UserInputMonitorLinuxCore(const UserInputMonitorLinuxCore&) = delete;
UserInputMonitorLinuxCore operator=(const UserInputMonitorLinuxCore&) =
delete;
~UserInputMonitorLinuxCore() override = default;
uint32_t GetKeyPressCount() const override {
if (!user_input_monitor_)
return 0;
return user_input_monitor_->GetKeyPressCount();
}
void StartMonitor(WriteKeyPressCallback callback) override {
if (!user_input_monitor_)
return;
user_input_monitor_->StartMonitor(callback);
}
void StartMonitorWithMapping(
WriteKeyPressCallback callback,
base::WritableSharedMemoryMapping mapping) override {
if (!user_input_monitor_)
return;
user_input_monitor_->StartMonitorWithMapping(callback, std::move(mapping));
}
void StopMonitor() override {
if (!user_input_monitor_)
return;
user_input_monitor_->StopMonitor();
}
private:
void OnConnectionData();
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
// Used for sharing key press count value.
std::unique_ptr<base::WritableSharedMemoryMapping> key_press_count_mapping_;
//
// The following members should only be accessed on the IO thread.
//
std::unique_ptr<base::FileDescriptorWatcher::Controller> watch_controller_;
std::unique_ptr<x11::Connection> connection_;
KeyboardEventCounter counter_;
DISALLOW_COPY_AND_ASSIGN(UserInputMonitorLinuxCore);
std::unique_ptr<Impl> user_input_monitor_;
};
class UserInputMonitorLinux : public UserInputMonitorBase {
......@@ -87,130 +116,27 @@ class UserInputMonitorLinux : public UserInputMonitorBase {
void StopKeyboardMonitoring() override;
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
UserInputMonitorLinuxCore* core_;
UserInputMonitorAdapter* core_;
DISALLOW_COPY_AND_ASSIGN(UserInputMonitorLinux);
};
UserInputMonitorLinuxCore::UserInputMonitorLinuxCore(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
: io_task_runner_(io_task_runner) {}
UserInputMonitorLinuxCore::~UserInputMonitorLinuxCore() {
DCHECK(!connection_);
}
void UserInputMonitorLinuxCore::WillDestroyCurrentMessageLoop() {
DCHECK(io_task_runner_->BelongsToCurrentThread());
StopMonitor();
}
bool UserInputMonitorLinuxCore::ShouldContinueStream() const {
return true;
}
void UserInputMonitorLinuxCore::DispatchXEvent(x11::Event* event) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
auto* raw = event->As<x11::Input::RawDeviceEvent>();
if (!raw || (raw->opcode != x11::Input::RawDeviceEvent::RawKeyPress &&
raw->opcode != x11::Input::RawDeviceEvent::RawKeyRelease)) {
return;
}
ui::EventType type = raw->opcode == x11::Input::RawDeviceEvent::RawKeyPress
? ui::ET_KEY_PRESSED
: ui::ET_KEY_RELEASED;
auto key_sym =
connection_->KeycodeToKeysym(static_cast<x11::KeyCode>(raw->detail), 0);
ui::KeyboardCode key_code = ui::KeyboardCodeFromXKeysym(key_sym);
counter_.OnKeyboardEvent(type, key_code);
// Update count value in shared memory.
if (key_press_count_mapping_)
WriteKeyPressMonitorCount(*key_press_count_mapping_, GetKeyPressCount());
}
uint32_t UserInputMonitorLinuxCore::GetKeyPressCount() const {
return counter_.GetKeyPressCount();
}
void UserInputMonitorLinuxCore::StartMonitor() {
DCHECK(io_task_runner_->BelongsToCurrentThread());
// TODO(https://crbug.com/1116414): support UserInputMonitorLinux on
// Ozone/Linux.
UserInputMonitorAdapter* CreateUserInputMonitor(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) {
#if defined(USE_OZONE)
if (features::IsUsingOzonePlatform()) {
NOTIMPLEMENTED_LOG_ONCE();
StopMonitor();
return;
return new UserInputMonitorLinuxCore<ui::PlatformUserInputMonitor>(
ui::OzonePlatform::GetInstance()->GetPlatformUserInputMonitor(
io_task_runner));
}
if (!connection_) {
// TODO(jamiewalch): We should pass the connection in.
if (auto* connection = x11::Connection::Get()) {
connection_ = x11::Connection::Get()->Clone();
} else {
LOG(ERROR) << "Couldn't open X connection";
StopMonitor();
return;
}
}
if (!connection_->xinput().present()) {
LOG(ERROR) << "X Input extension not available.";
StopMonitor();
return;
}
// Let the server know the client XInput version.
connection_->xinput().XIQueryVersion(
{x11::Input::major_version, x11::Input::minor_version});
x11::Input::XIEventMask mask;
ui::SetXinputMask(&mask, x11::Input::RawDeviceEvent::RawKeyPress);
ui::SetXinputMask(&mask, x11::Input::RawDeviceEvent::RawKeyRelease);
connection_->xinput().XISelectEvents(
{connection_->default_root(),
{{x11::Input::DeviceId::AllMaster, {mask}}}});
connection_->Flush();
// Register OnConnectionData() to be called every time there is something to
// read from |connection_|.
watch_controller_ = base::FileDescriptorWatcher::WatchReadable(
connection_->GetFd(),
base::BindRepeating(&UserInputMonitorLinuxCore::OnConnectionData,
base::Unretained(this)));
// Start observing message loop destruction if we start monitoring the first
// event.
base::CurrentThread::Get()->AddDestructionObserver(this);
// Fetch pending events if any.
OnConnectionData();
}
void UserInputMonitorLinuxCore::StartMonitorWithMapping(
base::WritableSharedMemoryMapping mapping) {
StartMonitor();
key_press_count_mapping_ =
std::make_unique<base::WritableSharedMemoryMapping>(std::move(mapping));
}
void UserInputMonitorLinuxCore::StopMonitor() {
DCHECK(io_task_runner_->BelongsToCurrentThread());
watch_controller_.reset();
connection_.reset();
key_press_count_mapping_.reset();
// Stop observing message loop destruction if no event is being monitored.
base::CurrentThread::Get()->RemoveDestructionObserver(this);
}
void UserInputMonitorLinuxCore::OnConnectionData() {
DCHECK(io_task_runner_->BelongsToCurrentThread());
connection_->Dispatch(this);
#endif
#if defined(USE_X11)
return new UserInputMonitorLinuxCore<ui::XUserInputMonitor>(
std::make_unique<ui::XUserInputMonitor>(io_task_runner));
#else
NOTREACHED();
return nullptr;
#endif
}
//
......@@ -220,34 +146,44 @@ void UserInputMonitorLinuxCore::OnConnectionData() {
UserInputMonitorLinux::UserInputMonitorLinux(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
: io_task_runner_(io_task_runner),
core_(new UserInputMonitorLinuxCore(io_task_runner)) {}
core_(CreateUserInputMonitor(io_task_runner_)) {}
UserInputMonitorLinux::~UserInputMonitorLinux() {
if (!io_task_runner_->DeleteSoon(FROM_HERE, core_))
if (core_ && !io_task_runner_->DeleteSoon(FROM_HERE, core_))
delete core_;
}
uint32_t UserInputMonitorLinux::GetKeyPressCount() const {
if (!core_)
return 0;
return core_->GetKeyPressCount();
}
void UserInputMonitorLinux::StartKeyboardMonitoring() {
if (!core_)
return;
io_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&UserInputMonitorLinuxCore::StartMonitor,
core_->AsWeakPtr()));
FROM_HERE,
base::BindOnce(&UserInputMonitorAdapter::StartMonitor, core_->AsWeakPtr(),
base::BindRepeating(&WriteKeyPressMonitorCount)));
}
void UserInputMonitorLinux::StartKeyboardMonitoring(
base::WritableSharedMemoryMapping mapping) {
if (!core_)
return;
io_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&UserInputMonitorLinuxCore::StartMonitorWithMapping,
core_->AsWeakPtr(), std::move(mapping)));
base::BindOnce(
&UserInputMonitorAdapter::StartMonitorWithMapping, core_->AsWeakPtr(),
base::BindRepeating(&WriteKeyPressMonitorCount), std::move(mapping)));
}
void UserInputMonitorLinux::StopKeyboardMonitoring() {
if (!core_)
return;
io_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&UserInputMonitorLinuxCore::StopMonitor,
FROM_HERE, base::BindOnce(&UserInputMonitorAdapter::StopMonitor,
core_->AsWeakPtr()));
}
......
......@@ -17,9 +17,21 @@
#include "base/files/file_descriptor_watcher_posix.h"
#endif
#if defined(USE_OZONE)
#include "ui/base/ui_base_features.h" // nogncheck
#endif
namespace media {
TEST(UserInputMonitorTest, CreatePlatformSpecific) {
#if defined(USE_OZONE)
// TODO(crbug.com/1109112): enable those tests for Ozone.
// Here, the only issue why they don't work is that the Ozone platform is not
// initialised.
if (features::IsUsingOzonePlatform())
return;
#endif
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
base::test::TaskEnvironment task_environment(
base::test::TaskEnvironment::MainThreadType::IO);
......@@ -42,6 +54,14 @@ TEST(UserInputMonitorTest, CreatePlatformSpecific) {
}
TEST(UserInputMonitorTest, CreatePlatformSpecificWithMapping) {
#if defined(USE_OZONE)
// TODO(crbug.com/1109112): enable those tests for Ozone.
// Here, the only issue why they don't work is that the Ozone platform is not
// initialised.
if (features::IsUsingOzonePlatform())
return;
#endif
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
base::test::TaskEnvironment task_environment(
base::test::TaskEnvironment::MainThreadType::IO);
......
......@@ -17,8 +17,8 @@
#include "base/synchronization/lock.h"
#include "base/task/current_thread.h"
#include "base/win/message_window.h"
#include "media/base/keyboard_event_counter.h"
#include "third_party/skia/include/core/SkPoint.h"
#include "ui/events/keyboard_event_counter.h"
#include "ui/events/keycodes/keyboard_code_conversion_win.h"
namespace media {
......@@ -77,7 +77,7 @@ class UserInputMonitorWinCore
// These members are only accessed on the UI thread.
std::unique_ptr<base::win::MessageWindow> window_;
KeyboardEventCounter counter_;
ui::KeyboardEventCounter counter_;
DISALLOW_COPY_AND_ASSIGN(UserInputMonitorWinCore);
};
......
......@@ -42,6 +42,8 @@ component("x") {
"x11_topmost_window_finder.h",
"x11_ui_thread.cc",
"x11_ui_thread.h",
"x11_user_input_monitor.cc",
"x11_user_input_monitor.h",
"x11_util.cc",
"x11_util.h",
"x11_whole_screen_move_loop.cc",
......
// 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/x11_user_input_monitor.h"
#include "base/logging.h"
#include "ui/events/devices/x11/xinput_util.h"
#include "ui/events/keycodes/keyboard_code_conversion_x.h"
namespace ui {
XUserInputMonitor::XUserInputMonitor(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
: io_task_runner_(io_task_runner) {}
XUserInputMonitor::~XUserInputMonitor() {
DCHECK(!connection_);
}
void XUserInputMonitor::WillDestroyCurrentMessageLoop() {
DCHECK(io_task_runner_->BelongsToCurrentThread());
StopMonitor();
}
bool XUserInputMonitor::ShouldContinueStream() const {
return true;
}
void XUserInputMonitor::DispatchXEvent(x11::Event* event) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
DCHECK(write_key_press_callback_);
auto* raw = event->As<x11::Input::RawDeviceEvent>();
if (!raw || (raw->opcode != x11::Input::RawDeviceEvent::RawKeyPress &&
raw->opcode != x11::Input::RawDeviceEvent::RawKeyRelease)) {
return;
}
EventType type = raw->opcode == x11::Input::RawDeviceEvent::RawKeyPress
? ET_KEY_PRESSED
: ET_KEY_RELEASED;
auto key_sym =
connection_->KeycodeToKeysym(static_cast<x11::KeyCode>(raw->detail), 0);
KeyboardCode key_code = KeyboardCodeFromXKeysym(key_sym);
counter_.OnKeyboardEvent(type, key_code);
// Update count value in shared memory.
if (key_press_count_mapping_) {
write_key_press_callback_.Run(*key_press_count_mapping_,
GetKeyPressCount());
}
}
uint32_t XUserInputMonitor::GetKeyPressCount() const {
return counter_.GetKeyPressCount();
}
void XUserInputMonitor::StartMonitor(WriteKeyPressCallback& callback) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
write_key_press_callback_ = callback;
if (!connection_) {
// TODO(jamiewalch): We should pass the connection in.
if (auto* connection = x11::Connection::Get()) {
connection_ = x11::Connection::Get()->Clone();
} else {
LOG(ERROR) << "Couldn't open X connection";
StopMonitor();
return;
}
}
if (!connection_->xinput().present()) {
LOG(ERROR) << "X Input extension not available.";
StopMonitor();
return;
}
// Let the server know the client XInput version.
connection_->xinput().XIQueryVersion(
{x11::Input::major_version, x11::Input::minor_version});
x11::Input::XIEventMask mask;
SetXinputMask(&mask, x11::Input::RawDeviceEvent::RawKeyPress);
SetXinputMask(&mask, x11::Input::RawDeviceEvent::RawKeyRelease);
connection_->xinput().XISelectEvents(
{connection_->default_root(),
{{x11::Input::DeviceId::AllMaster, {mask}}}});
connection_->Flush();
// Register OnConnectionData() to be called every time there is something to
// read from |connection_|.
watch_controller_ = base::FileDescriptorWatcher::WatchReadable(
connection_->GetFd(),
base::BindRepeating(&XUserInputMonitor::OnConnectionData,
base::Unretained(this)));
// Start observing message loop destruction if we start monitoring the first
// event.
base::CurrentThread::Get()->AddDestructionObserver(this);
// Fetch pending events if any.
OnConnectionData();
}
void XUserInputMonitor::StartMonitorWithMapping(
WriteKeyPressCallback& callback,
base::WritableSharedMemoryMapping mapping) {
StartMonitor(callback);
key_press_count_mapping_ =
std::make_unique<base::WritableSharedMemoryMapping>(std::move(mapping));
}
void XUserInputMonitor::StopMonitor() {
DCHECK(io_task_runner_->BelongsToCurrentThread());
watch_controller_.reset();
connection_.reset();
key_press_count_mapping_.reset();
// Stop observing message loop destruction if no event is being monitored.
base::CurrentThread::Get()->RemoveDestructionObserver(this);
}
void XUserInputMonitor::OnConnectionData() {
DCHECK(io_task_runner_->BelongsToCurrentThread());
connection_->Dispatch(this);
}
} // 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_X11_USER_INPUT_MONITOR_H_
#define UI_BASE_X_X11_USER_INPUT_MONITOR_H_
#include <memory>
#include "base/component_export.h"
#include "base/files/file_descriptor_watcher_posix.h"
#include "base/memory/shared_memory_mapping.h"
#include "base/single_thread_task_runner.h"
#include "base/task/current_thread.h"
#include "ui/events/keyboard_event_counter.h"
#include "ui/gfx/x/connection.h"
#include "ui/gfx/x/xinput.h"
namespace ui {
// This is the actual implementation of event monitoring. It's separated from
// UserInputMonitorLinux since it needs to be deleted on the IO thread.
class COMPONENT_EXPORT(UI_BASE_X) XUserInputMonitor
: public base::SupportsWeakPtr<XUserInputMonitor>,
public base::CurrentThread::DestructionObserver,
public x11::Connection::Delegate {
public:
using WriteKeyPressCallback = base::RepeatingCallback<
void(const base::WritableSharedMemoryMapping& shmem, uint32_t count)>;
explicit XUserInputMonitor(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
XUserInputMonitor(const XUserInputMonitor&) = delete;
XUserInputMonitor& operator=(const XUserInputMonitor&) = delete;
~XUserInputMonitor() override;
uint32_t GetKeyPressCount() const;
void StartMonitor(WriteKeyPressCallback& callback);
void StartMonitorWithMapping(WriteKeyPressCallback& callback,
base::WritableSharedMemoryMapping mapping);
void StopMonitor();
private:
// base::CurrentThread::DestructionObserver:
void WillDestroyCurrentMessageLoop() override;
// x11::Connection::Delegate:
bool ShouldContinueStream() const override;
void DispatchXEvent(x11::Event* event) override;
void OnConnectionData();
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
// Used for sharing key press count value.
std::unique_ptr<base::WritableSharedMemoryMapping> key_press_count_mapping_;
// The following members should only be accessed on the IO thread.
std::unique_ptr<base::FileDescriptorWatcher::Controller> watch_controller_;
std::unique_ptr<x11::Connection> connection_;
KeyboardEventCounter counter_;
WriteKeyPressCallback write_key_press_callback_;
};
} // namespace ui
#endif // UI_BASE_X_X11_USER_INPUT_MONITOR_H_
......@@ -255,6 +255,11 @@ component("events") {
]
}
if (is_linux || is_chromeos || is_win) {
public += [ "keyboard_event_counter.h" ]
sources += [ "keyboard_event_counter.cc" ]
}
defines = [ "EVENTS_IMPLEMENTATION" ]
public_deps = [
......@@ -579,6 +584,9 @@ if (!is_ios) {
"win/modifier_keyboard_hook_win_unittest.cc",
]
}
if (is_linux || is_chromeos || is_win) {
sources += [ "keyboard_event_counter_unittest.cc" ]
}
deps = [
":dom_keyboard_layout",
......
......@@ -2,26 +2,26 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/base/keyboard_event_counter.h"
#include "ui/events/keyboard_event_counter.h"
#include "base/check_op.h"
namespace media {
namespace ui {
KeyboardEventCounter::KeyboardEventCounter() : total_key_presses_(0) {}
KeyboardEventCounter::~KeyboardEventCounter() = default;
void KeyboardEventCounter::OnKeyboardEvent(ui::EventType event,
ui::KeyboardCode key_code) {
void KeyboardEventCounter::OnKeyboardEvent(EventType event,
KeyboardCode key_code) {
// Updates the pressed keys and the total count of key presses.
if (event == ui::ET_KEY_PRESSED) {
if (event == ET_KEY_PRESSED) {
if (pressed_keys_.find(key_code) != pressed_keys_.end())
return;
pressed_keys_.insert(key_code);
++total_key_presses_;
} else {
DCHECK_EQ(ui::ET_KEY_RELEASED, event);
DCHECK_EQ(ET_KEY_RELEASED, event);
pressed_keys_.erase(key_code);
}
}
......@@ -30,4 +30,4 @@ uint32_t KeyboardEventCounter::GetKeyPressCount() const {
return total_key_presses_.load();
}
} // namespace media
} // namespace ui
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_BASE_KEYBOARD_EVENT_COUNTER_H_
#define MEDIA_BASE_KEYBOARD_EVENT_COUNTER_H_
#ifndef UI_EVENTS_KEYBOARD_EVENT_COUNTER_H_
#define UI_EVENTS_KEYBOARD_EVENT_COUNTER_H_
#include <stddef.h>
......@@ -11,38 +11,38 @@
#include <set>
#include "base/macros.h"
#include "media/base/media_export.h"
#include "ui/events/events_export.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/events/types/event_type.h"
namespace media {
namespace ui {
// This class tracks the total number of keypresses based on the OnKeyboardEvent
// calls it receives from the client.
// Multiple key down events for the same key are counted as one keypress until
// the same key is released.
class MEDIA_EXPORT KeyboardEventCounter {
class EVENTS_EXPORT KeyboardEventCounter {
public:
KeyboardEventCounter();
~KeyboardEventCounter();
// Returns the total number of keypresses since its creation or last Reset()
// call. Can be called on any thread.
// Returns the total number of keypresses since its creation.
// Can be called on any thread.
uint32_t GetKeyPressCount() const;
// The client should call this method on key down or key up events.
// Must be called on a single thread.
void OnKeyboardEvent(ui::EventType event, ui::KeyboardCode key_code);
void OnKeyboardEvent(EventType event, KeyboardCode key_code);
private:
// The set of keys currently held down.
std::set<ui::KeyboardCode> pressed_keys_;
std::set<KeyboardCode> pressed_keys_;
std::atomic<uint32_t> total_key_presses_;
DISALLOW_COPY_AND_ASSIGN(KeyboardEventCounter);
};
} // namespace media
} // namespace ui
#endif // MEDIA_BASE_KEYBOARD_EVENT_COUNTER_H_
#endif // UI_EVENTS_KEYBOARD_EVENT_COUNTER_H_
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/base/keyboard_event_counter.h"
#include "ui/events/keyboard_event_counter.h"
#include <memory>
......@@ -10,9 +10,8 @@
#include "build/build_config.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkPoint.h"
namespace media {
namespace ui {
TEST(KeyboardEventCounterTest, KeyPressCounter) {
KeyboardEventCounter counter;
......@@ -35,4 +34,4 @@ TEST(KeyboardEventCounterTest, KeyPressCounter) {
EXPECT_EQ(2u, counter.GetKeyPressCount());
}
} // namespace media
} // namespace ui
......@@ -94,6 +94,8 @@ component("ozone_base") {
"public/platform_menu_utils.h",
"public/platform_screen.cc",
"public/platform_screen.h",
"public/platform_user_input_monitor.cc",
"public/platform_user_input_monitor.h",
"public/platform_window_surface.h",
"public/surface_factory_ozone.cc",
"public/surface_factory_ozone.h",
......
......@@ -30,6 +30,8 @@ source_set("x11") {
"x11_screen_ozone.h",
"x11_surface_factory.cc",
"x11_surface_factory.h",
"x11_user_input_monitor.cc",
"x11_user_input_monitor.h",
]
deps = [
......
......@@ -32,6 +32,7 @@
#include "ui/ozone/platform/x11/x11_menu_utils.h"
#include "ui/ozone/platform/x11/x11_screen_ozone.h"
#include "ui/ozone/platform/x11/x11_surface_factory.h"
#include "ui/ozone/platform/x11/x11_user_input_monitor.h"
#include "ui/ozone/public/gpu_platform_support_host.h"
#include "ui/ozone/public/input_controller.h"
#include "ui/ozone/public/ozone_platform.h"
......@@ -237,6 +238,12 @@ class OzonePlatformX11 : public OzonePlatform,
x11::Connection::Get()->SetIOErrorHandler(std::move(shutdown_cb));
}
std::unique_ptr<PlatformUserInputMonitor> GetPlatformUserInputMonitor(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
override {
return std::make_unique<X11UserInputMonitor>(std::move(io_task_runner));
}
private:
// Performs initialization steps need by both UI and GPU.
void InitializeCommon(const InitParams& params) {
......
// 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/ozone/platform/x11/x11_user_input_monitor.h"
#include "ui/base/x/x11_user_input_monitor.h"
namespace ui {
X11UserInputMonitor::X11UserInputMonitor(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
: user_input_monitor_(
std::make_unique<ui::XUserInputMonitor>(io_task_runner)) {}
X11UserInputMonitor::~X11UserInputMonitor() = default;
uint32_t X11UserInputMonitor::GetKeyPressCount() const {
return user_input_monitor_->GetKeyPressCount();
}
void X11UserInputMonitor::StartMonitor(
PlatformUserInputMonitor::WriteKeyPressCallback callback) {
user_input_monitor_->StartMonitor(callback);
}
void X11UserInputMonitor::StartMonitorWithMapping(
PlatformUserInputMonitor::WriteKeyPressCallback callback,
base::WritableSharedMemoryMapping mapping) {
user_input_monitor_->StartMonitorWithMapping(callback, std::move(mapping));
}
void X11UserInputMonitor::StopMonitor() {
user_input_monitor_->StopMonitor();
}
} // 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_OZONE_PLATFORM_X11_X11_USER_INPUT_MONITOR_H_
#define UI_OZONE_PLATFORM_X11_X11_USER_INPUT_MONITOR_H_
#include <memory>
#include "ui/ozone/public/platform_user_input_monitor.h"
namespace ui {
class XUserInputMonitor;
class X11UserInputMonitor : public PlatformUserInputMonitor {
public:
explicit X11UserInputMonitor(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
X11UserInputMonitor(const X11UserInputMonitor&) = delete;
X11UserInputMonitor& operator=(const X11UserInputMonitor&) = delete;
~X11UserInputMonitor() override;
// PlatformUserInputMonitor:
uint32_t GetKeyPressCount() const override;
void StartMonitor(
PlatformUserInputMonitor::WriteKeyPressCallback callback) override;
void StartMonitorWithMapping(
PlatformUserInputMonitor::WriteKeyPressCallback callback,
base::WritableSharedMemoryMapping mapping) override;
void StopMonitor() override;
private:
std::unique_ptr<XUserInputMonitor> user_input_monitor_;
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_X11_X11_USER_INPUT_MONITOR_H_
......@@ -15,6 +15,7 @@
#include "ui/ozone/platform_selection.h"
#include "ui/ozone/public/platform_menu_utils.h"
#include "ui/ozone/public/platform_screen.h"
#include "ui/ozone/public/platform_user_input_monitor.h"
namespace ui {
......@@ -131,6 +132,12 @@ void OzonePlatform::AfterSandboxEntry() {
DCHECK(!single_process_);
}
std::unique_ptr<PlatformUserInputMonitor>
OzonePlatform::GetPlatformUserInputMonitor(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) {
return {};
}
void OzonePlatform::PostMainMessageLoopStart(
base::OnceCallback<void()> shutdown_cb) {}
......
......@@ -12,6 +12,7 @@
#include "base/component_export.h"
#include "base/macros.h"
#include "base/message_loop/message_pump_type.h"
#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/bindings/binder_map.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/native_widget_types.h"
......@@ -31,6 +32,7 @@ class PlatformClipboard;
class PlatformGLEGLUtility;
class PlatformMenuUtils;
class PlatformScreen;
class PlatformUserInputMonitor;
class SurfaceFactoryOzone;
class SystemInputInjector;
......@@ -232,6 +234,13 @@ class COMPONENT_EXPORT(OZONE) OzonePlatform {
// issues.
virtual void AfterSandboxEntry();
// Creates a user input monitor.
// The user input comes from I/O devices and must be handled on the IO thread.
// |io_task_runner| must be bound to the IO thread so the implementation could
// ensure that calls happen on the right thread.
virtual std::unique_ptr<PlatformUserInputMonitor> GetPlatformUserInputMonitor(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
protected:
bool has_initialized_ui() const { return initialized_ui_; }
bool has_initialized_gpu() const { return initialized_gpu_; }
......
// 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/ozone/public/platform_user_input_monitor.h"
namespace ui {
PlatformUserInputMonitor::PlatformUserInputMonitor() = default;
PlatformUserInputMonitor::~PlatformUserInputMonitor() = default;
} // 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_OZONE_PUBLIC_PLATFORM_USER_INPUT_MONITOR_H_
#define UI_OZONE_PUBLIC_PLATFORM_USER_INPUT_MONITOR_H_
#include <memory>
#include "base/component_export.h"
#include "base/memory/shared_memory_mapping.h"
#include "base/single_thread_task_runner.h"
namespace ui {
// User input monitor for multimedia streams.
//
// Monitors the keyboard input events in the browser process. Can be provided
// with the shared memory mapping; in such a case should call the callback
// provided via StartMonitor() or StartMonitorWithMapping() every time
// the user presses a key.
class COMPONENT_EXPORT(OZONE_BASE) PlatformUserInputMonitor {
public:
// Via this callback, the platform implementation of the monitor gets the
// WriteKeyPressMonitorCount defined in media/base/user_input_monitor.h.
using WriteKeyPressCallback = base::RepeatingCallback<
void(const base::WritableSharedMemoryMapping& shmem, uint32_t count)>;
PlatformUserInputMonitor();
PlatformUserInputMonitor(const PlatformUserInputMonitor&) = delete;
PlatformUserInputMonitor& operator=(const PlatformUserInputMonitor&) = delete;
virtual ~PlatformUserInputMonitor();
// Returns how many key presses happened since this monitor has been started.
virtual uint32_t GetKeyPressCount() const = 0;
// Starts monitoring of events without a mapping.
virtual void StartMonitor(WriteKeyPressCallback callback) = 0;
// Starts monitoring of events. The |mapping| should be passed to the
// |callback| upon invocation.
virtual void StartMonitorWithMapping(
WriteKeyPressCallback callback,
base::WritableSharedMemoryMapping mapping) = 0;
// Stops monitoring.
virtual void StopMonitor() = 0;
};
} // namespace ui
#endif // UI_OZONE_PUBLIC_PLATFORM_USER_INPUT_MONITOR_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment