mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-25 22:56:23 +08:00
189 lines
7.1 KiB
C++
189 lines
7.1 KiB
C++
/*
|
|
* @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 <atomic>
|
|
#include <cstdint>
|
|
#include <deque>
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
#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<int(PeerPtr*, const std::string&)>& operation);
|
|
int SendControllerData(const std::string& id, const char* data, size_t size,
|
|
const char* label);
|
|
std::shared_ptr<PeerEventHandler> ControllerEvents(const std::string& id);
|
|
std::vector<std::string> ConnectedControllers();
|
|
std::unique_ptr<lan::SessionManager> lan_;
|
|
std::string lan_error_;
|
|
std::shared_ptr<lan::Session> lan_connecting_;
|
|
bool lan_stopping_ = false;
|
|
bool stopping_ = false;
|
|
std::chrono::steady_clock::time_point shutdown_report_at_{};
|
|
struct LanController {
|
|
std::shared_ptr<lan::Session> session;
|
|
std::shared_ptr<PeerEventHandler> events;
|
|
};
|
|
// Protected by remote_sessions_mutex_; snapshots acquire callback leases
|
|
// before releasing that lock, so removal cannot race a raw Peer use.
|
|
std::map<std::string, LanController> 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<RemoteSession>& props);
|
|
void UnmuteRemoteAudio(const std::shared_ptr<RemoteSession>& 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<RemoteSession> props);
|
|
void CloseAllRemoteSessions();
|
|
void CloseConnectionPeer();
|
|
void CloseServerController(const std::string& remote_id);
|
|
void ResetRemoteSessionResources(std::shared_ptr<RemoteSession> props);
|
|
void HandleSessionCleanup();
|
|
void WaitForSessionCleanup();
|
|
std::shared_ptr<RemoteSession> 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<std::pair<std::string, PrivacyCommand>> 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<PeerEventHandler> peer_events_;
|
|
std::atomic<bool> video_frame_dirty_{false};
|
|
std::unique_ptr<VideoRenderer> video_renderer_;
|
|
|
|
private:
|
|
friend class ClipboardController;
|
|
friend class SessionDeviceManager;
|
|
friend class FileTransferManager;
|
|
friend class SettingsManager;
|
|
friend class KeyboardController;
|
|
friend class PeerEventHandler;
|
|
};
|
|
|
|
} // namespace crossdesk
|
|
|
|
#endif
|