mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-15 00:09:39 +08:00
[refactor] build host information in the wire library
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
@@ -146,7 +147,7 @@ int SessionDeviceManager::InitializeScreenCapturer() {
|
|||||||
? 30
|
? 30
|
||||||
: 60;
|
: 60;
|
||||||
LOG_INFO("Init screen capturer with {} fps", fps);
|
LOG_INFO("Init screen capturer with {} fps", fps);
|
||||||
display_info_list_.clear();
|
SetDisplayInfoList({});
|
||||||
registered_display_stream_count_ = 0;
|
registered_display_stream_count_ = 0;
|
||||||
last_video_frame_stream_id_.clear();
|
last_video_frame_stream_id_.clear();
|
||||||
invalid_video_stream_id_logged_ = false;
|
invalid_video_stream_id_logged_ = false;
|
||||||
@@ -256,11 +257,11 @@ int SessionDeviceManager::InitializeScreenCapturer() {
|
|||||||
|
|
||||||
if (init_ret == 0) {
|
if (init_ret == 0) {
|
||||||
LOG_INFO("Init screen capturer success");
|
LOG_INFO("Init screen capturer success");
|
||||||
const auto latest_display_info = screen_capturer_->GetDisplayInfoList();
|
auto latest_display_info = screen_capturer_->GetDisplayInfoList();
|
||||||
|
registered_display_stream_count_ = latest_display_info.size();
|
||||||
if (!latest_display_info.empty()) {
|
if (!latest_display_info.empty()) {
|
||||||
display_info_list_ = latest_display_info;
|
SetDisplayInfoList(std::move(latest_display_info));
|
||||||
}
|
}
|
||||||
registered_display_stream_count_ = display_info_list_.size();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,6 +330,11 @@ void SessionDeviceManager::StopSpeakerCapturer() {
|
|||||||
speaker_capture_.SetEnabled(false);
|
speaker_capture_.SetEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SessionDeviceManager::SetDisplayInfoList(std::vector<DisplayInfo> displays) {
|
||||||
|
std::lock_guard<std::mutex> lock(display_info_mutex_);
|
||||||
|
display_info_list_ = std::move(displays);
|
||||||
|
}
|
||||||
|
|
||||||
int SessionDeviceManager::StartMouseController() {
|
int SessionDeviceManager::StartMouseController() {
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
if (!owner_.EnsureMacAccessibilityPermission()) {
|
if (!owner_.EnsureMacAccessibilityPermission()) {
|
||||||
@@ -657,11 +663,22 @@ void SessionDeviceManager::ResetToInitialDisplay() {
|
|||||||
owner_.selected_display_ = 0;
|
owner_.selected_display_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<DisplayInfo> &
|
std::vector<DisplayInfo> SessionDeviceManager::display_info_list() const {
|
||||||
SessionDeviceManager::display_info_list() const {
|
std::lock_guard<std::mutex> lock(display_info_mutex_);
|
||||||
return display_info_list_;
|
return display_info_list_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<HostDisplay> SessionDeviceManager::host_display_list() const {
|
||||||
|
std::lock_guard<std::mutex> lock(display_info_mutex_);
|
||||||
|
std::vector<HostDisplay> displays;
|
||||||
|
displays.reserve(display_info_list_.size());
|
||||||
|
for (const auto &display : display_info_list_) {
|
||||||
|
displays.push_back({display.name, display.left, display.top, display.right,
|
||||||
|
display.bottom});
|
||||||
|
}
|
||||||
|
return displays;
|
||||||
|
}
|
||||||
|
|
||||||
void SessionDeviceManager::DestroyDevices() {
|
void SessionDeviceManager::DestroyDevices() {
|
||||||
speaker_capture_.Shutdown();
|
speaker_capture_.Shutdown();
|
||||||
if (mouse_controller_) {
|
if (mouse_controller_) {
|
||||||
|
|||||||
@@ -74,7 +74,12 @@ public:
|
|||||||
int SwitchDisplay(int display_id);
|
int SwitchDisplay(int display_id);
|
||||||
void ResetToInitialDisplay();
|
void ResetToInitialDisplay();
|
||||||
|
|
||||||
const std::vector<DisplayInfo> &display_info_list() const;
|
// Snapshot of the capture displays. The UI thread refreshes the list every
|
||||||
|
// tick while transport threads build host information and map mouse input
|
||||||
|
// from it, so callers get a copy taken under the lock.
|
||||||
|
std::vector<DisplayInfo> display_info_list() const;
|
||||||
|
// The same snapshot in the wire's host information form.
|
||||||
|
std::vector<HostDisplay> host_display_list() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct CapturedKeyboardInput {
|
struct CapturedKeyboardInput {
|
||||||
@@ -91,6 +96,7 @@ private:
|
|||||||
bool ShouldSendCapturedFrame(std::chrono::steady_clock::time_point now,
|
bool ShouldSendCapturedFrame(std::chrono::steady_clock::time_point now,
|
||||||
int fps);
|
int fps);
|
||||||
bool ShouldCaptureCursor() const;
|
bool ShouldCaptureCursor() const;
|
||||||
|
void SetDisplayInfoList(std::vector<DisplayInfo> displays);
|
||||||
void RecordCaptureCadence(std::chrono::steady_clock::time_point now, int fps,
|
void RecordCaptureCadence(std::chrono::steady_clock::time_point now, int fps,
|
||||||
bool from_secure_desktop);
|
bool from_secure_desktop);
|
||||||
|
|
||||||
@@ -103,6 +109,8 @@ private:
|
|||||||
DeviceControllerFactory *device_controller_factory_ = nullptr;
|
DeviceControllerFactory *device_controller_factory_ = nullptr;
|
||||||
MouseController *mouse_controller_ = nullptr;
|
MouseController *mouse_controller_ = nullptr;
|
||||||
KeyboardCapturer *keyboard_capturer_ = nullptr;
|
KeyboardCapturer *keyboard_capturer_ = nullptr;
|
||||||
|
// Guards display_info_list_ (UI thread writes, transport threads read).
|
||||||
|
mutable std::mutex display_info_mutex_;
|
||||||
std::vector<DisplayInfo> display_info_list_;
|
std::vector<DisplayInfo> display_info_list_;
|
||||||
size_t registered_display_stream_count_ = 0;
|
size_t registered_display_stream_count_ = 0;
|
||||||
std::deque<CapturedKeyboardInput> captured_keyboard_inputs_;
|
std::deque<CapturedKeyboardInput> captured_keyboard_inputs_;
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
#include "runtime/gui_runtime.h"
|
#include "runtime/gui_runtime.h"
|
||||||
#include "runtime/remote_action_codec.h"
|
|
||||||
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
#include "interactive_state.h"
|
#include "interactive_state.h"
|
||||||
@@ -288,7 +287,7 @@ void PeerEventHandler::OnReceiveDataBuffer(
|
|||||||
remote_action.i.right[i], remote_action.i.bottom[i]));
|
remote_action.i.right[i], remote_action.i.bottom[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
remote_action_codec::Free(remote_action);
|
FreeRemoteAction(remote_action);
|
||||||
} else {
|
} else {
|
||||||
// server mode
|
// server mode
|
||||||
std::string host_name(remote_action.i.host_name,
|
std::string host_name(remote_action.i.host_name,
|
||||||
@@ -302,7 +301,7 @@ void PeerEventHandler::OnReceiveDataBuffer(
|
|||||||
runtime->SetControllerPrivacySupport(
|
runtime->SetControllerPrivacySupport(
|
||||||
remote_id, remote_action.i.supports_privacy_screen);
|
remote_id, remote_action.i.supports_privacy_screen);
|
||||||
}
|
}
|
||||||
remote_action_codec::Free(remote_action);
|
FreeRemoteAction(remote_action);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// remote
|
// remote
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
#include "platform/video_renderer.h"
|
#include "platform/video_renderer.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
#include "runtime/gui_runtime.h"
|
#include "runtime/gui_runtime.h"
|
||||||
#include "runtime/remote_action_codec.h"
|
|
||||||
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
#include "interactive_state.h"
|
#include "interactive_state.h"
|
||||||
@@ -265,52 +264,22 @@ void PeerEventHandler::OnConnectionStatus(ConnectionStatus status,
|
|||||||
props->cursor_presentation_ = {};
|
props->cursor_presentation_ = {};
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
RemoteAction remote_action{};
|
RemoteAction remote_action = MakeHostInformation(
|
||||||
remote_action.i.supports_privacy_screen = true;
|
GetHostName(), runtime->devices_.host_display_list(),
|
||||||
remote_action.i.display_num =
|
/*supports_privacy_screen=*/true);
|
||||||
runtime->devices_.display_info_list().size();
|
for (std::size_t i = 0; i < remote_action.i.display_num; i++) {
|
||||||
remote_action.i.display_list =
|
|
||||||
(char**)malloc(remote_action.i.display_num * sizeof(char*));
|
|
||||||
remote_action.i.left =
|
|
||||||
(int*)malloc(remote_action.i.display_num * sizeof(int));
|
|
||||||
remote_action.i.top =
|
|
||||||
(int*)malloc(remote_action.i.display_num * sizeof(int));
|
|
||||||
remote_action.i.right =
|
|
||||||
(int*)malloc(remote_action.i.display_num * sizeof(int));
|
|
||||||
remote_action.i.bottom =
|
|
||||||
(int*)malloc(remote_action.i.display_num * sizeof(int));
|
|
||||||
for (int i = 0; i < remote_action.i.display_num; i++) {
|
|
||||||
LOG_INFO("Local display [{}:{}]", i + 1,
|
LOG_INFO("Local display [{}:{}]", i + 1,
|
||||||
runtime->devices_.display_info_list()[i].name);
|
remote_action.i.display_list[i]);
|
||||||
remote_action.i.display_list[i] = (char*)malloc(
|
|
||||||
runtime->devices_.display_info_list()[i].name.length() + 1);
|
|
||||||
strncpy(remote_action.i.display_list[i],
|
|
||||||
runtime->devices_.display_info_list()[i].name.c_str(),
|
|
||||||
runtime->devices_.display_info_list()[i].name.length());
|
|
||||||
remote_action.i
|
|
||||||
.display_list[i][runtime->devices_.display_info_list()[i]
|
|
||||||
.name.length()] = '\0';
|
|
||||||
remote_action.i.left[i] =
|
|
||||||
runtime->devices_.display_info_list()[i].left;
|
|
||||||
remote_action.i.top[i] =
|
|
||||||
runtime->devices_.display_info_list()[i].top;
|
|
||||||
remote_action.i.right[i] =
|
|
||||||
runtime->devices_.display_info_list()[i].right;
|
|
||||||
remote_action.i.bottom[i] =
|
|
||||||
runtime->devices_.display_info_list()[i].bottom;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string host_name = GetHostName();
|
|
||||||
remote_action.type = ControlType::host_infomation;
|
|
||||||
memcpy(&remote_action.i.host_name, host_name.data(),
|
|
||||||
host_name.size());
|
|
||||||
remote_action.i.host_name[host_name.size()] = '\0';
|
|
||||||
remote_action.i.host_name_size = host_name.size();
|
|
||||||
|
|
||||||
std::string msg = remote_action.to_json();
|
std::string msg = remote_action.to_json();
|
||||||
int ret = SendReliableDataFrame(props->peer_, msg.data(), msg.size(),
|
const int ret =
|
||||||
runtime->control_data_label_.c_str());
|
SendReliableDataFrame(props->peer_, msg.data(), msg.size(),
|
||||||
remote_action_codec::Free(remote_action);
|
runtime->control_data_label_.c_str());
|
||||||
|
if (ret != 0) {
|
||||||
|
LOG_WARN("[{}] host information send failed, ret={}", remote_id,
|
||||||
|
ret);
|
||||||
|
}
|
||||||
|
FreeRemoteAction(remote_action);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!runtime->need_to_create_stream_window_) {
|
if (!runtime->need_to_create_stream_window_) {
|
||||||
@@ -413,53 +382,22 @@ void PeerEventHandler::OnConnectionStatus(ConnectionStatus status,
|
|||||||
runtime->last_windows_service_status_tick_ = 0;
|
runtime->last_windows_service_status_tick_ = 0;
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
RemoteAction remote_action{};
|
RemoteAction remote_action = MakeHostInformation(
|
||||||
remote_action.i.supports_privacy_screen = true;
|
GetHostName(), runtime->devices_.host_display_list(),
|
||||||
remote_action.i.display_num =
|
/*supports_privacy_screen=*/true);
|
||||||
runtime->devices_.display_info_list().size();
|
for (std::size_t i = 0; i < remote_action.i.display_num; i++) {
|
||||||
remote_action.i.display_list =
|
|
||||||
(char**)malloc(remote_action.i.display_num * sizeof(char*));
|
|
||||||
remote_action.i.left =
|
|
||||||
(int*)malloc(remote_action.i.display_num * sizeof(int));
|
|
||||||
remote_action.i.top =
|
|
||||||
(int*)malloc(remote_action.i.display_num * sizeof(int));
|
|
||||||
remote_action.i.right =
|
|
||||||
(int*)malloc(remote_action.i.display_num * sizeof(int));
|
|
||||||
remote_action.i.bottom =
|
|
||||||
(int*)malloc(remote_action.i.display_num * sizeof(int));
|
|
||||||
for (int i = 0; i < remote_action.i.display_num; i++) {
|
|
||||||
LOG_INFO("Local display [{}:{}]", i + 1,
|
LOG_INFO("Local display [{}:{}]", i + 1,
|
||||||
runtime->devices_.display_info_list()[i].name);
|
remote_action.i.display_list[i]);
|
||||||
remote_action.i.display_list[i] = (char*)malloc(
|
|
||||||
runtime->devices_.display_info_list()[i].name.length() + 1);
|
|
||||||
strncpy(remote_action.i.display_list[i],
|
|
||||||
runtime->devices_.display_info_list()[i].name.c_str(),
|
|
||||||
runtime->devices_.display_info_list()[i].name.length());
|
|
||||||
remote_action.i
|
|
||||||
.display_list[i][runtime->devices_.display_info_list()[i]
|
|
||||||
.name.length()] = '\0';
|
|
||||||
remote_action.i.left[i] =
|
|
||||||
runtime->devices_.display_info_list()[i].left;
|
|
||||||
remote_action.i.top[i] =
|
|
||||||
runtime->devices_.display_info_list()[i].top;
|
|
||||||
remote_action.i.right[i] =
|
|
||||||
runtime->devices_.display_info_list()[i].right;
|
|
||||||
remote_action.i.bottom[i] =
|
|
||||||
runtime->devices_.display_info_list()[i].bottom;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string host_name = GetHostName();
|
|
||||||
remote_action.type = ControlType::host_infomation;
|
|
||||||
memcpy(&remote_action.i.host_name, host_name.data(),
|
|
||||||
host_name.size());
|
|
||||||
remote_action.i.host_name[host_name.size()] = '\0';
|
|
||||||
remote_action.i.host_name_size = host_name.size();
|
|
||||||
|
|
||||||
std::string msg = remote_action.to_json();
|
std::string msg = remote_action.to_json();
|
||||||
int ret =
|
const int ret =
|
||||||
SendReliableDataFrame(runtime->peer_, msg.data(), msg.size(),
|
SendReliableDataFrame(runtime->peer_, msg.data(), msg.size(),
|
||||||
runtime->control_data_label_.c_str());
|
runtime->control_data_label_.c_str());
|
||||||
remote_action_codec::Free(remote_action);
|
if (ret != 0) {
|
||||||
|
LOG_WARN("[{}] host information send failed, ret={}", remote_id,
|
||||||
|
ret);
|
||||||
|
}
|
||||||
|
FreeRemoteAction(remote_action);
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime->need_to_destroy_server_window_.store(
|
runtime->need_to_destroy_server_window_.store(
|
||||||
|
|||||||
@@ -1,120 +0,0 @@
|
|||||||
#include "runtime/remote_action_codec.h"
|
|
||||||
|
|
||||||
#include <remote_action.h>
|
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
namespace crossdesk::remote_action_codec {
|
|
||||||
|
|
||||||
std::vector<char> Serialize(const RemoteAction &action) {
|
|
||||||
std::vector<char> buffer;
|
|
||||||
buffer.push_back(static_cast<char>(action.type));
|
|
||||||
|
|
||||||
auto insert_bytes = [&](const void *ptr, size_t len) {
|
|
||||||
buffer.insert(buffer.end(), static_cast<const char *>(ptr),
|
|
||||||
static_cast<const char *>(ptr) + len);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (action.type == ControlType::host_infomation) {
|
|
||||||
insert_bytes(&action.i.host_name_size, sizeof(size_t));
|
|
||||||
insert_bytes(action.i.host_name, action.i.host_name_size);
|
|
||||||
|
|
||||||
size_t num = action.i.display_num;
|
|
||||||
insert_bytes(&num, sizeof(size_t));
|
|
||||||
|
|
||||||
for (size_t i = 0; i < num; ++i) {
|
|
||||||
const size_t len = std::strlen(action.i.display_list[i]);
|
|
||||||
insert_bytes(&len, sizeof(size_t));
|
|
||||||
insert_bytes(action.i.display_list[i], len);
|
|
||||||
}
|
|
||||||
|
|
||||||
insert_bytes(action.i.left, sizeof(int) * num);
|
|
||||||
insert_bytes(action.i.top, sizeof(int) * num);
|
|
||||||
insert_bytes(action.i.right, sizeof(int) * num);
|
|
||||||
insert_bytes(action.i.bottom, sizeof(int) * num);
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Deserialize(const char *data, size_t size, RemoteAction &out) {
|
|
||||||
size_t offset = 0;
|
|
||||||
auto read = [&](void *dst, size_t len) -> bool {
|
|
||||||
if (offset + len > size) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
std::memcpy(dst, data + offset, len);
|
|
||||||
offset += len;
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (size < 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
out.type = static_cast<ControlType>(data[offset++]);
|
|
||||||
|
|
||||||
if (out.type == ControlType::host_infomation) {
|
|
||||||
out.i.supports_privacy_screen = false;
|
|
||||||
size_t name_len;
|
|
||||||
if (!read(&name_len, sizeof(size_t)) ||
|
|
||||||
name_len >= sizeof(out.i.host_name)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!read(out.i.host_name, name_len)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
out.i.host_name[name_len] = '\0';
|
|
||||||
out.i.host_name_size = name_len;
|
|
||||||
|
|
||||||
size_t num;
|
|
||||||
if (!read(&num, sizeof(size_t))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
out.i.display_num = num;
|
|
||||||
|
|
||||||
out.i.display_list =
|
|
||||||
static_cast<char **>(std::malloc(num * sizeof(char *)));
|
|
||||||
for (size_t i = 0; i < num; ++i) {
|
|
||||||
size_t len;
|
|
||||||
if (!read(&len, sizeof(size_t)) || offset + len > size) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
out.i.display_list[i] = static_cast<char *>(std::malloc(len + 1));
|
|
||||||
std::memcpy(out.i.display_list[i], data + offset, len);
|
|
||||||
out.i.display_list[i][len] = '\0';
|
|
||||||
offset += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto alloc_int_array = [&](int *&array) {
|
|
||||||
array = static_cast<int *>(std::malloc(num * sizeof(int)));
|
|
||||||
return read(array, num * sizeof(int));
|
|
||||||
};
|
|
||||||
|
|
||||||
return alloc_int_array(out.i.left) && alloc_int_array(out.i.top) &&
|
|
||||||
alloc_int_array(out.i.right) && alloc_int_array(out.i.bottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Free(RemoteAction &action) {
|
|
||||||
if (action.type != ControlType::host_infomation) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < action.i.display_num; ++i) {
|
|
||||||
std::free(action.i.display_list[i]);
|
|
||||||
}
|
|
||||||
std::free(action.i.display_list);
|
|
||||||
std::free(action.i.left);
|
|
||||||
std::free(action.i.top);
|
|
||||||
std::free(action.i.right);
|
|
||||||
std::free(action.i.bottom);
|
|
||||||
|
|
||||||
action.i.display_list = nullptr;
|
|
||||||
action.i.left = action.i.top = action.i.right = action.i.bottom = nullptr;
|
|
||||||
action.i.display_num = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace crossdesk::remote_action_codec
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: DI JUNKUN
|
|
||||||
* @Date: 2026-09-04
|
|
||||||
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _REMOTE_ACTION_CODEC_H_
|
|
||||||
#define _REMOTE_ACTION_CODEC_H_
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <remote_action.h>
|
|
||||||
|
|
||||||
namespace crossdesk::remote_action_codec {
|
|
||||||
|
|
||||||
std::vector<char> Serialize(const RemoteAction &action);
|
|
||||||
bool Deserialize(const char *data, size_t size, RemoteAction &out);
|
|
||||||
void Free(RemoteAction &action);
|
|
||||||
|
|
||||||
} // namespace crossdesk::remote_action_codec
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -25,8 +25,7 @@ apps/desktop/src/gui/
|
|||||||
│ ├── device_presence_cache.h # 设备在线状态缓存
|
│ ├── device_presence_cache.h # 设备在线状态缓存
|
||||||
│ ├── peer_event_handler.h/.cpp # 信令和连接状态回调
|
│ ├── peer_event_handler.h/.cpp # 信令和连接状态回调
|
||||||
│ ├── peer_media_callbacks.cpp # 视频和音频回调
|
│ ├── peer_media_callbacks.cpp # 视频和音频回调
|
||||||
│ ├── peer_data_callbacks.cpp # 控制、剪贴板和文件数据回调
|
│ └── peer_data_callbacks.cpp # 控制、剪贴板和文件数据回调
|
||||||
│ └── remote_action_codec.h/.cpp # RemoteAction 编解码
|
|
||||||
├── features/ # 可独立演进的功能模块
|
├── features/ # 可独立演进的功能模块
|
||||||
│ ├── clipboard/ # 本地与远端剪贴板同步
|
│ ├── clipboard/ # 本地与远端剪贴板同步
|
||||||
│ ├── devices/ # 媒体及输入设备生命周期
|
│ ├── devices/ # 媒体及输入设备生命周期
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <remote_cursor_shape.h>
|
#include <remote_cursor_shape.h>
|
||||||
|
|
||||||
@@ -179,6 +180,25 @@ struct RemoteAction {
|
|||||||
// Other RemoteAction variants do not own memory and are left unchanged.
|
// Other RemoteAction variants do not own memory and are left unchanged.
|
||||||
void FreeRemoteAction(RemoteAction& action);
|
void FreeRemoteAction(RemoteAction& action);
|
||||||
|
|
||||||
|
// One display as advertised in host information; bounds are virtual-desktop
|
||||||
|
// pixel coordinates.
|
||||||
|
struct HostDisplay {
|
||||||
|
std::string name;
|
||||||
|
int left = 0;
|
||||||
|
int top = 0;
|
||||||
|
int right = 0;
|
||||||
|
int bottom = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Builds the host_infomation message advertised on every new connection.
|
||||||
|
// |host_name| is truncated to the wire field size. The display arrays are
|
||||||
|
// heap-allocated with the same layout the decoder produces; release the
|
||||||
|
// result with FreeRemoteAction. An allocation failure yields an empty display
|
||||||
|
// list rather than a partially filled one.
|
||||||
|
RemoteAction MakeHostInformation(const std::string& host_name,
|
||||||
|
const std::vector<HostDisplay>& displays,
|
||||||
|
bool supports_privacy_screen);
|
||||||
|
|
||||||
} // namespace crossdesk
|
} // namespace crossdesk
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -37,8 +37,47 @@ bool AllocateHostDisplays(HostInfo& info, std::size_t count) {
|
|||||||
info.bottom;
|
info.bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* DuplicateString(const std::string& value) {
|
||||||
|
char* copy = static_cast<char*>(std::malloc(value.size() + 1));
|
||||||
|
if (copy == nullptr) return nullptr;
|
||||||
|
std::memcpy(copy, value.data(), value.size());
|
||||||
|
copy[value.size()] = '\0';
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
RemoteAction MakeHostInformation(const std::string& host_name,
|
||||||
|
const std::vector<HostDisplay>& displays,
|
||||||
|
bool supports_privacy_screen) {
|
||||||
|
RemoteAction action{};
|
||||||
|
action.type = ControlType::host_infomation;
|
||||||
|
ResetHostInfo(action.i);
|
||||||
|
|
||||||
|
const std::size_t count = displays.size();
|
||||||
|
if (AllocateHostDisplays(action.i, count)) {
|
||||||
|
action.i.display_num = count;
|
||||||
|
for (std::size_t index = 0; index < count; ++index) {
|
||||||
|
const HostDisplay& display = displays[index];
|
||||||
|
action.i.display_list[index] = DuplicateString(display.name);
|
||||||
|
action.i.left[index] = display.left;
|
||||||
|
action.i.top[index] = display.top;
|
||||||
|
action.i.right[index] = display.right;
|
||||||
|
action.i.bottom[index] = display.bottom;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
FreeRemoteAction(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
action.i.supports_privacy_screen = supports_privacy_screen;
|
||||||
|
const std::size_t name_size =
|
||||||
|
std::min(host_name.size(), sizeof(action.i.host_name) - 1);
|
||||||
|
std::memcpy(action.i.host_name, host_name.data(), name_size);
|
||||||
|
action.i.host_name[name_size] = '\0';
|
||||||
|
action.i.host_name_size = name_size;
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
std::string RemoteAction::to_json() const { return ToJson(*this); }
|
std::string RemoteAction::to_json() const { return ToJson(*this); }
|
||||||
|
|
||||||
bool RemoteAction::from_json(const std::string& json_string) {
|
bool RemoteAction::from_json(const std::string& json_string) {
|
||||||
|
|||||||
Reference in New Issue
Block a user