mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-09-01 14:33:18 +08:00
[refactor] reorganize platform and wire sources
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2026-09-01
|
||||
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DISPLAY_STREAM_ID_H_
|
||||
#define _DISPLAY_STREAM_ID_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
// MiniRTC stream identifiers are wire-facing logical identifiers. Keep
|
||||
// them independent from platform display handles and user-visible names, both
|
||||
// of which may change or contain duplicate/Unicode text.
|
||||
inline std::string MakeDisplayStreamId(size_t display_index) {
|
||||
return "Display" + std::to_string(display_index + 1);
|
||||
}
|
||||
|
||||
inline bool IsRegisteredDisplayStreamId(const std::string& stream_id,
|
||||
size_t display_count) {
|
||||
if (stream_id.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t index = 0; index < display_count; ++index) {
|
||||
if (stream_id == MakeDisplayStreamId(index)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Resolves a backend-reported identifier to a stream registered with MiniRTC.
|
||||
// Backends should report MakeDisplayStreamId(index); the fallbacks keep older
|
||||
// capture plugins and hotplug transitions safe.
|
||||
inline std::string ResolveDisplayStreamId(
|
||||
const char* reported_id, size_t display_count, int preferred_index = -1,
|
||||
const std::string& previous_id = {}) {
|
||||
const std::string candidate = reported_id ? reported_id : "";
|
||||
if (IsRegisteredDisplayStreamId(candidate, display_count)) {
|
||||
return candidate;
|
||||
}
|
||||
|
||||
if (preferred_index >= 0 &&
|
||||
preferred_index < static_cast<int>(display_count)) {
|
||||
return MakeDisplayStreamId(static_cast<size_t>(preferred_index));
|
||||
}
|
||||
|
||||
if (IsRegisteredDisplayStreamId(previous_id, display_count)) {
|
||||
return previous_id;
|
||||
}
|
||||
|
||||
if (display_count == 1) {
|
||||
return MakeDisplayStreamId(0);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace crossdesk
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2026-09-01
|
||||
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _FILE_TRANSFER_FORMAT_H_
|
||||
#define _FILE_TRANSFER_FORMAT_H_
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
inline constexpr uint32_t kFileChunkMagic = 0x4A4E544D; // 'JNTM'
|
||||
inline constexpr uint32_t kFileAckMagic = 0x4A4E5443; // 'JNTC'
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct FileChunkHeader {
|
||||
uint32_t magic;
|
||||
uint32_t file_id;
|
||||
uint64_t offset;
|
||||
uint64_t total_size;
|
||||
uint32_t chunk_size;
|
||||
uint16_t name_len;
|
||||
uint8_t flags;
|
||||
};
|
||||
|
||||
struct FileTransferAck {
|
||||
uint32_t magic;
|
||||
uint32_t file_id;
|
||||
uint64_t acked_offset;
|
||||
uint64_t total_size;
|
||||
uint32_t flags;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
static_assert(sizeof(FileChunkHeader) == 31,
|
||||
"FileChunkHeader wire layout must remain stable");
|
||||
static_assert(sizeof(FileTransferAck) == 28,
|
||||
"FileTransferAck wire layout must remain stable");
|
||||
|
||||
struct FileChunkView {
|
||||
FileChunkHeader header{};
|
||||
std::string file_name;
|
||||
const char* payload = nullptr;
|
||||
std::size_t payload_size = 0;
|
||||
};
|
||||
|
||||
std::vector<char> EncodeFileChunk(uint32_t file_id, uint64_t offset,
|
||||
uint64_t total_size, const char* data,
|
||||
uint32_t data_size,
|
||||
const std::string* file_name, bool is_first,
|
||||
bool is_last);
|
||||
|
||||
bool DecodeFileChunk(const char* data, std::size_t size,
|
||||
FileChunkView* output);
|
||||
|
||||
std::array<char, sizeof(FileTransferAck)> EncodeFileTransferAck(
|
||||
const FileTransferAck& ack);
|
||||
|
||||
bool DecodeFileTransferAck(const char* data, std::size_t size,
|
||||
FileTransferAck* output);
|
||||
|
||||
} // namespace crossdesk
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2026-09-01
|
||||
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _REMOTE_ACTION_H_
|
||||
#define _REMOTE_ACTION_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include <remote_cursor_shape.h>
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
enum ControlType {
|
||||
invalid = -1,
|
||||
mouse = 0,
|
||||
keyboard = 1,
|
||||
audio_capture = 2,
|
||||
host_infomation = 3,
|
||||
display_id = 4,
|
||||
service_status = 5,
|
||||
service_command = 6,
|
||||
keyboard_state = 7,
|
||||
cursor_state = 8,
|
||||
};
|
||||
|
||||
enum MouseFlag {
|
||||
move = 0,
|
||||
left_down,
|
||||
left_up,
|
||||
right_down,
|
||||
right_up,
|
||||
middle_down,
|
||||
middle_up,
|
||||
wheel_vertical,
|
||||
wheel_horizontal,
|
||||
};
|
||||
|
||||
enum KeyFlag { key_down = 0, key_up };
|
||||
enum ServiceCommandFlag { send_sas = 0, lock_workstation };
|
||||
|
||||
struct Mouse {
|
||||
float x;
|
||||
float y;
|
||||
int s;
|
||||
MouseFlag flag;
|
||||
};
|
||||
|
||||
struct Key {
|
||||
std::size_t key_value;
|
||||
uint32_t scan_code;
|
||||
bool extended;
|
||||
KeyFlag flag;
|
||||
};
|
||||
|
||||
inline constexpr std::size_t kMaxKeyboardStateKeys = 32;
|
||||
|
||||
struct KeyboardStateKey {
|
||||
std::size_t key_value;
|
||||
uint32_t scan_code;
|
||||
bool extended;
|
||||
};
|
||||
|
||||
struct KeyboardState {
|
||||
uint32_t seq;
|
||||
std::size_t pressed_count;
|
||||
KeyboardStateKey pressed_keys[kMaxKeyboardStateKeys];
|
||||
};
|
||||
|
||||
struct CursorState {
|
||||
uint32_t seq;
|
||||
bool visible;
|
||||
RemoteCursorShape shape;
|
||||
bool position_valid;
|
||||
float x;
|
||||
float y;
|
||||
// Normalized displacement from the input hotspot to the visible cursor
|
||||
// anchor. This is presentation metadata and must not affect input mapping.
|
||||
float visual_offset_x;
|
||||
float visual_offset_y;
|
||||
int display_id;
|
||||
// Whether receivers should apply the position fields in this message.
|
||||
// Shape-only updates set this to false so cursor appearance can remain
|
||||
// responsive while position feedback to the input source is suppressed.
|
||||
bool position_update;
|
||||
};
|
||||
|
||||
struct HostInfo {
|
||||
char host_name[64];
|
||||
std::size_t host_name_size;
|
||||
char** display_list;
|
||||
std::size_t display_num;
|
||||
int* left;
|
||||
int* top;
|
||||
int* right;
|
||||
int* bottom;
|
||||
};
|
||||
|
||||
struct ServiceStatus {
|
||||
bool available;
|
||||
char interactive_stage[32];
|
||||
};
|
||||
|
||||
struct ServiceCommand {
|
||||
ServiceCommandFlag flag;
|
||||
};
|
||||
|
||||
struct RemoteAction {
|
||||
ControlType type = ControlType::invalid;
|
||||
union {
|
||||
Mouse m;
|
||||
Key k;
|
||||
KeyboardState ks;
|
||||
CursorState cs;
|
||||
HostInfo i;
|
||||
bool a;
|
||||
int d;
|
||||
ServiceStatus ss;
|
||||
ServiceCommand c;
|
||||
};
|
||||
|
||||
std::string to_json() const;
|
||||
bool from_json(const std::string& json_string);
|
||||
|
||||
static std::string ToJson(const RemoteAction& action);
|
||||
static bool FromJson(const std::string& json_string, RemoteAction& output);
|
||||
};
|
||||
|
||||
// Releases the dynamically allocated display arrays held by host information.
|
||||
// Other RemoteAction variants do not own memory and are left unchanged.
|
||||
void FreeRemoteAction(RemoteAction& action);
|
||||
|
||||
} // namespace crossdesk
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2026-09-01
|
||||
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _REMOTE_CURSOR_SHAPE_H_
|
||||
#define _REMOTE_CURSOR_SHAPE_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
// Keep these values aligned with Slint's MouseCursor enum. The wire
|
||||
// intentionally carries a semantic cursor instead of a platform handle so a
|
||||
// Windows, macOS or Linux host can control a different desktop platform.
|
||||
enum class RemoteCursorShape : uint8_t {
|
||||
default_cursor = 0,
|
||||
none,
|
||||
help,
|
||||
pointer,
|
||||
progress,
|
||||
wait,
|
||||
crosshair,
|
||||
text,
|
||||
alias,
|
||||
copy,
|
||||
move,
|
||||
no_drop,
|
||||
not_allowed,
|
||||
grab,
|
||||
grabbing,
|
||||
col_resize,
|
||||
row_resize,
|
||||
n_resize,
|
||||
e_resize,
|
||||
s_resize,
|
||||
w_resize,
|
||||
ne_resize,
|
||||
nw_resize,
|
||||
se_resize,
|
||||
sw_resize,
|
||||
ew_resize,
|
||||
ns_resize,
|
||||
nesw_resize,
|
||||
nwse_resize,
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2026-09-01
|
||||
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _STREAM_NAMES_H_
|
||||
#define _STREAM_NAMES_H_
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
inline constexpr char kAudioStream[] = "control_audio";
|
||||
inline constexpr char kDataStream[] = "data";
|
||||
inline constexpr char kMouseStream[] = "mouse";
|
||||
inline constexpr char kKeyboardStream[] = "keyboard";
|
||||
inline constexpr char kControlStream[] = "control_data";
|
||||
inline constexpr char kFileStream[] = "file";
|
||||
inline constexpr char kFileFeedbackStream[] = "file_feedback";
|
||||
inline constexpr char kClipboardStream[] = "clipboard";
|
||||
|
||||
inline constexpr std::size_t kFileChunkSize = 64 * 1024;
|
||||
inline constexpr std::size_t kMaxClipboardBytes = 128 * 1024;
|
||||
|
||||
} // namespace crossdesk
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user