Compare commits
3 Commits
979f309497
...
v1.3.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36ba9ccc1d | ||
|
|
ed4b9eeb25 | ||
|
|
cfa9b581fc |
55
ReadMe.md
55
ReadMe.md
@@ -12,7 +12,7 @@
|
|||||||
<a href="https://github.com/yuanyuanxiang/SimpleRemoter/releases">
|
<a href="https://github.com/yuanyuanxiang/SimpleRemoter/releases">
|
||||||
<img src="https://img.shields.io/github/v/release/yuanyuanxiang/SimpleRemoter?style=flat-square" alt="GitHub Release">
|
<img src="https://img.shields.io/github/v/release/yuanyuanxiang/SimpleRemoter?style=flat-square" alt="GitHub Release">
|
||||||
</a>
|
</a>
|
||||||
<img src="https://img.shields.io/badge/platform-Windows%20%7C%20Linux-blue?style=flat-square" alt="Platform">
|
<img src="https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-blue?style=flat-square" alt="Platform">
|
||||||
<img src="https://img.shields.io/badge/language-C%2B%2B17-orange?style=flat-square&logo=cplusplus" alt="Language">
|
<img src="https://img.shields.io/badge/language-C%2B%2B17-orange?style=flat-square&logo=cplusplus" alt="Language">
|
||||||
<img src="https://img.shields.io/badge/IDE-VS2019%2B-purple?style=flat-square&logo=visualstudio" alt="IDE">
|
<img src="https://img.shields.io/badge/IDE-VS2019%2B-purple?style=flat-square&logo=visualstudio" alt="IDE">
|
||||||
<img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License">
|
<img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License">
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
|
|
||||||
## 项目简介
|
## 项目简介
|
||||||
|
|
||||||
**SimpleRemoter** 是一个功能完整的远程控制解决方案,基于经典的 Gh0st 框架重构,采用现代 C++17 开发。项目始于 2019 年,经过持续迭代已发展为支持 **Windows + Linux** 双平台的企业级远程管理工具。
|
**SimpleRemoter** 是一个功能完整的远程控制解决方案,基于经典的 Gh0st 框架重构,采用现代 C++17 开发。项目始于 2019 年,经过持续迭代已发展为支持 **Windows + Linux + macOS** 三平台的企业级远程管理工具。
|
||||||
|
|
||||||
### 核心能力
|
### 核心能力
|
||||||
|
|
||||||
@@ -354,6 +354,7 @@ struct FileChunkPacketV2 {
|
|||||||
| `TestRun.exe` + `ServerDll.dll` | 分离加载,支持内存加载 DLL |
|
| `TestRun.exe` + `ServerDll.dll` | 分离加载,支持内存加载 DLL |
|
||||||
| Windows 服务 | 后台运行,支持锁屏控制 |
|
| Windows 服务 | 后台运行,支持锁屏控制 |
|
||||||
| Linux 客户端 | 跨平台支持(v1.2.5+) |
|
| Linux 客户端 | 跨平台支持(v1.2.5+) |
|
||||||
|
| macOS 客户端 | 跨平台支持(v1.3.2+) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -489,10 +490,60 @@ cmake .
|
|||||||
make
|
make
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### macOS 客户端(v1.3.2+)
|
||||||
|
|
||||||
|
**系统要求**:
|
||||||
|
- macOS 10.15 (Catalina) 及以上
|
||||||
|
- 需要授予系统权限:屏幕录制、辅助功能、完全磁盘访问
|
||||||
|
|
||||||
|
**功能支持**:
|
||||||
|
|
||||||
|
| 功能 | 状态 | 实现 |
|
||||||
|
|------|------|------|
|
||||||
|
| 远程桌面 | ✅ | CoreGraphics 屏幕捕获,H.264 硬件编码 |
|
||||||
|
| 鼠标控制 | ✅ | CGEvent 模拟,支持双击、拖拽 |
|
||||||
|
| 键盘控制 | ✅ | CGEvent 模拟,完整键码映射 |
|
||||||
|
| 光标同步 | ✅ | 实时同步远程光标样式 |
|
||||||
|
| 心跳/RTT | ✅ | RFC 6298 RTT 估算 |
|
||||||
|
| 文件管理 | ⏳ | 开发中 |
|
||||||
|
| 远程终端 | ⏳ | 开发中 |
|
||||||
|
|
||||||
|
**编译方式**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd macos
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 更新日志
|
## 更新日志
|
||||||
|
|
||||||
|
### v1.3.2 (2026.5.1)
|
||||||
|
|
||||||
|
**macOS 客户端 & Web 远程桌面增强**
|
||||||
|
|
||||||
|
**新功能:**
|
||||||
|
- macOS 客户端支持:全新实现的 macOS 原生客户端,支持屏幕捕获、H.264 编码、键鼠控制、系统权限管理
|
||||||
|
- Web 远程桌面光标同步:浏览器端实时显示远程主机光标样式
|
||||||
|
- 触发器功能:支持主机上线事件触发自定义操作
|
||||||
|
- 用户管理功能:新增角色权限管理,支持多用户分级控制
|
||||||
|
- DLL 执行增强:参数持久化存储、支持自动运行配置
|
||||||
|
- 远程桌面输入法切换:支持远程切换被控端输入语言
|
||||||
|
|
||||||
|
**改进:**
|
||||||
|
- Web 远程桌面手势优化:改进双指手势识别、双击拖拽、Shift 组合键支持
|
||||||
|
|
||||||
|
**Bug 修复:**
|
||||||
|
- 修复 Web 远程桌面在 macOS 客户端上双击无法打开文件的问题
|
||||||
|
- 修复 macOS 完全磁盘访问权限检测不准确的问题
|
||||||
|
- 修复 RestoreMemDLL 因 DLL 信息大小错误导致还原失败
|
||||||
|
- 修复多个 DLL 同时执行可能因全局变量冲突而失败
|
||||||
|
- 修复鼠标双击和远程桌面切换问题
|
||||||
|
- 修复 Linux 客户端编译缺少 libzstd.a 的问题
|
||||||
|
|
||||||
### v1.3.1 (2026.4.15)
|
### v1.3.1 (2026.4.15)
|
||||||
|
|
||||||
**Web 远程桌面 & 多主控共享增强**
|
**Web 远程桌面 & 多主控共享增强**
|
||||||
|
|||||||
55
ReadMe_EN.md
55
ReadMe_EN.md
@@ -12,7 +12,7 @@
|
|||||||
<a href="https://github.com/yuanyuanxiang/SimpleRemoter/releases">
|
<a href="https://github.com/yuanyuanxiang/SimpleRemoter/releases">
|
||||||
<img src="https://img.shields.io/github/v/release/yuanyuanxiang/SimpleRemoter?style=flat-square" alt="GitHub Release">
|
<img src="https://img.shields.io/github/v/release/yuanyuanxiang/SimpleRemoter?style=flat-square" alt="GitHub Release">
|
||||||
</a>
|
</a>
|
||||||
<img src="https://img.shields.io/badge/platform-Windows%20%7C%20Linux-blue?style=flat-square" alt="Platform">
|
<img src="https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-blue?style=flat-square" alt="Platform">
|
||||||
<img src="https://img.shields.io/badge/language-C%2B%2B17-orange?style=flat-square&logo=cplusplus" alt="Language">
|
<img src="https://img.shields.io/badge/language-C%2B%2B17-orange?style=flat-square&logo=cplusplus" alt="Language">
|
||||||
<img src="https://img.shields.io/badge/IDE-VS2019%2B-purple?style=flat-square&logo=visualstudio" alt="IDE">
|
<img src="https://img.shields.io/badge/IDE-VS2019%2B-purple?style=flat-square&logo=visualstudio" alt="IDE">
|
||||||
<img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License">
|
<img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License">
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
**SimpleRemoter** is a full-featured remote control solution, rebuilt from the classic Gh0st framework using modern C++17. Started in 2019, it has evolved into an enterprise-grade remote management tool supporting both **Windows and Linux** platforms.
|
**SimpleRemoter** is a full-featured remote control solution, rebuilt from the classic Gh0st framework using modern C++17. Started in 2019, it has evolved into an enterprise-grade remote management tool supporting **Windows, Linux, and macOS** platforms.
|
||||||
|
|
||||||
### Core Capabilities
|
### Core Capabilities
|
||||||
|
|
||||||
@@ -354,6 +354,7 @@ The master program **YAMA.exe** provides a graphical management interface:
|
|||||||
| `TestRun.exe` + `ServerDll.dll` | Separate loading, supports in-memory DLL loading |
|
| `TestRun.exe` + `ServerDll.dll` | Separate loading, supports in-memory DLL loading |
|
||||||
| Windows Service | Background operation, supports lock screen control |
|
| Windows Service | Background operation, supports lock screen control |
|
||||||
| Linux Client | Cross-platform support (v1.2.5+) |
|
| Linux Client | Cross-platform support (v1.2.5+) |
|
||||||
|
| macOS Client | Cross-platform support (v1.3.2+) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -474,10 +475,60 @@ cmake .
|
|||||||
make
|
make
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### macOS Client (v1.3.2+)
|
||||||
|
|
||||||
|
**System Requirements**:
|
||||||
|
- macOS 10.15 (Catalina) or later
|
||||||
|
- Required permissions: Screen Recording, Accessibility, Full Disk Access
|
||||||
|
|
||||||
|
**Feature Support**:
|
||||||
|
|
||||||
|
| Feature | Status | Implementation |
|
||||||
|
|---------|--------|----------------|
|
||||||
|
| Remote Desktop | ✅ | CoreGraphics screen capture, H.264 hardware encoding |
|
||||||
|
| Mouse Control | ✅ | CGEvent simulation, supports double-click, drag |
|
||||||
|
| Keyboard Control | ✅ | CGEvent simulation, full keycode mapping |
|
||||||
|
| Cursor Sync | ✅ | Real-time remote cursor style synchronization |
|
||||||
|
| Heartbeat/RTT | ✅ | RFC 6298 RTT estimation |
|
||||||
|
| File Management | ⏳ | In development |
|
||||||
|
| Remote Terminal | ⏳ | In development |
|
||||||
|
|
||||||
|
**Build Instructions**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd macos
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### v1.3.2 (2026.5.1)
|
||||||
|
|
||||||
|
**macOS Client & Web Remote Desktop Enhancement**
|
||||||
|
|
||||||
|
**New Features:**
|
||||||
|
- macOS client support: Native macOS client with screen capture, H.264 encoding, keyboard/mouse control, system permission management
|
||||||
|
- Web remote desktop cursor sync: Real-time display of remote host cursor style in browser
|
||||||
|
- Trigger functionality: Support custom actions triggered by host online events
|
||||||
|
- User management: Role-based permission management, multi-user hierarchical control
|
||||||
|
- DLL execution enhancements: Parameter persistence, auto-run configuration support
|
||||||
|
- Remote desktop input language switching: Support switching remote host input language
|
||||||
|
|
||||||
|
**Improvements:**
|
||||||
|
- Web remote desktop gesture optimization: Improved two-finger gesture recognition, double-tap drag, Shift key combination support
|
||||||
|
|
||||||
|
**Bug Fixes:**
|
||||||
|
- Fixed Web remote desktop double-click not working for macOS clients
|
||||||
|
- Fixed macOS Full Disk Access permission detection inaccuracy
|
||||||
|
- Fixed RestoreMemDLL failure due to incorrect DLL info size
|
||||||
|
- Fixed multiple DLLs execution failure due to global variable conflict
|
||||||
|
- Fixed mouse double-click and remote desktop switching issues
|
||||||
|
- Fixed Linux client build missing libzstd.a
|
||||||
|
|
||||||
### v1.3.1 (2026.4.15)
|
### v1.3.1 (2026.4.15)
|
||||||
|
|
||||||
**Web Remote Desktop & Multi-Master Sharing Enhancement**
|
**Web Remote Desktop & Multi-Master Sharing Enhancement**
|
||||||
|
|||||||
55
ReadMe_TW.md
55
ReadMe_TW.md
@@ -12,7 +12,7 @@
|
|||||||
<a href="https://github.com/yuanyuanxiang/SimpleRemoter/releases">
|
<a href="https://github.com/yuanyuanxiang/SimpleRemoter/releases">
|
||||||
<img src="https://img.shields.io/github/v/release/yuanyuanxiang/SimpleRemoter?style=flat-square" alt="GitHub Release">
|
<img src="https://img.shields.io/github/v/release/yuanyuanxiang/SimpleRemoter?style=flat-square" alt="GitHub Release">
|
||||||
</a>
|
</a>
|
||||||
<img src="https://img.shields.io/badge/platform-Windows%20%7C%20Linux-blue?style=flat-square" alt="Platform">
|
<img src="https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-blue?style=flat-square" alt="Platform">
|
||||||
<img src="https://img.shields.io/badge/language-C%2B%2B17-orange?style=flat-square&logo=cplusplus" alt="Language">
|
<img src="https://img.shields.io/badge/language-C%2B%2B17-orange?style=flat-square&logo=cplusplus" alt="Language">
|
||||||
<img src="https://img.shields.io/badge/IDE-VS2019%2B-purple?style=flat-square&logo=visualstudio" alt="IDE">
|
<img src="https://img.shields.io/badge/IDE-VS2019%2B-purple?style=flat-square&logo=visualstudio" alt="IDE">
|
||||||
<img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License">
|
<img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License">
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
## 專案簡介
|
## 專案簡介
|
||||||
|
|
||||||
**SimpleRemoter** 是一個功能完整的遠端控制解決方案,基於經典的 Gh0st 框架重構,採用現代 C++17 開發。專案始於 2019 年,經過持續迭代已發展為支援 **Windows + Linux** 雙平台的企業級遠端管理工具。
|
**SimpleRemoter** 是一個功能完整的遠端控制解決方案,基於經典的 Gh0st 框架重構,採用現代 C++17 開發。專案始於 2019 年,經過持續迭代已發展為支援 **Windows + Linux + macOS** 三平台的企業級遠端管理工具。
|
||||||
|
|
||||||
### 核心能力
|
### 核心能力
|
||||||
|
|
||||||
@@ -353,6 +353,7 @@ struct FileChunkPacketV2 {
|
|||||||
| `TestRun.exe` + `ServerDll.dll` | 分離載入,支援記憶體載入 DLL |
|
| `TestRun.exe` + `ServerDll.dll` | 分離載入,支援記憶體載入 DLL |
|
||||||
| Windows 服務 | 背景執行,支援鎖定畫面控制 |
|
| Windows 服務 | 背景執行,支援鎖定畫面控制 |
|
||||||
| Linux 用戶端 | 跨平台支援(v1.2.5+) |
|
| Linux 用戶端 | 跨平台支援(v1.2.5+) |
|
||||||
|
| macOS 用戶端 | 跨平台支援(v1.3.2+) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -473,10 +474,60 @@ cmake .
|
|||||||
make
|
make
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### macOS 用戶端(v1.3.2+)
|
||||||
|
|
||||||
|
**系統要求**:
|
||||||
|
- macOS 10.15 (Catalina) 及以上
|
||||||
|
- 需要授予系統權限:螢幕錄製、輔助使用、完全磁碟存取
|
||||||
|
|
||||||
|
**功能支援**:
|
||||||
|
|
||||||
|
| 功能 | 狀態 | 實作 |
|
||||||
|
|------|------|------|
|
||||||
|
| 遠端桌面 | ✅ | CoreGraphics 螢幕擷取,H.264 硬體編碼 |
|
||||||
|
| 滑鼠控制 | ✅ | CGEvent 模擬,支援雙擊、拖曳 |
|
||||||
|
| 鍵盤控制 | ✅ | CGEvent 模擬,完整鍵碼對應 |
|
||||||
|
| 游標同步 | ✅ | 即時同步遠端游標樣式 |
|
||||||
|
| 心跳/RTT | ✅ | RFC 6298 RTT 估算 |
|
||||||
|
| 檔案管理 | ⏳ | 開發中 |
|
||||||
|
| 遠端終端 | ⏳ | 開發中 |
|
||||||
|
|
||||||
|
**編譯方式**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd macos
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 更新日誌
|
## 更新日誌
|
||||||
|
|
||||||
|
### v1.3.2 (2026.5.1)
|
||||||
|
|
||||||
|
**macOS 用戶端 & Web 遠端桌面增強**
|
||||||
|
|
||||||
|
**新功能:**
|
||||||
|
- macOS 用戶端支援:全新實現的 macOS 原生用戶端,支援螢幕擷取、H.264 編碼、鍵鼠控制、系統權限管理
|
||||||
|
- Web 遠端桌面游標同步:瀏覽器端即時顯示遠端主機游標樣式
|
||||||
|
- 觸發器功能:支援主機上線事件觸發自訂操作
|
||||||
|
- 使用者管理功能:新增角色權限管理,支援多使用者分級控制
|
||||||
|
- DLL 執行增強:參數持久化儲存、支援自動執行設定
|
||||||
|
- 遠端桌面輸入法切換:支援遠端切換被控端輸入語言
|
||||||
|
|
||||||
|
**改進:**
|
||||||
|
- Web 遠端桌面手勢最佳化:改進雙指手勢識別、雙擊拖曳、Shift 組合鍵支援
|
||||||
|
|
||||||
|
**Bug 修復:**
|
||||||
|
- 修復 Web 遠端桌面在 macOS 用戶端上雙擊無法開啟檔案的問題
|
||||||
|
- 修復 macOS 完全磁碟存取權限偵測不準確的問題
|
||||||
|
- 修復 RestoreMemDLL 因 DLL 資訊大小錯誤導致還原失敗
|
||||||
|
- 修復多個 DLL 同時執行可能因全域變數衝突而失敗
|
||||||
|
- 修復滑鼠雙擊和遠端桌面切換問題
|
||||||
|
- 修復 Linux 用戶端編譯缺少 libzstd.a 的問題
|
||||||
|
|
||||||
### v1.3.1 (2026.4.15)
|
### v1.3.1 (2026.4.15)
|
||||||
|
|
||||||
**Web 遠端桌面 & 多主控共享增強**
|
**Web 遠端桌面 & 多主控共享增強**
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ IDR_WAVE WAVE "Res\\msg.wav"
|
|||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,0,3,1
|
FILEVERSION 1,0,3,2
|
||||||
PRODUCTVERSION 1,0,0,1
|
PRODUCTVERSION 1,0,0,1
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
@@ -106,7 +106,7 @@ BEGIN
|
|||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "FUCK THE UNIVERSE"
|
VALUE "CompanyName", "FUCK THE UNIVERSE"
|
||||||
VALUE "FileDescription", "A GHOST"
|
VALUE "FileDescription", "A GHOST"
|
||||||
VALUE "FileVersion", "1.0.3.1"
|
VALUE "FileVersion", "1.0.3.2"
|
||||||
VALUE "InternalName", "ServerDll.dll"
|
VALUE "InternalName", "ServerDll.dll"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2019-2026"
|
VALUE "LegalCopyright", "Copyright (C) 2019-2026"
|
||||||
VALUE "OriginalFilename", "ServerDll.dll"
|
VALUE "OriginalFilename", "ServerDll.dll"
|
||||||
|
|||||||
Binary file not shown.
@@ -156,6 +156,8 @@ void InputHandler::handleMouseButton(CGMouseButton button, bool down, int x, int
|
|||||||
|
|
||||||
CGEventRef event = CGEventCreateMouseEvent(NULL, eventType, point, button);
|
CGEventRef event = CGEventCreateMouseEvent(NULL, eventType, point, button);
|
||||||
if (event) {
|
if (event) {
|
||||||
|
// clickState=1 for all single clicks
|
||||||
|
CGEventSetIntegerValueField(event, kCGMouseEventClickState, 1);
|
||||||
CGEventPost(kCGHIDEventTap, event);
|
CGEventPost(kCGHIDEventTap, event);
|
||||||
CFRelease(event);
|
CFRelease(event);
|
||||||
}
|
}
|
||||||
@@ -163,6 +165,13 @@ void InputHandler::handleMouseButton(CGMouseButton button, bool down, int x, int
|
|||||||
|
|
||||||
void InputHandler::handleMouseDoubleClick(CGMouseButton button, int x, int y)
|
void InputHandler::handleMouseDoubleClick(CGMouseButton button, int x, int y)
|
||||||
{
|
{
|
||||||
|
// WM_LBUTTONDBLCLK represents the second click of a double-click.
|
||||||
|
// The first click was already sent via WM_LBUTTONDOWN/WM_LBUTTONUP.
|
||||||
|
//
|
||||||
|
// We send complete down(2) + up(2) here because:
|
||||||
|
// - Web client: dblclick fires AFTER mouseup, no subsequent WM_LBUTTONUP
|
||||||
|
// - MFC client: WM_LBUTTONUP follows, but extra up(1) is harmless
|
||||||
|
|
||||||
CGPoint point = CGPointMake(x, y);
|
CGPoint point = CGPointMake(x, y);
|
||||||
m_lastMousePos = point;
|
m_lastMousePos = point;
|
||||||
|
|
||||||
@@ -184,36 +193,24 @@ void InputHandler::handleMouseDoubleClick(CGMouseButton button, int x, int y)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// First click (clickState=1)
|
// Send second click: down(2) + up(2)
|
||||||
CGEventRef down1 = CGEventCreateMouseEvent(NULL, downType, point, button);
|
CGEventRef down = CGEventCreateMouseEvent(NULL, downType, point, button);
|
||||||
CGEventRef up1 = CGEventCreateMouseEvent(NULL, upType, point, button);
|
CGEventRef up = CGEventCreateMouseEvent(NULL, upType, point, button);
|
||||||
|
|
||||||
if (down1 && up1) {
|
if (down) {
|
||||||
CGEventSetIntegerValueField(down1, kCGMouseEventClickState, 1);
|
CGEventSetIntegerValueField(down, kCGMouseEventClickState, 2);
|
||||||
CGEventSetIntegerValueField(up1, kCGMouseEventClickState, 1);
|
CGEventPost(kCGHIDEventTap, down);
|
||||||
CGEventPost(kCGHIDEventTap, down1);
|
CFRelease(down);
|
||||||
CGEventPost(kCGHIDEventTap, up1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (down1) CFRelease(down1);
|
if (up) {
|
||||||
if (up1) CFRelease(up1);
|
CGEventSetIntegerValueField(up, kCGMouseEventClickState, 2);
|
||||||
|
CGEventPost(kCGHIDEventTap, up);
|
||||||
// Brief delay between clicks (50ms)
|
CFRelease(up);
|
||||||
usleep(50000);
|
|
||||||
|
|
||||||
// Second click (clickState=2)
|
|
||||||
CGEventRef down2 = CGEventCreateMouseEvent(NULL, downType, point, button);
|
|
||||||
CGEventRef up2 = CGEventCreateMouseEvent(NULL, upType, point, button);
|
|
||||||
|
|
||||||
if (down2 && up2) {
|
|
||||||
CGEventSetIntegerValueField(down2, kCGMouseEventClickState, 2);
|
|
||||||
CGEventSetIntegerValueField(up2, kCGMouseEventClickState, 2);
|
|
||||||
CGEventPost(kCGHIDEventTap, down2);
|
|
||||||
CGEventPost(kCGHIDEventTap, up2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (down2) CFRelease(down2);
|
// Note: For MFC client, an extra WM_LBUTTONUP will follow (sending up(1)),
|
||||||
if (up2) CFRelease(up2);
|
// but this is harmless since mouse is already up.
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputHandler::handleMouseWheel(int delta)
|
void InputHandler::handleMouseWheel(int delta)
|
||||||
|
|||||||
@@ -49,30 +49,38 @@ void Permissions::openAccessibilitySettings() {
|
|||||||
|
|
||||||
bool Permissions::checkFullDiskAccess() {
|
bool Permissions::checkFullDiskAccess() {
|
||||||
// There's no official API to check Full Disk Access.
|
// There's no official API to check Full Disk Access.
|
||||||
// We try to read a protected file that requires FDA permission.
|
// Try to actually read a protected file that requires FDA.
|
||||||
// Safari bookmarks is a commonly used test file.
|
|
||||||
|
|
||||||
NSArray* testPaths = @[
|
NSString* testPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Safari/Bookmarks.plist"];
|
||||||
[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Safari/Bookmarks.plist"],
|
|
||||||
[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Safari/CloudTabs.db"],
|
|
||||||
@"/Library/Application Support/com.apple.TCC/TCC.db",
|
|
||||||
[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/com.apple.TCC/TCC.db"]
|
|
||||||
];
|
|
||||||
|
|
||||||
NSFileManager* fm = [NSFileManager defaultManager];
|
NSFileManager* fm = [NSFileManager defaultManager];
|
||||||
for (NSString* path in testPaths) {
|
if ([fm fileExistsAtPath:testPath]) {
|
||||||
if ([fm fileExistsAtPath:path]) {
|
// Try to actually read the file (more reliable than isReadableFileAtPath)
|
||||||
// File exists, try to read it
|
NSData* data = [NSData dataWithContentsOfFile:testPath];
|
||||||
if ([fm isReadableFileAtPath:path]) {
|
if (data != nil) {
|
||||||
return true; // Can read protected file = FDA granted
|
NSLog(@"FDA check: OK (can read Safari bookmarks)");
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false; // File exists but can't read = FDA not granted
|
NSLog(@"FDA check: FAILED (Safari bookmarks exists but unreadable)");
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If none of the test files exist, assume FDA is granted
|
// Safari bookmarks doesn't exist, try TCC database
|
||||||
// (edge case: fresh system without Safari history)
|
testPath = @"/Library/Application Support/com.apple.TCC/TCC.db";
|
||||||
|
if ([fm fileExistsAtPath:testPath]) {
|
||||||
|
NSData* data = [NSData dataWithContentsOfFile:testPath];
|
||||||
|
if (data != nil) {
|
||||||
|
NSLog(@"FDA check: OK (can read TCC.db)");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
NSLog(@"FDA check: FAILED (TCC.db exists but unreadable)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No test files exist, assume OK
|
||||||
|
NSLog(@"FDA check: SKIPPED (no test files found)");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ ScreenHandler::ScreenHandler(IOCPClient* client)
|
|||||||
, m_algorithm(ALGORITHM_H264)
|
, m_algorithm(ALGORITHM_H264)
|
||||||
, m_maxFPS(15)
|
, m_maxFPS(15)
|
||||||
, m_qualityLevel(QUALITY_GOOD) // Use fixed QUALITY_GOOD (H264) for web compatibility
|
, m_qualityLevel(QUALITY_GOOD) // Use fixed QUALITY_GOOD (H264) for web compatibility
|
||||||
, m_h264Bitrate(2000000) // 2 Mbps default
|
, m_h264Bitrate(3000000) // 3 Mbps (matches Windows QUALITY_GOOD)
|
||||||
{
|
{
|
||||||
memset(&m_bmpHeader, 0, sizeof(m_bmpHeader));
|
memset(&m_bmpHeader, 0, sizeof(m_bmpHeader));
|
||||||
|
|
||||||
|
|||||||
@@ -272,8 +272,8 @@ static void fillLoginInfo(LOGIN_INFOR& info)
|
|||||||
// Reserved fields (pipe-separated, must match Windows client order)
|
// Reserved fields (pipe-separated, must match Windows client order)
|
||||||
// Order: Type|Bits|Cores|Memory|Path|?|InstallTime|?|ProgBits|Auth|Location|IP|Version|User|IsAdmin|Resolution|ClientID
|
// Order: Type|Bits|Cores|Memory|Path|?|InstallTime|?|ProgBits|Auth|Location|IP|Version|User|IsAdmin|Resolution|ClientID
|
||||||
|
|
||||||
// 1. Client type
|
// 1. Client type (use GetClientType for consistency with Windows client)
|
||||||
info.AddReserved("macOS");
|
info.AddReserved(GetClientType(CLIENT_TYPE_MACOS));
|
||||||
|
|
||||||
// 2. System bits (OS bits, always 64 on modern macOS)
|
// 2. System bits (OS bits, always 64 on modern macOS)
|
||||||
info.AddReserved(64);
|
info.AddReserved(64);
|
||||||
@@ -496,10 +496,11 @@ int main(int argc, const char* argv[])
|
|||||||
Permissions::requestAccessibility();
|
Permissions::requestAccessibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FDA check is unreliable (no official API), just log a warning
|
||||||
if (!Permissions::checkFullDiskAccess()) {
|
if (!Permissions::checkFullDiskAccess()) {
|
||||||
NSLog(@"Full Disk Access permission not granted.");
|
NSLog(@"Full Disk Access: not detected (may be false negative).");
|
||||||
NSLog(@"Please grant permission in System Preferences > Privacy & Security > Full Disk Access");
|
NSLog(@"If file access issues occur, grant FDA in System Preferences > Privacy & Security > Full Disk Access");
|
||||||
Permissions::openFullDiskAccessSettings();
|
// Don't auto-open settings since detection is unreliable
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create client
|
// Create client
|
||||||
|
|||||||
Binary file not shown.
@@ -541,6 +541,7 @@
|
|||||||
<Image Include="res\Bitmap\Notify.bmp" />
|
<Image Include="res\Bitmap\Notify.bmp" />
|
||||||
<Image Include="res\Bitmap\PEEdit.bmp" />
|
<Image Include="res\Bitmap\PEEdit.bmp" />
|
||||||
<Image Include="res\Bitmap\Plugin.bmp" />
|
<Image Include="res\Bitmap\Plugin.bmp" />
|
||||||
|
<Image Include="res\Bitmap\PluginConfig.bmp" />
|
||||||
<Image Include="res\Bitmap\PortProxyStd.bmp" />
|
<Image Include="res\Bitmap\PortProxyStd.bmp" />
|
||||||
<Image Include="res\Bitmap\PrivateScreen.bmp" />
|
<Image Include="res\Bitmap\PrivateScreen.bmp" />
|
||||||
<Image Include="res\Bitmap\proxy.bmp" />
|
<Image Include="res\Bitmap\proxy.bmp" />
|
||||||
@@ -554,10 +555,12 @@
|
|||||||
<Image Include="res\Bitmap\Shutdown.bmp" />
|
<Image Include="res\Bitmap\Shutdown.bmp" />
|
||||||
<Image Include="res\Bitmap\SpeedDesktop.bmp" />
|
<Image Include="res\Bitmap\SpeedDesktop.bmp" />
|
||||||
<Image Include="res\Bitmap\Trial.bmp" />
|
<Image Include="res\Bitmap\Trial.bmp" />
|
||||||
|
<Image Include="res\Bitmap\Trigger.bmp" />
|
||||||
<Image Include="res\Bitmap\unauthorize.bmp" />
|
<Image Include="res\Bitmap\unauthorize.bmp" />
|
||||||
<Image Include="res\Bitmap\update.bmp" />
|
<Image Include="res\Bitmap\update.bmp" />
|
||||||
<Image Include="res\Bitmap\VirtualDesktop.bmp" />
|
<Image Include="res\Bitmap\VirtualDesktop.bmp" />
|
||||||
<Image Include="res\Bitmap\Wallet.bmp" />
|
<Image Include="res\Bitmap\Wallet.bmp" />
|
||||||
|
<Image Include="res\Bitmap\WebDesktop.bmp" />
|
||||||
<Image Include="res\Bitmap_4.bmp" />
|
<Image Include="res\Bitmap_4.bmp" />
|
||||||
<Image Include="res\Bitmap_5.bmp" />
|
<Image Include="res\Bitmap_5.bmp" />
|
||||||
<Image Include="res\chat.ico" />
|
<Image Include="res\chat.ico" />
|
||||||
|
|||||||
@@ -268,6 +268,9 @@
|
|||||||
<Image Include="res\Bitmap\Trial.bmp" />
|
<Image Include="res\Bitmap\Trial.bmp" />
|
||||||
<Image Include="res\Bitmap\RequestAuth.bmp" />
|
<Image Include="res\Bitmap\RequestAuth.bmp" />
|
||||||
<Image Include="res\Bitmap\CancelShare.bmp" />
|
<Image Include="res\Bitmap\CancelShare.bmp" />
|
||||||
|
<Image Include="res\Bitmap\Trigger.bmp" />
|
||||||
|
<Image Include="res\Bitmap\WebDesktop.bmp" />
|
||||||
|
<Image Include="res\Bitmap\PluginConfig.bmp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\..\Release\ghost.exe" />
|
<None Include="..\..\Release\ghost.exe" />
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
|
|
||||||
// 程序版本号 [建议格式: X.Y.Z]
|
// 程序版本号 [建议格式: X.Y.Z]
|
||||||
// 影响:关于对话框、标题栏
|
// 影响:关于对话框、标题栏
|
||||||
#define BRAND_VERSION "1.3.1"
|
#define BRAND_VERSION "1.3.2"
|
||||||
|
|
||||||
// 启动画面名称 [建议大写,更有 Logo 感]
|
// 启动画面名称 [建议大写,更有 Logo 感]
|
||||||
// 影响:启动画面 Logo 文字(大号艺术字体渲染)
|
// 影响:启动画面 Logo 文字(大号艺术字体渲染)
|
||||||
|
|||||||
@@ -2696,7 +2696,12 @@ inline std::string GetWebPageHTML() {
|
|||||||
sendMouse('up', pos.x, pos.y, e.button);
|
sendMouse('up', pos.x, pos.y, e.button);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Note: dblclick is handled by mousedown-mouseup sequence, no separate handler needed
|
// dblclick handler - server will forward only to macOS clients
|
||||||
|
canvas.addEventListener('dblclick', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const pos = getMousePos(e);
|
||||||
|
sendMouse('dblclick', pos.x, pos.y, e.button);
|
||||||
|
});
|
||||||
|
|
||||||
canvas.addEventListener('mousemove', function(e) {
|
canvas.addEventListener('mousemove', function(e) {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
|||||||
@@ -770,6 +770,15 @@ void CWebService::HandleMouse(void* ws_ptr, const std::string& msg) {
|
|||||||
short wheelDelta = (short)(delta > 0 ? -120 : (delta < 0 ? 120 : 0));
|
short wheelDelta = (short)(delta > 0 ? -120 : (delta < 0 ? 120 : 0));
|
||||||
msg64.wParam = MAKEWPARAM(0, wheelDelta);
|
msg64.wParam = MAKEWPARAM(0, wheelDelta);
|
||||||
} else if (type == "dblclick") {
|
} else if (type == "dblclick") {
|
||||||
|
// dblclick is only needed for macOS clients
|
||||||
|
// Windows detects double-click from rapid mousedown/mouseup sequence
|
||||||
|
context* mainCtx = m_pParentDlg->FindHost(device_id);
|
||||||
|
if (!mainCtx) return;
|
||||||
|
CString clientType = mainCtx->GetAdditionalData(RES_CLIENT_TYPE);
|
||||||
|
// Check for both "MAC" (new) and "macOS" (legacy) for compatibility
|
||||||
|
if (clientType != GetClientType(CLIENT_TYPE_MACOS) && clientType != "macOS") {
|
||||||
|
return; // Skip dblclick for non-macOS clients
|
||||||
|
}
|
||||||
if (button == 0) {
|
if (button == 0) {
|
||||||
msg64.message = WM_LBUTTONDBLCLK;
|
msg64.message = WM_LBUTTONDBLCLK;
|
||||||
msg64.wParam = MK_LBUTTON;
|
msg64.wParam = MK_LBUTTON;
|
||||||
|
|||||||
Reference in New Issue
Block a user