fix: close server window after controller disconnects

This commit is contained in:
dijunkun
2026-07-27 00:22:33 +08:00
parent 7cd0d6a351
commit 765452e3c9
7 changed files with 374 additions and 343 deletions
+75 -23
View File
@@ -1,5 +1,3 @@
#include "runtime/gui_runtime.h"
#include <algorithm>
#include <chrono>
#include <cstring>
@@ -12,6 +10,7 @@
#include "localization.h"
#include "rd_log.h"
#include "runtime/gui_runtime.h"
namespace crossdesk {
@@ -22,7 +21,7 @@ bool IsConnectionAttemptPending(ConnectionStatus status) {
return status == ConnectionStatus::Connecting ||
status == ConnectionStatus::Gathering;
}
} // namespace
} // namespace
void GuiRuntime::HandleConnectionStatusChange() {
if (signal_connected_ && peer_ && need_to_send_recent_connections_) {
@@ -31,7 +30,7 @@ void GuiRuntime::HandleConnectionStatusChange() {
j["type"] = "recent_connections_presence";
j["user_id"] = client_id_;
j["devices"] = nlohmann::json::array();
for (const auto &id : recent_connection_ids_) {
for (const auto& id : recent_connection_ids_) {
std::string pure_id = id;
size_t pos_y = pure_id.find('Y');
size_t pos_n = pure_id.find('N');
@@ -123,7 +122,7 @@ void GuiRuntime::HandleConnectionTimeouts() {
}
bool rejoin_state_changed = false;
for (auto &[_, props] : remote_sessions_) {
for (auto& [_, props] : remote_sessions_) {
if (!props || !props->connection_attempt_active_.load()) {
continue;
}
@@ -152,7 +151,7 @@ void GuiRuntime::HandleConnectionTimeouts() {
if (rejoin_state_changed) {
need_to_rejoin_ = false;
for (const auto &[_, props] : remote_sessions_) {
for (const auto& [_, props] : remote_sessions_) {
if (props && props->rejoin_) {
need_to_rejoin_ = true;
break;
@@ -161,8 +160,65 @@ void GuiRuntime::HandleConnectionTimeouts() {
}
}
int GuiRuntime::RequestSingleDevicePresence(const std::string &remote_id,
const char *password,
void GuiRuntime::HandleServerControllerDisconnected(
const std::string& remote_id, const char* reason) {
keyboard_.ReleaseRemotePressedKeys(remote_id, reason);
bool has_connected_controller = false;
bool has_web_controller = false;
std::string remaining_controller_id;
{
std::unique_lock lock(connection_status_mutex_);
connection_status_.erase(remote_id);
connection_host_names_.erase(remote_id);
for (const auto& [id, status] : connection_status_) {
if (status != ConnectionStatus::Connected) {
continue;
}
has_connected_controller = true;
has_web_controller =
has_web_controller || id.find("web") != std::string::npos;
if (remaining_controller_id.empty()) {
remaining_controller_id = id;
}
}
}
show_cursor_ = has_web_controller;
if (has_connected_controller) {
remote_client_id_ = remaining_controller_id;
return;
}
need_to_create_server_window_.store(false, std::memory_order_release);
need_to_destroy_server_window_.store(true, std::memory_order_release);
is_server_mode_ = false;
#if defined(__linux__) && !defined(__APPLE__)
if (IsWaylandSession()) {
// Keep Wayland capture session warm to avoid black screen on subsequent
// reconnects.
start_screen_capturer_ = true;
LOG_INFO(
"Keeping Wayland screen capturer running after disconnect to "
"preserve reconnect stability");
} else {
start_screen_capturer_ = false;
}
#else
start_screen_capturer_ = false;
#endif
start_speaker_capturer_ = false;
start_mouse_controller_ = false;
start_keyboard_capturer_ = false;
remote_client_id_.clear();
if (audio_capture_) {
devices_.StopSpeakerCapturer();
audio_capture_ = false;
}
devices_.ResetToInitialDisplay();
}
int GuiRuntime::RequestSingleDevicePresence(const std::string& remote_id,
const char* password,
bool remember_password) {
if (!signal_connected_ || !peer_) {
return -1;
@@ -221,7 +277,7 @@ void GuiRuntime::CloseRemoteSession(std::shared_ptr<RemoteSession> props) {
std::thread save_thread([buffer_copy, video_width, video_height, remote_id,
remote_host_name, password,
thumbnail = thumbnail_]() {
thumbnail->SaveToThumbnail((char *)buffer_copy.data(), video_width,
thumbnail->SaveToThumbnail((char*)buffer_copy.data(), video_width,
video_height, remote_id, remote_host_name,
password);
});
@@ -255,7 +311,7 @@ void GuiRuntime::CloseAllRemoteSessions() {
{
// std::shared_lock lock(remote_sessions_mutex_);
for (auto &it : remote_sessions_) {
for (auto& it : remote_sessions_) {
auto props = it.second;
CloseRemoteSession(props);
}
@@ -279,7 +335,7 @@ void GuiRuntime::WaitForThumbnailSaveTasks() {
return;
}
for (auto &thread : threads_to_join) {
for (auto& thread : threads_to_join) {
if (thread.joinable()) {
thread.join();
}
@@ -300,9 +356,8 @@ void GuiRuntime::ResetRemoteSessionResources(
}
}
std::shared_ptr<GuiRuntime::RemoteSession>
GuiRuntime::FindRemoteSession(
const std::string &remote_id) {
std::shared_ptr<GuiRuntime::RemoteSession> GuiRuntime::FindRemoteSession(
const std::string& remote_id) {
if (remote_id.empty()) {
return nullptr;
}
@@ -315,8 +370,7 @@ GuiRuntime::FindRemoteSession(
return it->second;
}
int GuiRuntime::ConnectTo(const std::string &remote_id, const char *password,
int GuiRuntime::ConnectTo(const std::string& remote_id, const char* password,
bool remember_password, bool bypass_presence_check) {
if (!bypass_presence_check && !device_presence_cache_.IsOnline(remote_id)) {
int ret =
@@ -336,19 +390,17 @@ int GuiRuntime::ConnectTo(const std::string &remote_id, const char *password,
focused_remote_id_ = remote_id;
// std::shared_lock shared_lock(remote_sessions_mutex_);
bool exists =
(remote_sessions_.find(remote_id) != remote_sessions_.end());
bool exists = (remote_sessions_.find(remote_id) != remote_sessions_.end());
// shared_lock.unlock();
if (!exists) {
PeerPtr *peer_to_init = nullptr;
PeerPtr* peer_to_init = nullptr;
std::string local_id;
{
// std::unique_lock unique_lock(remote_sessions_mutex_);
if (remote_sessions_.find(remote_id) == remote_sessions_.end()) {
remote_sessions_[remote_id] =
std::make_shared<RemoteSession>();
remote_sessions_[remote_id] = std::make_shared<RemoteSession>();
auto props = remote_sessions_[remote_id];
props->local_id_ = "C-" + std::string(client_id_);
props->remote_id_ = remote_id;
@@ -371,7 +423,7 @@ int GuiRuntime::ConnectTo(const std::string &remote_id, const char *password,
return -1;
}
for (const auto &display_info : devices_.display_info_list()) {
for (const auto& display_info : devices_.display_info_list()) {
AddVideoStream(props->peer_, display_info.name.c_str());
}
AddAudioStream(props->peer_, props->audio_label_.c_str());
@@ -429,4 +481,4 @@ int GuiRuntime::ConnectTo(const std::string &remote_id, const char *password,
return 0;
}
} // namespace crossdesk
} // namespace crossdesk