/* * @Author: DI JUNKUN * @Date: 2026-09-04 * Copyright (c) 2026 by DI JUNKUN, All Rights Reserved. */ #ifndef _GUI_RUNTIME_H_ #define _GUI_RUNTIME_H_ #include #include #include #include #include #include "features/clipboard/clipboard_controller.h" #include "features/devices/session_device_manager.h" #include "features/file_transfer/file_transfer_manager.h" #include "features/input/keyboard_controller.h" #include "features/input/remote_input_dispatcher.h" #include "features/settings/settings_manager.h" #include "network/lan/lan_session_manager.h" #include "privacy_controller.h" #include "runtime/gui_state.h" #include "runtime/disconnect_lock_policy.h" #include "runtime/announcement_inbox.h" #include "runtime/peer_event_handler.h" #include "runtime/privacy_session_policy.h" namespace crossdesk { class VideoRenderer; // Shared GUI runtime. It owns subsystem controllers and cross-cutting session // state, but no window lifecycle, UI view, or transport callback methods. class GuiRuntime : protected gui_detail::GuiState { protected: using FileTransferState = gui_detail::FileTransferState; using RemoteSession = gui_detail::RemoteSession; enum class RemoteUnlockState { none, service_unavailable, lock_screen, credential_ui, secure_desktop, }; GuiRuntime(); ~GuiRuntime(); static void SdlCaptureAudioIn(void* userdata, uint8_t* stream, int len); static void SdlCaptureAudioOut(void* userdata, uint8_t* stream, int len); void InitializeLan(); void ApplyLanSettings(); bool LanAvailable() const; void TickLan(); void BeginShutdown(); bool ShutdownDrained(); void RegisterStreams(PeerPtr* peer, size_t display_count); void ConnectLan(const std::string& address, unsigned port, std::string password, bool remember_password = false); int WithController( const std::string& id, const std::function& operation); int SendControllerData(const std::string& id, const char* data, size_t size, const char* label); std::shared_ptr ControllerEvents(const std::string& id); std::vector ConnectedControllers(); std::unique_ptr lan_; std::string lan_error_; std::shared_ptr lan_connecting_; bool lan_stopping_ = false; bool stopping_ = false; std::chrono::steady_clock::time_point shutdown_report_at_{}; struct LanController { std::shared_ptr session; std::shared_ptr events; }; // Protected by remote_sessions_mutex_; snapshots acquire callback leases // before releasing that lock, so removal cannot race a raw Peer use. std::map lan_controllers_; int CreateConnectionPeer(); int ConnectTo(const std::string& remote_id, const char* password, bool remember_password, bool bypass_presence_check = false, bool background = false); // UI thread: mute this receiver without stopping audio for other controllers. void MuteRemoteAudio(const std::shared_ptr& props); void UnmuteRemoteAudio(const std::shared_ptr& props); int RequestSingleDevicePresence(const std::string& remote_id, const char* password, bool remember_password); int ForceSignalReconnect(); void HandleRecentConnections(); void HandleConnectionStatusChange(); void HandlePendingRejoins(); void CancelPendingConnection(const std::string& remote_id); void HandlePendingPresenceProbe(); void HandlePresenceProbeTimeout(); bool HasActiveSession(); void HandleServerControllerDisconnected(const std::string& remote_id, const char* reason); void HandleWindowsServiceIntegration(); void HandlePrivacy(); void HandleScreenLock(); bool IsAuthorizedController(const std::string& remote_id); void SetControllerPrivacySupport(const std::string& remote_id, bool supported); // Caller holds connection_status_mutex_ exclusively. Turns privacy off when // any connected controller lacks support, or on for the first automatic one. void ApplyPrivacyAdmission(bool automatic_enable); void QueuePrivacyCommand(const std::string& remote_id, const PrivacyCommand& command); void CloseRemoteSession(std::shared_ptr props); void CloseAllRemoteSessions(); void CloseConnectionPeer(); void CloseServerController(const std::string& remote_id); void ResetRemoteSessionResources(std::shared_ptr props); void HandleSessionCleanup(); void WaitForSessionCleanup(); std::shared_ptr FindRemoteSession( const std::string& remote_id); // UI thread: send mapped mouse/keyboard input to the current control target, // or every connected session while that target leads DeskHub group control. void SendRemoteInput(const RemoteAction& action); InputOutcome ApplyRemoteInput(const std::string& remote_id, const RemoteAction& action); InputOutcome InjectRemoteMouse(const RemoteAction& action, int display); std::string gallery_group_control_id_; void ResetRemoteServiceStatus(RemoteSession& props); void ApplyRemoteServiceStatus(RemoteSession& props, const ServiceStatus& status); RemoteUnlockState GetRemoteUnlockState(const RemoteSession& props) const; #if _WIN32 void ResetLocalWindowsServiceState(bool clear_pending_sas); std::string WindowsInputStage() const { std::lock_guard lock(windows_input_stage_mutex_); return windows_input_stage_; } void PublishWindowsInputStage() { std::lock_guard lock(windows_input_stage_mutex_); windows_input_stage_ = local_service_status_received_ ? local_interactive_stage_ : std::string{}; } #endif #ifdef __APPLE__ bool CheckScreenRecordingPermission(); bool CheckAccessibilityPermission(); void OpenScreenRecordingPreferences(); void OpenAccessibilityPreferences(); void RefreshMacPermissionStatus(bool force); bool EnsureMacScreenRecordingPermission(); bool EnsureMacAccessibilityPermission(); #endif PrivacyController privacy_; // Set before initializing callbacks; immutable for the process lifetime. bool unattended_host_ = false; AnnouncementInbox announcements_; PrivacySessionPolicy privacy_sessions_; DisconnectLockPolicy disconnect_lock_; std::mutex privacy_commands_mutex_; std::deque> privacy_commands_; uint32_t last_privacy_revision_ = 0; uint64_t last_privacy_status_tick_ = 0; ClipboardController clipboard_; SessionDeviceManager devices_; FileTransferManager transfers_; SettingsManager settings_; KeyboardController keyboard_; RemoteInputDispatcher remote_input_; std::shared_ptr peer_events_; std::atomic video_frame_dirty_{false}; std::unique_ptr video_renderer_; private: friend class ClipboardController; friend class SessionDeviceManager; friend class FileTransferManager; friend class SettingsManager; friend class KeyboardController; friend class PeerEventHandler; }; } // namespace crossdesk #endif