#ifndef ORBITHUB_RDP_SESSION_BACKEND_H #define ORBITHUB_RDP_SESSION_BACKEND_H #include "session_backend.h" #include #include #include #include #include struct rdp_freerdp; class RdpSessionBackend : public SessionBackend { Q_OBJECT public: explicit RdpSessionBackend(const Profile& profile, QObject* parent = nullptr); ~RdpSessionBackend() override; public slots: void connectSession(const SessionConnectOptions& options) override; void disconnectSession() override; void reconnectSession(const SessionConnectOptions& options) override; void sendInput(const QString& input) override; void confirmHostKey(bool trustHost) override; void updateTerminalSize(int columns, int rows) override; void sendKeyEvent(int key, quint32 nativeScanCode, const QString& text, bool pressed, int modifiers) override; void sendMouseMoveEvent(int x, int y) override; void sendMouseButtonEvent(int x, int y, int button, bool pressed) override; void sendMouseWheelEvent(int x, int y, int deltaX, int deltaY) override; void setClipboardText(const QString& text) override; private: enum class InputEventType { Key, MouseMove, MouseButton, MouseWheel, Resize, SetClipboardText, }; struct InputEvent { InputEventType type = InputEventType::MouseMove; int key = 0; quint32 nativeScanCode = 0; QString text; bool pressed = false; int modifiers = 0; int x = 0; int y = 0; int button = 0; int deltaX = 0; int deltaY = 0; int width = 0; int height = 0; }; SessionState m_state; SessionConnectOptions m_activeOptions; std::atomic_bool m_userInitiatedDisconnect; std::atomic_int m_requestedDesktopWidth; std::atomic_int m_requestedDesktopHeight; std::thread m_worker; std::atomic_bool m_workerRunning; std::atomic_bool m_stopRequested; std::mutex m_instanceMutex; rdp_freerdp* m_instance; std::mutex m_inputMutex; std::deque m_inputEvents; std::mutex m_displayControlMutex; void* m_displayControlContext; bool m_displayControlReady; bool m_resizeFailureLogged; int m_lastResizeWidth; int m_lastResizeHeight; std::mutex m_cliprdrMutex; void* m_cliprdrContext; QString m_pendingLocalClipboardText; void setState(SessionState state, const QString& message); bool validateProfile(QString& message) const; void startWorker(); void stopWorker(bool userInitiated); void workerMain(); void enqueueInputEvent(const InputEvent& event); void processInputEvents(rdp_freerdp* instance); bool sendDisplayResize(rdp_freerdp* instance, int width, int height); void sendClipboardTextToRemote(rdp_freerdp* instance, const QString& text); public: void onChannelConnectedEvent(const char* name, void* channelInterface); void onChannelDisconnectedEvent(const char* name, void* channelInterface); void onDisplayControlCaps(uint32_t maxNumMonitors, uint32_t maxMonitorAreaFactorA, uint32_t maxMonitorAreaFactorB); void onCliprdrMonitorReady(); void onCliprdrServerFormatList(bool hasUnicodeText); void onCliprdrServerFormatDataRequest(uint32_t requestedFormatId); void onCliprdrServerFormatDataResponse(bool success, const uint8_t* data, uint32_t size); private: void emitStateAsync(SessionState state, const QString& message); void emitConnectionFailureAsync(const QString& displayMessage, const QString& rawMessage); int sanitizeDesktopWidth(int width) const; int sanitizeDesktopHeight(int height) const; }; #endif