blob: ba089a7ebcc2c419b7fdb8b89b611ceb7928c410 [file] [log] [blame]
// 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 "media/base/user_input_monitor.h"
#include <stddef.h>
#include <sys/select.h>
#include <unistd.h>
#include <memory>
#include "base/bind.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/files/file_descriptor_watcher_posix.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "base/task/current_thread.h"
#include "third_party/skia/include/core/SkPoint.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 {
using WriteKeyPressCallback =
base::RepeatingCallback<void(const base::WritableSharedMemoryMapping& shmem,
uint32_t count)>;
// 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;
};
// 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:
std::unique_ptr<Impl> user_input_monitor_;
};
class UserInputMonitorLinux : public UserInputMonitorBase {
public:
explicit UserInputMonitorLinux(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
UserInputMonitorLinux(const UserInputMonitorLinux&) = delete;
UserInputMonitorLinux& operator=(const UserInputMonitorLinux&) = delete;
~UserInputMonitorLinux() override;
// Public UserInputMonitor overrides.
uint32_t GetKeyPressCount() const override;
private:
// Private UserInputMonitor overrides.
void StartKeyboardMonitoring() override;
void StartKeyboardMonitoring(
base::WritableSharedMemoryMapping mapping) override;
void StopKeyboardMonitoring() override;
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
UserInputMonitorAdapter* core_;
};
UserInputMonitorAdapter* CreateUserInputMonitor(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) {
#if defined(USE_OZONE)
if (features::IsUsingOzonePlatform()) {
return new UserInputMonitorLinuxCore<ui::PlatformUserInputMonitor>(
ui::OzonePlatform::GetInstance()->GetPlatformUserInputMonitor(
io_task_runner));
}
#endif
#if defined(USE_X11)
return new UserInputMonitorLinuxCore<ui::XUserInputMonitor>(
std::make_unique<ui::XUserInputMonitor>(io_task_runner));
#else
NOTREACHED();
return nullptr;
#endif
}
//
// Implementation of UserInputMonitorLinux.
//
UserInputMonitorLinux::UserInputMonitorLinux(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
: io_task_runner_(io_task_runner),
core_(CreateUserInputMonitor(io_task_runner_)) {}
UserInputMonitorLinux::~UserInputMonitorLinux() {
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(&UserInputMonitorAdapter::StartMonitor, core_->AsWeakPtr(),
base::BindRepeating(&WriteKeyPressMonitorCount)));
}
void UserInputMonitorLinux::StartKeyboardMonitoring(
base::WritableSharedMemoryMapping mapping) {
if (!core_)
return;
io_task_runner_->PostTask(
FROM_HERE,
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(&UserInputMonitorAdapter::StopMonitor,
core_->AsWeakPtr()));
}
} // namespace
std::unique_ptr<UserInputMonitor> UserInputMonitor::Create(
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
return std::make_unique<UserInputMonitorLinux>(io_task_runner);
}
} // namespace media