Files
Aeth3randClaude Opus 5.5 ca7e62ac8d 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>
2026-09-27 13:58:20 -04:00

73 lines
2.1 KiB
C++

#pragma once
#include <chrono>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include "alvin/error.hpp"
#include "alvin/frame.hpp"
#include "alvin/window.hpp"
namespace alvin {
enum class CaptureBackend {
Auto,
Portal, // xdg-desktop-portal ScreenCast + PipeWire (any modern Wayland desktop)
Gdi, // Win32 BitBlt / PrintWindow
};
std::string_view toString(CaptureBackend backend) noexcept;
enum class CaptureSource : std::uint8_t {
Monitor = 1,
Window = 2,
Any = Monitor | Window,
};
struct CaptureOptions {
CaptureBackend backend = CaptureBackend::Auto;
// What the portal picker offers. On Windows, Monitor + monitorIndex or
// Window + window select the target directly with no dialog.
CaptureSource source = CaptureSource::Monitor;
int monitorIndex = 0;
std::optional<WindowId> window;
bool showCursor = false;
// Portal only: token from Capture::restoreToken() of an earlier session.
// Lets the compositor skip the picker and reuse the previous selection.
std::string restoreToken;
std::chrono::milliseconds permissionTimeout = std::chrono::minutes(2);
};
// A live capture of one monitor or window.
class Capture {
public:
static Result<std::unique_ptr<Capture>> create(const CaptureOptions& options = {});
virtual ~Capture() = default;
Capture(const Capture&) = delete;
Capture& operator=(const Capture&) = delete;
virtual CaptureBackend backend() const = 0;
// Most recent frame. Blocks until the first frame arrives (up to timeout).
// Streaming backends only deliver frames when the screen changes, so this
// does not wait for a *new* frame; use nextFrame() for that.
virtual Result<Frame> grab(std::chrono::milliseconds timeout = std::chrono::seconds(5)) = 0;
// Waits for a frame newer than any previously returned one.
virtual Result<Frame> nextFrame(std::chrono::milliseconds timeout = std::chrono::seconds(5)) = 0;
virtual std::string restoreToken() const { return {}; }
protected:
Capture() = default;
};
} // namespace alvin