Add Alvin library: input, capture, windows and vision
A cross-platform C++23 library with a platform-neutral public API and runtime-selected backends: - Input: Wayland virtual pointer/keyboard (Hyprland, wlroots), libei via the RemoteDesktop portal (GNOME, KDE), uinput, and Win32 SendInput - Capture: ScreenCast portal + PipeWire, and Win32 GDI - Windows: Hyprland IPC and Win32 enumeration - Monitors via wl_output/xdg-output and EnumDisplayMonitors - Optional OpenCV template matching (alvin::vision) Also adds the `alvin` CLI, Catch2 unit tests, install rules with find_package(Alvin) support, API docs (docs/API.md and the Obsidian vault), and README instructions for both ways of consuming the library. Windows backends are written but not yet compiled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
76ff506fd0
commit
ca7e62ac8d
59 files changed
+6515
-1
No files matched your search
@@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <initializer_list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "alvin/error.hpp"
|
||||
#include "alvin/keys.hpp"
|
||||
#include "alvin/types.hpp"
|
||||
|
||||
namespace alvin {
|
||||
|
||||
enum class InputBackend {
|
||||
Auto,
|
||||
WlrVirtual, // Wayland zwlr_virtual_pointer_v1 + zwp_virtual_keyboard_v1 (Hyprland, sway, other wlroots)
|
||||
LibEi, // libei via xdg-desktop-portal RemoteDesktop (GNOME, KDE)
|
||||
UInput, // /dev/uinput kernel virtual devices (any Linux session; needs write access)
|
||||
SendInput, // Win32
|
||||
};
|
||||
|
||||
std::string_view toString(InputBackend backend) noexcept;
|
||||
|
||||
struct InputOptions {
|
||||
InputBackend backend = InputBackend::Auto;
|
||||
|
||||
// LibEi only: token from a previous session (Input::restoreToken()) that
|
||||
// lets the portal skip its permission dialog.
|
||||
std::string restoreToken;
|
||||
|
||||
// How long to wait for the user to answer a portal permission dialog.
|
||||
std::chrono::milliseconds permissionTimeout = std::chrono::minutes(2);
|
||||
};
|
||||
|
||||
// Synthesises mouse and keyboard events.
|
||||
//
|
||||
// Coordinates passed to moveTo() are global desktop coordinates in logical
|
||||
// pixels, matching Monitor::bounds and WindowInfo::bounds.
|
||||
class Input {
|
||||
public:
|
||||
// Picks a backend (or uses options.backend). With Auto, the environment
|
||||
// variable ALVIN_INPUT_BACKEND=wlr|libei|uinput|sendinput overrides the choice.
|
||||
static Result<std::unique_ptr<Input>> create(const InputOptions& options = {});
|
||||
|
||||
virtual ~Input() = default;
|
||||
Input(const Input&) = delete;
|
||||
Input& operator=(const Input&) = delete;
|
||||
|
||||
virtual InputBackend backend() const = 0;
|
||||
|
||||
virtual Status moveTo(Point p) = 0;
|
||||
virtual Status moveBy(int dx, int dy) = 0;
|
||||
virtual Status buttonDown(MouseButton button) = 0;
|
||||
virtual Status buttonUp(MouseButton button) = 0;
|
||||
// Wheel notches; positive dy scrolls down, positive dx scrolls right.
|
||||
virtual Status scroll(int dx, int dy) = 0;
|
||||
|
||||
virtual Status keyDown(Key key) = 0;
|
||||
virtual Status keyUp(Key key) = 0;
|
||||
// Types UTF-8 text using the active keyboard layout (or a synthesized one).
|
||||
virtual Status typeText(std::string_view utf8) = 0;
|
||||
|
||||
// Portal-backed sessions can hand out a token to skip the dialog next time.
|
||||
virtual std::string restoreToken() const { return {}; }
|
||||
|
||||
// ---- Convenience helpers built on the primitives above ----
|
||||
|
||||
Status click(MouseButton button = MouseButton::Left, int count = 1);
|
||||
Status clickAt(Point p, MouseButton button = MouseButton::Left, int count = 1);
|
||||
Status drag(Point from, Point to, MouseButton button = MouseButton::Left);
|
||||
Status keyPress(Key key);
|
||||
// Presses keys in order, releases in reverse: chord({Key::LeftCtrl, Key::C}).
|
||||
Status chord(std::initializer_list<Key> keys);
|
||||
// Same, from a string such as "ctrl+shift+esc".
|
||||
Status chord(std::string_view chord);
|
||||
|
||||
// Delay inserted between the down/up halves of clicks and key presses.
|
||||
// Some applications drop events that arrive with zero spacing.
|
||||
void setEventDelay(std::chrono::milliseconds delay) { eventDelay_ = delay; }
|
||||
std::chrono::milliseconds eventDelay() const { return eventDelay_; }
|
||||
|
||||
protected:
|
||||
Input() = default;
|
||||
void pause() const;
|
||||
|
||||
private:
|
||||
std::chrono::milliseconds eventDelay_{8};
|
||||
};
|
||||
|
||||
} // namespace alvin
|
||||
Reference in new issue
Block a user