Skip to content

Commit

Permalink
Merge branch 'rustdesk:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
zhangbo8418 authored Dec 7, 2024
2 parents 46dceea + 1c17fdd commit 01f1b33
Show file tree
Hide file tree
Showing 15 changed files with 98 additions and 131 deletions.
32 changes: 16 additions & 16 deletions docs/README-KR.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
<b>README를 모국어로 번역하기 위한 당신의 도움의 필요합니다.</b>
</p>

Chat with us: [Discord](https://discord.gg/nDceKgxnkV) | [Twitter](https://twitter.com/rustdesk) | [Reddit](https://www.reddit.com/r/rustdesk)
채팅하기: [Discord](https://discord.gg/nDceKgxnkV) | [Twitter](https://twitter.com/rustdesk) | [Reddit](https://www.reddit.com/r/rustdesk)


[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09)

Rust로 작성되었고, 설정없이 바로 사용할 수 있는 원격 데스트탑 소프트웨어입니다. 자신의 데이터를 완전히 컨트롤할 수 있고, 보안의 염려도 없습니다. 우리의 rendezvous/relay 서버를 사용해도, [스스로 설정](https://rustdesk.com/server)하는 것도, [스스로 rendezvous/relay 서버를 작성할 수도 있습니다](https://github.com/rustdesk/rustdesk-server-demo).
Rust로 작성되었고, 설정없이 바로 사용할 수 있는 원격 데스트탑 소프트웨어입니다. 자신의 데이터를 완전히 컨트롤할 수 있고, 보안의 염려도 없습니다. 우리의 rendezvous/relay 서버를 사용해도, [직접 설정](https://rustdesk.com/server)하거나 [직접 rendezvous/relay 서버를 작성할 수도 있습니다](https://github.com/rustdesk/rustdesk-server-demo).

![image](https://user-images.githubusercontent.com/71636191/171661982-430285f0-2e12-4b1d-9957-4a58e375304d.png)

Expand Down Expand Up @@ -43,9 +43,9 @@ RustDesk는 모든 기여를 환영합니다. 기여하고자 한다면 [`docs/C
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus aom

- run `cargo run`
- 실행 `cargo run`

## [Build](https://rustdesk.com/docs/en/dev/build/)
## [빌드](https://rustdesk.com/docs/en/dev/build/)

## Linux에서 빌드 순서

Expand All @@ -67,7 +67,7 @@ sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-
sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pipewire
```

### Install vcpkg
### vcpkg 설치

```sh
git clone https://github.com/microsoft/vcpkg
Expand All @@ -79,7 +79,7 @@ export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus aom
```

### Fix libvpx (For Fedora)
### libvpx 수정 (For Fedora용)

```sh
cd vcpkg/buildtrees/libvpx/src
Expand All @@ -92,7 +92,7 @@ cp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/
cd
```

### Build
### 빌드

```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Expand All @@ -107,21 +107,21 @@ VCPKG_ROOT=$HOME/vcpkg cargo run

## Docker에 빌드하는 방법

레포지토리를 클론하고, Docker 컨테이너 구성하는 것으로 시작합니다.
리포지토리를 클론하고, Docker 컨테이너 구성하는 것으로 시작합니다.

```sh
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
docker build -t "rustdesk-builder" .
```

이후, 애플리케이션을 빌드할 필요가 있을 때마다, 이하의 커맨드를 실행합니다.
이후, 애플리케이션을 빌드할 필요가 있을 때마다, 아래의의 명령을 실행합니다.

```sh
docker run --rm -it -v $PWD:/home/user/rustdesk -v rustdesk-git-cache:/home/user/.cargo/git -v rustdesk-registry-cache:/home/user/.cargo/registry -e PUID="$(id -u)" -e PGID="$(id -g)" rustdesk-builder
```

첫 빌드에서는 의존관계가 캐시될 때까지 시간이 걸릴 수 있습니다만, 이후의 빌드때는 빨라집니다. 더불어 빌드 커맨드에 다른 인수를 지정할 필요가 있다면, 커맨드 끝에 있는 `<OPTIONAL-ARGS>` 에 지정할 수 있습니다. 예를 들어 최적화된 출시 버전을 빌드하고 싶다면 이렇게 상기한 커맨드 뒤에 `--release` 를 붙여 실행합니다. 성공했다면 실행파일은 시스템 타겟 폴더에 담겨지고, 다음 커맨드로 실행할 수 있습니다.
첫 빌드에서는 의존관계가 캐시될 때까지 시간이 걸릴 수 있습니다만, 이후의 빌드때는 빨라집니다. 더불어 빌드 명령에 다른 인수를 지정할 필요가 있다면, 명령 끝에 있는 `<OPTIONAL-ARGS>` 에 지정할 수 있습니다. 예를 들어 최적화된 출시 버전을 빌드하고 싶다면 이렇게 상기한 명령 뒤에 `--release` 를 붙여 실행합니다. 성공했다면 실행파일은 시스템 타겟 폴더에 담겨지고, 다음 명령으로 실행할 수 있습니다.

```sh
target/debug/rustdesk
Expand All @@ -133,22 +133,22 @@ target/debug/rustdesk
target/release/rustdesk
```

커맨드를 RustDesk 리포지토리 루트에서 실행한다는 것을 확인해주세요. 그렇게 하지 않으면 애플리케이션이 필요한 리소스를 발견하지 못 할 가능성이 있습니다. 또한 `install`, `run` 같은 cargo 서브커맨드는 호스트가 아니라 컨테이너 프로그램을 설치, 실행을 위함이므로 현재 이 방법은 지원하지 않다는 점을 유념해주시길 바랍니다.
명령을 RustDesk 리포지토리 루트에서 실행한다는 것을 확인해주세요. 그렇게 하지 않으면 애플리케이션이 필요한 리소스를 발견하지 못 할 가능성이 있습니다. 또한 `install`, `run` 같은 cargo 하위 명령은 호스트가 아니라 컨테이너 프로그램을 설치, 실행을 위함이므로 현재 이 방법은 지원하지 않다는 점을 유념해주시길 바랍니다.

## File Structure
## 파일 구조

- **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)**: 비디오 코덱, 설정, tcp/udp 랩퍼, protobuf, 파일 전송을 위한 fs 함수, 그 외 유틸리티 함수
- **[libs/scrap](https://github.com/rustdesk/rustdesk/tree/master/libs/scrap)**: 화면 캡처
- **[libs/enigo](https://github.com/rustdesk/rustdesk/tree/master/libs/enigo)**: 플랫폼 고유 키보드/마우스 컨트롤
- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: GUI
- **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)**: 오디오, 클립보드, 입력, 비디오 서비스 그리고 네트워크 연결
- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: 피어 접속 시작
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: [rustdesk-server](https://github.com/rustdesk/rustdesk-server)와 통신해서 리모트 다이렉트(TCP hole punching) 혹은 relayed 접속
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: [rustdesk-server](https://github.com/rustdesk/rustdesk-server)와 통신해서 리모트 다이렉트 (TCP hole punching) 혹은 relayed 접속
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: 플랫폼 고유의 코드
- **[flutter](https://github.com/rustdesk/rustdesk/tree/master/flutter)**: Flutter code for mobile
- **[flutter/web/js](https://github.com/rustdesk/rustdesk/tree/master/flutter/web/js)**: Javascript for Flutter web client
- **[flutter](https://github.com/rustdesk/rustdesk/tree/master/flutter)**: 모바일용 Flutter 코드
- **[flutter/web/js](https://github.com/rustdesk/rustdesk/tree/master/flutter/web/js)**: Flutter 웹 클라이언트용 자바스크립트

## Snapshot
## 스냅샷

![image](https://user-images.githubusercontent.com/71636191/113112362-ae4deb80-923b-11eb-957d-ff88daad4f06.png)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,8 @@ class FloatingWindowService : Service(), View.OnTouchListener {
popupMenu.menu.add(0, idShowRustDesk, 0, translate("Show RustDesk"))
// For host side, clipboard sync
val idSyncClipboard = 1
val isClipboardListenerEnabled = MainActivity.rdClipboardManager?.isListening ?: false
if (isClipboardListenerEnabled) {
val isServiceSyncEnabled = (MainActivity.rdClipboardManager?.isCaptureStarted ?: false) && FFI.isServiceClipboardEnabled()
if (isServiceSyncEnabled) {
popupMenu.menu.add(0, idSyncClipboard, 0, translate("Update client clipboard"))
}
val idStopService = 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ class MainActivity : FlutterActivity() {
mainService?.let {
unbindService(serviceConnection)
}
rdClipboardManager?.rustEnableServiceClipboard(false)
super.onDestroy()
}

Expand Down Expand Up @@ -221,6 +220,10 @@ class MainActivity : FlutterActivity() {
result.success(true)

}
"try_sync_clipboard" -> {
rdClipboardManager?.syncClipboard(true)
result.success(true)
}
GET_START_ON_BOOT_OPT -> {
val prefs = getSharedPreferences(KEY_SHARED_PREFERENCES, MODE_PRIVATE)
result.success(prefs.getBoolean(KEY_START_ON_BOOT_OPT, false))
Expand Down Expand Up @@ -402,13 +405,4 @@ class MainActivity : FlutterActivity() {
super.onStart()
stopService(Intent(this, FloatingWindowService::class.java))
}

// For client side
// When swithing from other app to this app, try to sync clipboard.
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus) {
rdClipboardManager?.syncClipboard(true)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,7 @@ class MainService : Service() {
checkMediaPermission()
_isStart = true
FFI.setFrameRawEnable("video",true)
MainActivity.rdClipboardManager?.setCaptureStarted(_isStart)
return true
}

Expand All @@ -441,6 +442,7 @@ class MainService : Service() {
Log.d(logTag, "Stop Capture")
FFI.setFrameRawEnable("video",false)
_isStart = false
MainActivity.rdClipboardManager?.setCaptureStarted(_isStart)
// release video
if (reuseVirtualDisplay) {
// The virtual display video projection can be paused by calling `setSurface(null)`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,19 @@ class RdClipboardManager(private val clipboardManager: ClipboardManager) {
// though the `lastUpdatedClipData` will be set to null once.
private var lastUpdatedClipData: ClipData? = null
private var isClientEnabled = true;
private var _isListening = false;
val isListening: Boolean
get() = _isListening
private var _isCaptureStarted = false;

fun checkPrimaryClip(isClient: Boolean, isSync: Boolean) {
val isCaptureStarted: Boolean
get() = _isCaptureStarted

fun checkPrimaryClip(isClient: Boolean) {
val clipData = clipboardManager.primaryClip
if (clipData != null && clipData.itemCount > 0) {
// Only handle the first item in the clipboard for now.
val clip = clipData.getItemAt(0)
val isHostSync = !isClient && isSync
// Ignore the `isClipboardDataEqual()` check if it's a host sync operation.
// Because it's a action manually triggered by the user.
if (!isHostSync) {
// Ignore the `isClipboardDataEqual()` check if it's a host operation.
// Because it's an action manually triggered by the user.
if (isClient) {
if (lastUpdatedClipData != null && isClipboardDataEqual(clipData, lastUpdatedClipData!!)) {
Log.d(logTag, "Clipboard data is the same as last update, ignore")
return
Expand Down Expand Up @@ -95,13 +95,6 @@ class RdClipboardManager(private val clipboardManager: ClipboardManager) {
}
}

private val clipboardListener = object : ClipboardManager.OnPrimaryClipChangedListener {
override fun onPrimaryClipChanged() {
Log.d(logTag, "onPrimaryClipChanged")
checkPrimaryClip(true, false)
}
}

private fun isSupportedMimeType(mimeType: String): Boolean {
return supportedMimeTypes.contains(mimeType)
}
Expand Down Expand Up @@ -136,43 +129,23 @@ class RdClipboardManager(private val clipboardManager: ClipboardManager) {
return true
}

@Keep
fun rustEnableServiceClipboard(enable: Boolean) {
Log.d(logTag, "rustEnableServiceClipboard: enable: $enable, _isListening: $_isListening")
if (enable) {
if (!_isListening) {
clipboardManager.addPrimaryClipChangedListener(clipboardListener)
_isListening = true
}
} else {
if (_isListening) {
clipboardManager.removePrimaryClipChangedListener(clipboardListener)
_isListening = false
lastUpdatedClipData = null
}
}
fun setCaptureStarted(started: Boolean) {
_isCaptureStarted = started
}

@Keep
fun rustEnableClientClipboard(enable: Boolean) {
Log.d(logTag, "rustEnableClientClipboard: enable: $enable")
isClientEnabled = enable
if (enable) {
lastUpdatedClipData = clipboardManager.primaryClip
} else {
lastUpdatedClipData = null
}
lastUpdatedClipData = null
}

fun syncClipboard(isClient: Boolean) {
Log.d(logTag, "syncClipboard: isClient: $isClient, isClientEnabled: $isClientEnabled, _isListening: $_isListening")
Log.d(logTag, "syncClipboard: isClient: $isClient, isClientEnabled: $isClientEnabled")
if (isClient && !isClientEnabled) {
return
}
if (!isClient && !_isListening) {
return
}
checkPrimaryClip(isClient, true)
checkPrimaryClip(isClient)
}

@Keep
Expand Down
1 change: 1 addition & 0 deletions flutter/android/app/src/main/kotlin/ffi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ object FFI {
external fun setCodecInfo(info: String)
external fun getLocalOption(key: String): String
external fun onClipboardUpdate(clips: ByteBuffer)
external fun isServiceClipboardEnabled(): Boolean
}
13 changes: 13 additions & 0 deletions flutter/lib/mobile/pages/remote_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,19 @@ class _RemotePageState extends State<RemotePage> with WidgetsBindingObserver {
gFFI.chatModel.onVoiceCallClosed("End connetion");
}

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
trySyncClipboard();
}
}

// For client side
// When swithing from other app to this app, try to sync clipboard.
void trySyncClipboard() {
gFFI.invokeMethod("try_sync_clipboard");
}

@override
void didChangeMetrics() {
// If the soft keyboard is visible and the canvas has been changed(panned or scaled)
Expand Down
4 changes: 2 additions & 2 deletions flutter/lib/models/server_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -323,10 +323,10 @@ class ServerModel with ChangeNotifier {
}

toggleClipboard() async {
_clipboardOk = !_clipboardOk;
_clipboardOk = !clipboardOk;
bind.mainSetOption(
key: kOptionEnableClipboard,
value: _clipboardOk ? defaultOptionYes : 'N');
value: clipboardOk ? defaultOptionYes : 'N');
notifyListeners();
}

Expand Down
8 changes: 0 additions & 8 deletions libs/scrap/src/android/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,14 +371,6 @@ pub fn call_clipboard_manager_update_clipboard(data: &[u8]) -> JniResult<()> {
}
}

pub fn call_clipboard_manager_enable_service_clipboard(enable: bool) -> JniResult<()> {
_call_clipboard_manager(
"rustEnableServiceClipboard",
"(Z)V",
&[JValue::Bool(jboolean::from(enable))],
)
}

pub fn call_clipboard_manager_enable_client_clipboard(enable: bool) -> JniResult<()> {
_call_clipboard_manager(
"rustEnableClientClipboard",
Expand Down
36 changes: 18 additions & 18 deletions src/flutter_ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -831,30 +831,22 @@ pub fn main_show_option(_key: String) -> SyncReturn<bool> {
SyncReturn(false)
}

#[inline]
#[cfg(target_os = "android")]
fn enable_server_clipboard(keyboard_enabled: &str, clip_enabled: &str) {
use scrap::android::ffi::call_clipboard_manager_enable_service_clipboard;
let keyboard_enabled =
config::option2bool(config::keys::OPTION_ENABLE_KEYBOARD, &keyboard_enabled);
let clip_enabled = config::option2bool(config::keys::OPTION_ENABLE_CLIPBOARD, &clip_enabled);
crate::ui_cm_interface::switch_permission_all("clipboard".to_owned(), clip_enabled);
let _ = call_clipboard_manager_enable_service_clipboard(keyboard_enabled && clip_enabled);
}

pub fn main_set_option(key: String, value: String) {
#[cfg(target_os = "android")]
if key.eq(config::keys::OPTION_ENABLE_KEYBOARD) {
crate::ui_cm_interface::notify_input_control(config::option2bool(
config::keys::OPTION_ENABLE_KEYBOARD,
&value,
));
enable_server_clipboard(&value, &get_option(config::keys::OPTION_ENABLE_CLIPBOARD));
crate::ui_cm_interface::switch_permission_all(
"keyboard".to_owned(),
config::option2bool(&key, &value),
);
}
#[cfg(target_os = "android")]
if key.eq(config::keys::OPTION_ENABLE_CLIPBOARD) {
enable_server_clipboard(&get_option(config::keys::OPTION_ENABLE_KEYBOARD), &value);
crate::ui_cm_interface::switch_permission_all(
"clipboard".to_owned(),
config::option2bool(&key, &value),
);
}

if key.eq("custom-rendezvous-server") {
set_option(key, value.clone());
#[cfg(target_os = "android")]
Expand Down Expand Up @@ -2348,7 +2340,7 @@ pub mod server_side {
use jni::{
errors::{Error as JniError, Result as JniResult},
objects::{JClass, JObject, JString},
sys::jstring,
sys::{jboolean, jstring},
JNIEnv,
};

Expand Down Expand Up @@ -2421,4 +2413,12 @@ pub mod server_side {
};
return env.new_string(res).unwrap_or_default().into_raw();
}

#[no_mangle]
pub unsafe extern "system" fn Java_ffi_FFI_isServiceClipboardEnabled(
env: JNIEnv,
_class: JClass,
) -> jboolean {
jboolean::from(crate::server::is_clipboard_service_ok())
}
}
2 changes: 0 additions & 2 deletions src/ipc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,6 @@ pub enum Data {
MouseMoveTime(i64),
Authorize,
Close,
#[cfg(target_os = "android")]
InputControl(bool),
#[cfg(windows)]
SAS,
UserSid(Option<u32>),
Expand Down
2 changes: 2 additions & 0 deletions src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ pub mod audio_service;
cfg_if::cfg_if! {
if #[cfg(not(target_os = "ios"))] {
mod clipboard_service;
#[cfg(target_os = "android")]
pub use clipboard_service::is_clipboard_service_ok;
#[cfg(target_os = "linux")]
pub(crate) mod wayland;
#[cfg(target_os = "linux")]
Expand Down
Loading

0 comments on commit 01f1b33

Please sign in to comment.