#ifndef REMOTING_HOST_LINUX_INPUT_INJECTOR_X11_H_
#define REMOTING_HOST_LINUX_INPUT_INJECTOR_X11_H_
#include <stddef.h>
#include <stdint.h>
#include <array>
#include <memory>
#include <optional>
#include <set>
#include <utility>
#include "base/compiler_specific.h"
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "remoting/host/clipboard.h"
#include "remoting/host/input_injector.h"
#include "remoting/host/linux/input_injector_constants_linux.h"
#include "remoting/host/linux/x11_character_injector.h"
#include "remoting/host/linux/x11_keyboard_impl.h"
#include "remoting/host/linux/x11_util.h"
#include "remoting/proto/internal.pb.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
#include "ui/gfx/x/xproto.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "remoting/host/chromeos/point_transformer.h"
#endif
namespace remoting {
class InputInjectorX11 : public InputInjector {
public:
explicit InputInjectorX11(
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
InputInjectorX11(const InputInjectorX11&) = delete;
InputInjectorX11& operator=(const InputInjectorX11&) = delete;
~InputInjectorX11() override;
void Init();
void InjectClipboardEvent(const protocol::ClipboardEvent& event) override;
void InjectKeyEvent(const protocol::KeyEvent& event) override;
void InjectTextEvent(const protocol::TextEvent& event) override;
void InjectMouseEvent(const protocol::MouseEvent& event) override;
void InjectTouchEvent(const protocol::TouchEvent& event) override;
void Start(
std::unique_ptr<protocol::ClipboardStub> client_clipboard) override;
private:
class Core : public base::RefCountedThreadSafe<Core> {
public:
explicit Core(scoped_refptr<base::SingleThreadTaskRunner> task_runner);
Core(const Core&) = delete;
Core& operator=(const Core&) = delete;
void Init();
void InjectClipboardEvent(const protocol::ClipboardEvent& event);
void InjectKeyEvent(const protocol::KeyEvent& event);
void InjectTextEvent(const protocol::TextEvent& event);
void InjectMouseEvent(const protocol::MouseEvent& event);
void Start(std::unique_ptr<protocol::ClipboardStub> client_clipboard);
void Stop();
private:
friend class base::RefCountedThreadSafe<Core>;
virtual ~Core();
void InitClipboard();
bool IsAutoRepeatEnabled();
void SetAutoRepeatEnabled(bool enabled);
bool IsLockKey(x11::KeyCode keycode);
void SetLockStates(std::optional<bool> caps_lock,
std::optional<bool> num_lock);
void InjectScrollWheelClicks(int button, int count);
void InitMouseButtonMap();
int MouseButtonToX11ButtonNumber(protocol::MouseEvent::MouseButton button);
int HorizontalScrollWheelToX11ButtonNumber(int dx);
int VerticalScrollWheelToX11ButtonNumber(int dy);
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
std::set<int> pressed_keys_;
webrtc::DesktopVector latest_mouse_position_ =
webrtc::DesktopVector(-1, -1);
float wheel_ticks_x_ = 0;
float wheel_ticks_y_ = 0;
base::Time latest_tick_y_event_;
ScrollDirection latest_tick_y_direction_ = ScrollDirection::NONE;
raw_ptr<x11::Connection> connection_;
static const int kNumPointerButtons = 9;
std::array<int, kNumPointerButtons> pointer_button_map_;
#if BUILDFLAG(IS_CHROMEOS)
PointTransformer point_transformer_;
#endif
std::unique_ptr<Clipboard> clipboard_;
std::unique_ptr<X11CharacterInjector> character_injector_;
bool saved_auto_repeat_enabled_ = false;
};
scoped_refptr<Core> core_;
};
}
#endif