Initial project snapshot

This commit is contained in:
2026-04-28 22:29:50 +03:00
commit 8ba0561f4f
365 changed files with 91832 additions and 0 deletions
@@ -0,0 +1,268 @@
#pragma once
#include <atomic>
#include <chrono>
#include <cstdint>
#include <optional>
#include <queue>
#include <mutex>
#include <memory>
#include <string>
#include <vector>
#include <freerdp/client/cliprdr.h>
#include <freerdp/client/rdpgfx.h>
#include <freerdp/event.h>
#include <freerdp/freerdp.h>
#include <freerdp/gdi/gdi.h>
#include <freerdp/pointer.h>
#include <freerdp/update.h>
#include "rdp_worker/cursor/cursor_adapter.hpp"
#include "rdp_worker/common/logger.hpp"
#include "rdp_worker/runtime/models.hpp"
namespace rdp_worker::freerdp_runtime {
class RdpRuntime {
public:
explicit RdpRuntime(std::shared_ptr<common::Logger> logger);
~RdpRuntime();
bool Start(const runtime::ConnectionSpec& spec);
void Disconnect(bool terminate);
bool IsConnected() const;
bool PumpEvents(std::chrono::milliseconds timeout);
int DesktopWidth() const;
int DesktopHeight() const;
bool SendFocusEvent(bool focused);
bool SendKeyboardInput(uint16_t scan_code, bool key_down, bool extended);
bool SendMouseMove(double normalized_x, double normalized_y);
bool SendMouseButton(const std::string& button, bool pressed, double normalized_x, double normalized_y);
bool SendMouseWheel(int wheel_delta, bool horizontal, double normalized_x, double normalized_y);
bool SetClipboardText(const std::string& text);
void MarkInputAppliedForGraphicsTrace(const std::string& correlation_id);
std::optional<runtime::RenderNotification> CaptureFullFrameNotification(
const std::string& state,
const std::string& capture_source);
std::optional<runtime::RenderNotification> PopRenderNotification();
std::optional<runtime::ClipboardNotification> PopClipboardNotification();
const std::string& RenderQualityProfile() const;
void InstallRenderHooks();
void RemoveRenderHooks();
void EnqueueRenderNotification(const std::string& type, common::JsonObject payload);
void OnBeginPaint(rdpContext* context);
void OnEndPaint(rdpContext* context);
void OnDesktopResize(rdpContext* context);
void OnBitmapUpdate(rdpContext* context, const BITMAP_UPDATE* bitmap);
void OnRefreshRect(rdpContext* context, BYTE count, const RECTANGLE_16* areas);
void OnSurfaceBits(rdpContext* context, const SURFACE_BITS_COMMAND* surface_bits);
void OnSurfaceFrameMarker(rdpContext* context, const SURFACE_FRAME_MARKER* surface_frame_marker);
void OnSurfaceFrameBits(rdpContext* context, const SURFACE_BITS_COMMAND* surface_bits, bool first, bool last, UINT32 frame_id);
void OnChannelConnected(rdpContext* context, ChannelConnectedEventArgs* event_args);
void OnChannelDisconnected(rdpContext* context, ChannelDisconnectedEventArgs* event_args);
void OnPointerPosition(rdpContext* context, const POINTER_POSITION_UPDATE* pointer_position);
void OnPointerSystem(rdpContext* context, const POINTER_SYSTEM_UPDATE* pointer_system);
void OnPointerColor(rdpContext* context, const POINTER_COLOR_UPDATE* pointer_color);
void OnPointerNew(rdpContext* context, const POINTER_NEW_UPDATE* pointer_new);
void OnPointerCached(rdpContext* context, const POINTER_CACHED_UPDATE* pointer_cached);
void OnPointerLarge(rdpContext* context, const POINTER_LARGE_UPDATE* pointer_large);
UINT OnCliprdrServerCapabilities(CliprdrClientContext* context, const CLIPRDR_CAPABILITIES* capabilities);
UINT OnCliprdrMonitorReady(CliprdrClientContext* context, const CLIPRDR_MONITOR_READY* monitor_ready);
UINT OnCliprdrServerFormatList(CliprdrClientContext* context, const CLIPRDR_FORMAT_LIST* format_list);
UINT OnCliprdrServerFormatListResponse(CliprdrClientContext* context, const CLIPRDR_FORMAT_LIST_RESPONSE* response);
UINT OnCliprdrServerLockClipboardData(CliprdrClientContext* context, const CLIPRDR_LOCK_CLIPBOARD_DATA* lock_data);
UINT OnCliprdrServerUnlockClipboardData(CliprdrClientContext* context, const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlock_data);
UINT OnCliprdrServerFormatDataRequest(CliprdrClientContext* context, const CLIPRDR_FORMAT_DATA_REQUEST* request);
UINT OnCliprdrServerFormatDataResponse(CliprdrClientContext* context, const CLIPRDR_FORMAT_DATA_RESPONSE* response);
UINT OnCliprdrServerFileContentsRequest(CliprdrClientContext* context, const CLIPRDR_FILE_CONTENTS_REQUEST* request);
UINT OnCliprdrServerFileContentsResponse(CliprdrClientContext* context, const CLIPRDR_FILE_CONTENTS_RESPONSE* response);
private:
using DesktopResizeCallback = BOOL (*)(rdpContext*);
using BitmapUpdateCallback = BOOL (*)(rdpContext*, const BITMAP_UPDATE*);
using RefreshRectCallback = BOOL (*)(rdpContext*, BYTE, const RECTANGLE_16*);
using PointerPositionCallback = BOOL (*)(rdpContext*, const POINTER_POSITION_UPDATE*);
using BeginPaintCallback = BOOL (*)(rdpContext*);
using EndPaintCallback = BOOL (*)(rdpContext*);
using PointerSystemCallback = BOOL (*)(rdpContext*, const POINTER_SYSTEM_UPDATE*);
using PointerColorCallback = BOOL (*)(rdpContext*, const POINTER_COLOR_UPDATE*);
using PointerNewCallback = BOOL (*)(rdpContext*, const POINTER_NEW_UPDATE*);
using PointerCachedCallback = BOOL (*)(rdpContext*, const POINTER_CACHED_UPDATE*);
using PointerLargeCallback = BOOL (*)(rdpContext*, const POINTER_LARGE_UPDATE*);
using SurfaceBitsCallback = BOOL (*)(rdpContext*, const SURFACE_BITS_COMMAND*);
using SurfaceFrameMarkerCallback = BOOL (*)(rdpContext*, const SURFACE_FRAME_MARKER*);
using SurfaceFrameBitsCallback = BOOL (*)(rdpContext*, const SURFACE_BITS_COMMAND*, BOOL, BOOL, UINT32);
struct RenderHooks {
BeginPaintCallback begin_paint{};
EndPaintCallback end_paint{};
DesktopResizeCallback desktop_resize{};
BitmapUpdateCallback bitmap_update{};
RefreshRectCallback refresh_rect{};
SurfaceBitsCallback surface_bits{};
SurfaceFrameMarkerCallback surface_frame_marker{};
SurfaceFrameBitsCallback surface_frame_bits{};
PointerPositionCallback pointer_position{};
PointerSystemCallback pointer_system{};
PointerColorCallback pointer_color{};
PointerNewCallback pointer_new{};
PointerCachedCallback pointer_cached{};
PointerLargeCallback pointer_large{};
};
struct DirtyRegion {
int x{};
int y{};
int width{};
int height{};
int rectangles{};
};
struct CallbackPerfStats {
std::uint64_t begin_paint{};
std::uint64_t end_paint{};
std::uint64_t desktop_resize{};
std::uint64_t bitmap_update{};
std::uint64_t refresh_rect{};
std::uint64_t surface_bits{};
std::uint64_t surface_frame_marker{};
std::uint64_t surface_frame_bits{};
std::uint64_t pointer_position{};
std::uint64_t pointer_system{};
std::uint64_t pointer_color{};
std::uint64_t pointer_new{};
std::uint64_t pointer_cached{};
std::uint64_t pointer_large{};
std::uint64_t frame_capture_full{};
std::uint64_t frame_capture_region{};
std::uint64_t periodic_polls{};
std::uint64_t periodic_changes{};
std::uint64_t periodic_no_changes{};
std::uint64_t interactive_refresh_requests{};
std::uint64_t bitmap_update_deferred{};
std::uint64_t paint_flush_region{};
std::uint64_t paint_flush_full{};
std::uint64_t end_paint_change_fallback{};
std::uint64_t end_paint_noop{};
std::uint64_t rdpgfx_channel_connected{};
std::uint64_t rdpgfx_channel_disconnected{};
std::uint64_t rdpgfx_pipeline_init_success{};
std::uint64_t rdpgfx_pipeline_init_failed{};
std::uint64_t rdpgfx_fallback_to_gdi{};
std::uint64_t cursor_updates_enqueued{};
std::uint64_t event_pump_drained_checks{};
std::uint64_t event_pump_wait_timeouts{};
std::chrono::steady_clock::time_point first_callback_at{};
std::chrono::steady_clock::time_point last_callback_at{};
std::chrono::steady_clock::time_point last_summary_at{};
std::string last_callback_name;
};
bool ConfigureSettings(const runtime::ConnectionSpec& spec);
void ConfigureQualityProfile(const runtime::ConnectionSpec& spec);
bool ConfigureRestrictedDrive(const runtime::ConnectionSpec& spec);
bool LoadClipboardChannel();
bool SubscribeChannelEvents();
void UnsubscribeChannelEvents();
bool ConfigureClipboardChannel();
bool SendClientClipboardCapabilities();
bool SendClientClipboardFormatList();
bool SendClientClipboardFormatListResponse(bool ok);
bool SendClientClipboardDataRequest(UINT32 format_id);
bool SendClientClipboardDataResponse(UINT32 format_id);
void EnqueueClipboardText(std::string text, std::string origin);
std::optional<runtime::RenderNotification> CaptureFrameNotification(
const std::string& state,
const std::optional<DirtyRegion>& dirty_region = std::nullopt,
const std::string& capture_source = "explicit");
std::optional<runtime::RenderNotification> CaptureChangedFrameNotification(
const std::string& state,
const std::string& detection_source = "periodic_change_detector");
bool EnsureInputReady() const;
uint16_t ScaleCoordinate(double normalized, int size) const;
void RequestInteractiveFrameRefresh();
void TryEnqueueInteractiveFrameCapture(const char* reason);
std::optional<std::pair<std::string, std::int64_t>> RecentInputTraceDelay() const;
void AccumulatePendingPaintRegion(const std::optional<DirtyRegion>& dirty_region, int rectangle_count);
void ClearPendingPaintCycle();
bool SyncPollSnapshotFromCapture(const std::vector<std::uint8_t>& frame_bytes,
int frame_width,
int frame_height,
int frame_stride,
const std::optional<DirtyRegion>& dirty_region,
bool is_region);
void MaybeLogMouseMoveRate();
void RecordRdpCallback(const std::string& callback_name);
void RecordFrameCapture(bool region);
void RecordPeriodicPoll(bool changed);
void MaybeLogPeriodicNoChange(const std::string& detection_source,
std::chrono::steady_clock::time_point poll_started,
std::chrono::steady_clock::time_point poll_completed);
void MaybeLogCallbackSummary(const std::string& trigger);
void MaybeLogFirstInputCallback(const std::string& callback_name, std::chrono::steady_clock::time_point callback_at);
void LogRdpgfxFallbackIfNeeded(const std::string& reason);
void LogSurfaceBitsEvent(const std::string& callback_name, const SURFACE_BITS_COMMAND* surface_bits) const;
void EnqueueCursorUpdate(const cursor::CursorUpdate& update);
void MaybeLogCursorRate(const cursor::CursorUpdate& update);
void Cleanup();
std::shared_ptr<common::Logger> logger_;
freerdp* instance_;
std::atomic<bool> connected_;
int desktop_width_;
int desktop_height_;
std::string render_quality_profile_;
RenderHooks render_hooks_;
mutable std::mutex render_mutex_;
std::queue<runtime::RenderNotification> render_notifications_;
std::queue<runtime::ClipboardNotification> clipboard_notifications_;
cursor::CursorAdapter cursor_adapter_;
CliprdrClientContext* cliprdr_context_{nullptr};
RdpgfxClientContext* rdpgfx_context_{nullptr};
bool rdpgfx_enabled_{false};
bool channel_events_subscribed_{false};
bool rdpgfx_pipeline_active_{false};
bool rdpgfx_channel_seen_{false};
bool rdpgfx_fallback_logged_{false};
std::string client_clipboard_text_;
std::string last_client_clipboard_hash_;
UINT32 requested_server_clipboard_format_{0};
std::uint64_t clipboard_sequence_{0};
int cursor_x_{0};
int cursor_y_{0};
bool cursor_visible_{true};
std::uint64_t cursor_sequence_{0};
std::chrono::steady_clock::time_point last_cursor_rate_log_at_{};
std::uint64_t cursor_updates_since_log_{0};
int64_t frame_sequence_{0};
std::atomic<bool> interactive_frame_refresh_requested_{false};
std::atomic<std::uint32_t> interactive_frame_refresh_budget_{0};
std::chrono::steady_clock::time_point last_interactive_frame_capture_at_{};
std::chrono::steady_clock::time_point last_mouse_move_refresh_request_at_{};
std::chrono::steady_clock::time_point post_input_capture_until_{};
std::chrono::steady_clock::time_point next_post_input_capture_at_{};
std::chrono::steady_clock::time_point last_mouse_move_rate_log_at_{};
std::uint64_t mouse_moves_sent_since_log_{0};
std::vector<std::uint8_t> last_polled_frame_;
int last_polled_frame_width_{0};
int last_polled_frame_height_{0};
int last_polled_frame_stride_{0};
std::chrono::steady_clock::time_point last_periodic_frame_poll_at_{};
std::chrono::steady_clock::time_point last_periodic_no_change_log_at_{};
std::uint64_t periodic_no_change_suppressed_since_log_{0};
bool paint_cycle_active_{false};
bool pending_paint_has_bitmap_update_{false};
bool pending_paint_force_full_frame_{false};
std::optional<DirtyRegion> pending_paint_dirty_region_;
int pending_paint_dirty_rectangles_{0};
std::uint64_t pending_paint_bitmap_updates_{0};
mutable std::mutex input_trace_mutex_;
std::string last_input_trace_correlation_id_;
std::chrono::steady_clock::time_point last_input_trace_at_{};
bool last_input_waiting_for_first_callback_{false};
CallbackPerfStats callback_perf_;
};
} // namespace rdp_worker::freerdp_runtime