[feat] add mobile privacy controls and Windows secure text input

This commit is contained in:
dijunkun
2026-10-27 02:37:23 +08:00
parent 1e25ec15e1
commit b15925f857
37 changed files with 795 additions and 80 deletions
@@ -123,6 +123,10 @@ typedef struct {
didReceiveServiceAvailable:(BOOL)available;
- (void)rtcBridge:(CrossDeskRTCBridge *)bridge
didSendSecureAttention:(BOOL)success;
- (void)rtcBridge:(CrossDeskRTCBridge *)bridge
didReceivePrivacyStatus:(NSData *)data;
- (void)rtcBridge:(CrossDeskRTCBridge *)bridge
didSendPrivacyRequest:(uint32_t)requestID success:(BOOL)success;
- (void)rtcBridge:(CrossDeskRTCBridge *)bridge
didUpdateFileTransfer:(NSString *)fileName
progress:(double)progress
@@ -186,6 +190,9 @@ typedef struct {
- (void)sendClipboardText:(NSString *)text;
- (void)sendFileAtURL:(NSURL *)fileURL;
- (void)sendSecureAttentionSequence;
- (void)sendPrivacyCommand:(BOOL)enable
blockLocalInput:(BOOL)blockLocalInput
requestID:(uint32_t)requestID;
@end
@@ -1043,6 +1043,30 @@ Params MakeParams(const RTCState &state, const std::string &user_id,
});
}
- (void)sendPrivacyCommand:(BOOL)enable
blockLocalInput:(BOOL)blockLocalInput
requestID:(uint32_t)requestID {
const uint64_t generation = _activeControllerGeneration.load();
dispatch_async(_rtcQueue, ^{
if (![self isControllerGenerationActive:generation]) return;
RemoteAction action{};
action.type = ControlType::privacy_command;
action.pc = {enable ? crossdesk::PrivacyCommandFlag::enable
: crossdesk::PrivacyCommandFlag::disable,
static_cast<bool>(blockLocalInput)};
const auto message = action.to_json();
const BOOL success = self->_state->controller_peer &&
SendReliableDataFrame(self->_state->controller_peer, message.data(),
message.size(), kControlStream) == 0;
DispatchMain(^{
if (![self isControllerGenerationActive:generation]) return;
id<CrossDeskRTCBridgeDelegate> delegate = self.delegate;
if ([delegate respondsToSelector:@selector(rtcBridge:didSendPrivacyRequest:success:)])
[delegate rtcBridge:self didSendPrivacyRequest:requestID success:success];
});
});
}
- (void)sendSecureAttentionSequence {
const uint64_t generation = _activeControllerGeneration.load();
dispatch_async(_rtcQueue, ^{
@@ -1409,6 +1433,7 @@ Params MakeParams(const RTCState &state, const std::string &user_id,
RemoteAction action{};
action.type = ControlType::host_infomation;
action.i.platform = crossdesk::HostPlatform::IOS;
action.i.supports_privacy_screen = true;
CopyCString(action.i.host_name, sizeof(action.i.host_name),
controller_name);
action.i.host_name_size = std::strlen(action.i.host_name);
@@ -1694,6 +1719,17 @@ Params MakeParams(const RTCState &state, const std::string &user_id,
if (source == kControlStream) {
RemoteAction action{};
if (!action.from_json(std::string(data, size))) return;
if (action.type == ControlType::privacy_status) {
const auto message = action.to_json();
NSData *status = [NSData dataWithBytes:message.data() length:message.size()];
DispatchMain(^{
if (![self isControllerGenerationActive:generation]) return;
id<CrossDeskRTCBridgeDelegate> delegate = self.delegate;
if ([delegate respondsToSelector:@selector(rtcBridge:didReceivePrivacyStatus:)])
[delegate rtcBridge:self didReceivePrivacyStatus:status];
});
return;
}
if (action.type == ControlType::video_settings_status) {
[self notifyVideoSettings:action.vs generation:generation];
return;