mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-02-19 07:09:10 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad0a24ba23 |
995
Cargo.lock
generated
995
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -46,7 +46,7 @@ cpal = { git = "https://github.com/rustaudio/cpal" }
|
||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||
machine-uid = "0.2"
|
||||
mac_address = "1.1"
|
||||
sciter-rs = { git = "https://github.com/sciter-sdk/rust-sciter", rev = "7702fb17290e76606bdd7010a0c3cbb32e85db76" }
|
||||
sciter-rs = { git = "https://github.com/sciter-sdk/rust-sciter" }
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
systray = { path = "libs/systray-rs" }
|
||||
|
||||
75
README.md
75
README.md
@@ -1,10 +1,10 @@
|
||||
# RustDesk | Your Remote Desktop Software
|
||||
### RustDesk | Your Remote Desktop Software
|
||||
|
||||
The best open-source remote desktop client software, written in Rust. Works out of the box, no configuration required. Great alternative to TeamViewer and AnyDesk! You have full control of your data, with no concerns about security. You can use our rendezvous/relay server, [set up your own](https://rustdesk.com/blog/id-relay-set/), or write your own rendezvous/relay server.
|
||||
The best open source remote desktop software written with Rust.
|
||||
|
||||
[**BINARY DOWNLOAD**](https://github.com/rustdesk/rustdesk/releases)
|
||||
|
||||
## Dependencies
|
||||
## Dependence
|
||||
|
||||
Desktop versions use [sciter](https://sciter.com/) for GUI, please download sciter dynamic library yourself.
|
||||
|
||||
@@ -12,68 +12,16 @@ Desktop versions use [sciter](https://sciter.com/) for GUI, please download scit
|
||||
[Linux](https://github.com/c-smile/sciter-sdk/raw/dc65744b66389cd5a0ff6bdb7c63a8b7b05a708b/bin.lnx/x64/libsciter-gtk.so)
|
||||
[Osx](https://github.com/c-smile/sciter-sdk/raw/dc65744b66389cd5a0ff6bdb7c63a8b7b05a708b/bin.osx/sciter-osx-64.dylib)
|
||||
|
||||
## How To Build
|
||||
|
||||
## Raw steps to build
|
||||
* Prepare your Rust development env and C++ build env
|
||||
|
||||
* Install [vcpkg](https://github.com/microsoft/vcpkg), and set `VCPKG_ROOT` env variable correctly
|
||||
* Install [vcpkg](https://github.com/microsoft/vcpkg), and set VCPKG_ROOT env variable correctly
|
||||
|
||||
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
|
||||
- Linux/Osx: vcpkg install libvpx libyuv opus
|
||||
|
||||
* run `cargo run`
|
||||
|
||||
## How to build on Linux
|
||||
|
||||
### Ubuntu 18 (Debian 10)
|
||||
```
|
||||
sudo apt install -y g++ gcc git curl wget nasm yasm libgtk-3-dev clang libxcb-randr0-dev libxdo-dev libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev libpulse-dev cmake
|
||||
```
|
||||
|
||||
### Fedora 28 (CentOS 8)
|
||||
```
|
||||
sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel
|
||||
```
|
||||
|
||||
### Arch (Manjaro)
|
||||
```
|
||||
sudo pacman -Syu unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pulseaudio
|
||||
```
|
||||
|
||||
### Install vcpkg
|
||||
```
|
||||
git clone https://github.com/microsoft/vcpkg --branch 2020.11-1
|
||||
vcpkg/bootstrap-vcpkg.sh
|
||||
export VCPKG_ROOT=$HOME/vcpkg
|
||||
vcpkg/vcpkg install libvpx libyuv opus
|
||||
```
|
||||
|
||||
### Fix libvpx (For Fedora)
|
||||
```
|
||||
cd vcpkg/buildtrees/libvpx/src
|
||||
cd *
|
||||
./configure
|
||||
sed -i 's/CFLAGS+=-I/CFLAGS+=-fPIC -I/g' Makefile
|
||||
sed -i 's/CXXFLAGS+=-I/CXXFLAGS+=-fPIC -I/g' Makefile
|
||||
make
|
||||
cp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/
|
||||
cd
|
||||
```
|
||||
|
||||
### Build
|
||||
```
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
source $HOME/.cargo/env
|
||||
git clone https://github.com/rustdesk/rustdesk
|
||||
cd rustdesk
|
||||
mkdir -p target/debug
|
||||
wget https://github.com/c-smile/sciter-sdk/raw/dc65744b66389cd5a0ff6bdb7c63a8b7b05a708b/bin.lnx/x64/libsciter-gtk.so
|
||||
mv libsciter-gtk.so target/debug
|
||||
cargo run
|
||||
```
|
||||
|
||||
### Change Wayland to X11 (Xorg)
|
||||
RustDesk does not support Wayland. Check [this](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) to configuring Xorg as the default GNOME session.
|
||||
* cargo run
|
||||
|
||||
## File Structure
|
||||
|
||||
@@ -85,14 +33,3 @@ RustDesk does not support Wayland. Check [this](https://docs.fedoraproject.org/e
|
||||
- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: start a peer connection
|
||||
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: Communicate with [rustdesk-server](https://github.com/rustdesk/rustdesk-server), wait for remote direct (TCP hole punching) or relayed connection
|
||||
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: platform specific code
|
||||
|
||||
## Snapshot
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
4
build.rs
4
build.rs
@@ -1,7 +1,7 @@
|
||||
#[cfg(windows)]
|
||||
fn build_windows() {
|
||||
cc::Build::new().file("src/windows.cc").compile("windows");
|
||||
println!("cargo:rustc-link-lib=WtsApi32");
|
||||
cc::Build::new().file("windows.cc").compile("windows");
|
||||
// println!("cargo:rustc-link-lib=WtsApi32");
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-changed=windows.cc");
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "hbb_common"
|
||||
version = "0.1.0"
|
||||
authors = ["rustdesk<info@rustdesk.com>"]
|
||||
authors = ["open-trade <info@opentradesolutions.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -109,7 +109,6 @@ message LocalAddr {
|
||||
bytes socket_addr = 1;
|
||||
bytes local_addr = 2;
|
||||
string relay_server = 3;
|
||||
string id = 4;
|
||||
}
|
||||
|
||||
message RendezvousMessage {
|
||||
|
||||
@@ -31,7 +31,7 @@ fn find_package(name: &str) -> Vec<PathBuf> {
|
||||
if lib == "vpx" && target_os == "windows" {
|
||||
lib = format!("{}mt", lib);
|
||||
}
|
||||
println!("{}", format!("cargo:rustc-link-lib=static={}", lib));
|
||||
println!("{}", format!("cargo:rustc-link-lib={}", lib));
|
||||
println!(
|
||||
"{}",
|
||||
format!(
|
||||
|
||||
118
oboe.cc
Normal file
118
oboe.cc
Normal file
@@ -0,0 +1,118 @@
|
||||
#include <oboe/Oboe.h>
|
||||
#include <math.h>
|
||||
#include <deque>
|
||||
#include <pthread.h>
|
||||
|
||||
// I got link problem with std::mutex, so use pthread instead
|
||||
class CThreadLock
|
||||
{
|
||||
public:
|
||||
CThreadLock();
|
||||
virtual ~CThreadLock();
|
||||
|
||||
void Lock();
|
||||
void Unlock();
|
||||
|
||||
private:
|
||||
pthread_mutex_t mutexlock;
|
||||
};
|
||||
|
||||
CThreadLock::CThreadLock()
|
||||
{
|
||||
// init lock here
|
||||
pthread_mutex_init(&mutexlock, 0);
|
||||
}
|
||||
|
||||
CThreadLock::~CThreadLock()
|
||||
{
|
||||
// deinit lock here
|
||||
pthread_mutex_destroy(&mutexlock);
|
||||
}
|
||||
void CThreadLock::Lock()
|
||||
{
|
||||
// lock
|
||||
pthread_mutex_lock(&mutexlock);
|
||||
}
|
||||
void CThreadLock::Unlock()
|
||||
{
|
||||
// unlock
|
||||
pthread_mutex_unlock(&mutexlock);
|
||||
}
|
||||
|
||||
class Player : public oboe::AudioStreamDataCallback
|
||||
{
|
||||
public:
|
||||
Player(int channels, int sample_rate)
|
||||
{
|
||||
this->channels = channels;
|
||||
oboe::AudioStreamBuilder builder;
|
||||
// The builder set methods can be chained for convenience.
|
||||
builder.setSharingMode(oboe::SharingMode::Exclusive)
|
||||
->setPerformanceMode(oboe::PerformanceMode::LowLatency)
|
||||
->setChannelCount(channels)
|
||||
->setSampleRate(sample_rate)
|
||||
->setFormat(oboe::AudioFormat::Float)
|
||||
->setDataCallback(this)
|
||||
->openManagedStream(outStream);
|
||||
// Typically, start the stream after querying some stream information, as well as some input from the user
|
||||
outStream->requestStart();
|
||||
}
|
||||
|
||||
~Player() {
|
||||
outStream->requestStop();
|
||||
}
|
||||
|
||||
oboe::DataCallbackResult onAudioReady(oboe::AudioStream *oboeStream, void *audioData, int32_t numFrames) override
|
||||
{
|
||||
float *floatData = (float *)audioData;
|
||||
int i = 0;
|
||||
mtx.Lock();
|
||||
auto n = channels * numFrames;
|
||||
for (; i < n && i < (int)buffer.size(); ++i, ++floatData)
|
||||
{
|
||||
*floatData = buffer.front();
|
||||
buffer.pop_front();
|
||||
}
|
||||
mtx.Unlock();
|
||||
for (; i < n; ++i, ++floatData)
|
||||
{
|
||||
*floatData = 0;
|
||||
}
|
||||
return oboe::DataCallbackResult::Continue;
|
||||
}
|
||||
|
||||
void push(const float *v, int n)
|
||||
{
|
||||
mtx.Lock();
|
||||
for (auto i = 0; i < n; ++i, ++v)
|
||||
buffer.push_back(*v);
|
||||
// in case memory overuse
|
||||
if (buffer.size() > 48 * 1024 * 120)
|
||||
buffer.clear();
|
||||
mtx.Unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
oboe::ManagedStream outStream;
|
||||
int channels;
|
||||
std::deque<float> buffer;
|
||||
CThreadLock mtx;
|
||||
};
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void *create_oboe_player(int channels, int sample_rate)
|
||||
{
|
||||
return new Player(channels, sample_rate);
|
||||
}
|
||||
|
||||
void push_oboe_data(void *player, const float* v, int n)
|
||||
{
|
||||
static_cast<Player *>(player)->push(v, n);
|
||||
}
|
||||
|
||||
void destroy_oboe_player(void *player)
|
||||
{
|
||||
delete static_cast<Player *>(player);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
use super::{CursorData, ResultType};
|
||||
use hbb_common::{allow_err, bail, log};
|
||||
use libc::{c_char, c_int, c_void};
|
||||
use std::io::prelude::*;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
sync::{
|
||||
@@ -31,7 +30,7 @@ extern "C" {
|
||||
#[link(name = "X11")]
|
||||
extern "C" {
|
||||
fn XOpenDisplay(display_name: *const c_char) -> *mut c_void;
|
||||
// fn XCloseDisplay(d: *mut c_void) -> c_int;
|
||||
// fn XCloseDisplay(d: *mut c_void) -> c_int;
|
||||
}
|
||||
|
||||
#[link(name = "Xfixes")]
|
||||
@@ -163,36 +162,8 @@ pub fn start_os_service() {
|
||||
if tmp != uid && !tmp.is_empty() {
|
||||
uid = tmp;
|
||||
log::info!("uid of seat0: {}", uid);
|
||||
let gdm = format!("/run/user/{}/gdm/Xauthority", uid);
|
||||
let mut auth = get_env("XAUTHORITY", &uid);
|
||||
if auth.is_empty() {
|
||||
auth = if std::path::Path::new(&gdm).exists() {
|
||||
gdm
|
||||
} else {
|
||||
let username = get_active_username();
|
||||
if username == "root" {
|
||||
format!("/{}/.Xauthority", username)
|
||||
} else {
|
||||
let tmp = format!("/home/{}/.Xauthority", username);
|
||||
if std::path::Path::new(&tmp).exists() {
|
||||
tmp
|
||||
} else {
|
||||
format!("/var/lib/{}/.Xauthority", username)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
let mut d = get_env("DISPLAY", &uid);
|
||||
if d.is_empty() {
|
||||
d = get_display();
|
||||
}
|
||||
if d.is_empty() {
|
||||
d = ":0".to_owned()
|
||||
}
|
||||
log::info!("DISPLAY: {}", d);
|
||||
log::info!("XAUTHORITY: {}", auth);
|
||||
std::env::set_var("XAUTHORITY", auth);
|
||||
std::env::set_var("DISPLAY", d);
|
||||
std::env::set_var("XAUTHORITY", format!("/run/user/{}/gdm/Xauthority", uid));
|
||||
std::env::set_var("DISPLAY", get_display());
|
||||
if let Some(ps) = server.as_mut() {
|
||||
allow_err!(ps.kill());
|
||||
std::thread::sleep(std::time::Duration::from_millis(30));
|
||||
@@ -274,27 +245,26 @@ fn get_cm() -> bool {
|
||||
|
||||
fn get_display() -> String {
|
||||
let user = get_active_username();
|
||||
log::debug!("w {}", &user);
|
||||
if let Ok(output) = std::process::Command::new("w").arg(&user).output() {
|
||||
for line in String::from_utf8_lossy(&output.stdout).lines() {
|
||||
log::debug!(" {}", line);
|
||||
let mut iter = line.split_whitespace();
|
||||
let b = iter.nth(2);
|
||||
if let Some(b) = b {
|
||||
if b.starts_with(":") {
|
||||
return b.to_owned();
|
||||
let a = iter.nth(1);
|
||||
let b = iter.next();
|
||||
if a == b {
|
||||
if let Some(b) = b {
|
||||
if b.starts_with(":") {
|
||||
return b.to_owned();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// above not work for gdm user
|
||||
log::debug!("ls -l /tmp/.X11-unix/");
|
||||
if let Ok(output) = std::process::Command::new("ls")
|
||||
.args(vec!["-l", "/tmp/.X11-unix/"])
|
||||
.output()
|
||||
{
|
||||
for line in String::from_utf8_lossy(&output.stdout).lines() {
|
||||
log::debug!(" {}", line);
|
||||
let mut iter = line.split_whitespace();
|
||||
if iter.nth(2) == Some(&user) {
|
||||
if let Some(x) = iter.last() {
|
||||
@@ -474,33 +444,3 @@ pub fn block_input(_v: bool) {
|
||||
pub fn is_installed() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn run_cmds(cmds: String) -> ResultType<Option<String>> {
|
||||
let mut tmp = std::env::temp_dir();
|
||||
tmp.push(format!(
|
||||
"{}_{}",
|
||||
hbb_common::config::APP_NAME,
|
||||
crate::get_time()
|
||||
));
|
||||
let mut file = std::fs::File::create(&tmp)?;
|
||||
file.write_all(cmds.as_bytes())?;
|
||||
file.sync_all()?;
|
||||
if let Ok(output) = std::process::Command::new("bash")
|
||||
.arg(tmp.to_str().unwrap_or(""))
|
||||
.output()
|
||||
{
|
||||
Ok(Some(String::from_utf8_lossy(&output.stdout).to_string()))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_env(name: &str, uid: &str) -> String {
|
||||
let cmd = format!("ps -u {} -o pid= | xargs -I__ cat /proc/__/environ 2>/dev/null | tr '\\0' '\\n' | grep -m1 '^{}=' | sed 's/{}=//g'", uid, name, name);
|
||||
log::debug!("Run: {}", &cmd);
|
||||
if let Ok(Some(x)) = run_cmds(cmd) {
|
||||
x.trim_end().to_string()
|
||||
} else {
|
||||
"".to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,17 +17,6 @@ pub mod linux;
|
||||
use hbb_common::{message_proto::CursorData, ResultType};
|
||||
const SERVICE_INTERVAL: u64 = 300;
|
||||
|
||||
pub fn is_xfce() -> bool {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
return std::env::var_os("XDG_CURRENT_DESKTOP") == Some(std::ffi::OsString::from("XFCE"));
|
||||
}
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -638,43 +638,21 @@ pub fn get_active_username() -> String {
|
||||
if name != "SYSTEM" {
|
||||
return name;
|
||||
}
|
||||
extern "C" {
|
||||
fn get_active_user(path: *mut u16, n: u32) -> u32;
|
||||
}
|
||||
let buff_size = 256;
|
||||
let mut buff: Vec<u16> = Vec::with_capacity(buff_size);
|
||||
buff.resize(buff_size, 0);
|
||||
let n = unsafe { get_active_user(buff.as_mut_ptr(), buff_size as _) };
|
||||
if n == 0 {
|
||||
return "".to_owned();
|
||||
}
|
||||
let sl = unsafe { std::slice::from_raw_parts(buff.as_ptr(), n as _) };
|
||||
String::from_utf16(sl).unwrap_or("??".to_owned()).trim_end_matches('\0').to_owned()
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn get_active_username() -> String {
|
||||
use std::os::windows::process::CommandExt;
|
||||
let name = crate::username();
|
||||
if name != "SYSTEM" {
|
||||
return name;
|
||||
}
|
||||
const CREATE_NO_WINDOW: u32 = 0x08000000;
|
||||
let mut cmd = std::process::Command::new("query");
|
||||
cmd.arg("user");
|
||||
cmd.creation_flags(CREATE_NO_WINDOW);
|
||||
if let Ok(output) = cmd.output() {
|
||||
if let Ok(output) = std::process::Command::new("query").arg("user").output() {
|
||||
for line in String::from_utf8_lossy(&output.stdout).lines() {
|
||||
if let Some(name) = line.split_whitespace().next() {
|
||||
if name.starts_with(">") {
|
||||
return name.replace(">", "");
|
||||
if line.contains("Active") {
|
||||
if let Some(name) = line.split_whitespace().next() {
|
||||
if name.starts_with(">") {
|
||||
return name.replace(">", "");
|
||||
} else {
|
||||
return name.to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return "".to_owned();
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn is_prelogin() -> bool {
|
||||
let username = get_active_username();
|
||||
|
||||
@@ -211,11 +211,7 @@ impl RendezvousMediator {
|
||||
Config::update_latency(&host, -1);
|
||||
old_latency = 0;
|
||||
if now.duration_since(last_dns_check).map(|d| d.as_millis() as i64).unwrap_or(0) > DNS_INTERVAL {
|
||||
if let Ok(_) = rz.dns_check() {
|
||||
// in some case of network reconnect (dial IP network),
|
||||
// old UDP socket not work any more after network recover
|
||||
socket = FramedSocket::new(Config::get_any_listen_addr()).await?;
|
||||
}
|
||||
allow_err!(rz.dns_check());
|
||||
last_dns_check = now;
|
||||
}
|
||||
} else if fails > MAX_FAILS1 {
|
||||
@@ -302,7 +298,6 @@ impl RendezvousMediator {
|
||||
relay_server = fla.relay_server;
|
||||
}
|
||||
msg_out.set_local_addr(LocalAddr {
|
||||
id: Config::get_id(),
|
||||
socket_addr: AddrMangle::encode(peer_addr),
|
||||
local_addr: AddrMangle::encode(local_addr),
|
||||
relay_server,
|
||||
@@ -310,7 +305,7 @@ impl RendezvousMediator {
|
||||
});
|
||||
let bytes = msg_out.write_to_bytes()?;
|
||||
socket.send_raw(bytes).await?;
|
||||
crate::accept_connection(server.clone(), socket, peer_addr, true).await;
|
||||
crate::accept_connection(server.clone(), socket, peer_addr, false).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -437,7 +437,7 @@ impl Connection {
|
||||
try_activate_screen();
|
||||
match super::video_service::get_displays() {
|
||||
Err(err) => {
|
||||
res.set_error(format!("X11 error: {}", err));
|
||||
res.set_error(err.to_string());
|
||||
}
|
||||
Ok((current, displays)) => {
|
||||
pi.displays = displays.into();
|
||||
|
||||
@@ -73,11 +73,7 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
rc_max_quantizer,
|
||||
speed,
|
||||
};
|
||||
let mut vpx;
|
||||
match Encoder::new(&cfg, 1) {
|
||||
Ok(x) => vpx = x,
|
||||
Err(err) => bail!("Failed to create encoder: {}", err),
|
||||
}
|
||||
let mut vpx = Encoder::new(&cfg, 1).with_context(|| "Failed to create encoder")?;
|
||||
|
||||
if *SWITCH.lock().unwrap() {
|
||||
log::debug!("Broadcasting display switch");
|
||||
|
||||
@@ -495,15 +495,10 @@ impl UI {
|
||||
let p = "xdg-open";
|
||||
allow_err!(std::process::Command::new(p).arg(url).spawn());
|
||||
}
|
||||
|
||||
fn is_xfce(&self) -> bool {
|
||||
crate::platform::is_xfce()
|
||||
}
|
||||
}
|
||||
|
||||
impl sciter::EventHandler for UI {
|
||||
sciter::dispatch_script_call! {
|
||||
fn is_xfce();
|
||||
fn get_id();
|
||||
fn get_password();
|
||||
fn update_password(String);
|
||||
|
||||
@@ -41,9 +41,9 @@ class Body: Reactor.Component
|
||||
<div />
|
||||
{c.is_file_transfer || c.port_forward ? "" : <div>Permissions</div>}
|
||||
{c.is_file_transfer || c.port_forward ? "" : <div .permissions>
|
||||
<div class={!c.keyboard ? "disabled" : ""} title="Allow using keyboard and mouse"><icon .keyboard /></div>
|
||||
<div class={!c.clipboard ? "disabled" : ""} title="Allow using clipboard"><icon .clipboard /></div>
|
||||
<div class={!c.audio ? "disabled" : ""} title="Allow hearing sound"><icon .audio /></div>
|
||||
<div class={!c.keyboard ? "disabled" : ""} title="Allow to use keyboard and mouse"><icon .keyboard /></div>
|
||||
<div class={!c.clipboard ? "disabled" : ""} title="Allow to use clipboard"><icon .clipboard /></div>
|
||||
<div class={!c.audio ? "disabled" : ""} title="Allow to hear sound"><icon .audio /></div>
|
||||
</div>}
|
||||
{c.port_forward ? <div>Port Forwarding: {c.port_forward}</div> : ""}
|
||||
<div style="size:*"/>
|
||||
@@ -246,11 +246,7 @@ function update() {
|
||||
|
||||
function bring_to_top(idx=-1) {
|
||||
if (view.windowState == View.WINDOW_HIDDEN || view.windowState == View.WINDOW_MINIMIZED) {
|
||||
if (is_linux) {
|
||||
view.focus = self;
|
||||
} else {
|
||||
view.windowState = View.WINDOW_SHOWN;
|
||||
}
|
||||
view.windowState = View.WINDOW_SHOWN;
|
||||
if (idx >= 0) body.cur = idx;
|
||||
} else {
|
||||
view.windowTopmost = true;
|
||||
|
||||
@@ -7,8 +7,6 @@ var is_osx = OS == "OSX";
|
||||
var is_win = OS == "Windows";
|
||||
var is_linux = OS == "Linux";
|
||||
var is_file_transfer;
|
||||
var is_xfce = false;
|
||||
try { is_xfce = handler.is_xfce(); } catch(e) {}
|
||||
|
||||
function hashCode(str) {
|
||||
var hash = 160 << 16 + 114 << 8 + 91;
|
||||
@@ -223,8 +221,8 @@ function msgbox(type, title, text, callback, height, width) {
|
||||
var dialog = {
|
||||
client: true,
|
||||
parameters: msgbox_params,
|
||||
width: width + (is_xfce ? 50 : 0),
|
||||
height: height + (is_xfce ? 50 : 0),
|
||||
width: width,
|
||||
height: height,
|
||||
};
|
||||
var html = handler.get_msgbox();
|
||||
if (html) dialog.html = html;
|
||||
|
||||
@@ -567,7 +567,7 @@ var create_dir_jobs = {}
|
||||
|
||||
function confirmDelete(path, is_remote) {
|
||||
handler.msgbox("custom-skip", "Confirm Delete", "<div .form> \
|
||||
<div>Are you sure you want to delete this file?</div> \
|
||||
<div>Are you sure you want to deelte this file?</div> \
|
||||
<div.ellipsis style=\"font-weight: bold;\">" + path + "</div> \
|
||||
</div>", function(res=null) {
|
||||
if (res) {
|
||||
@@ -588,7 +588,7 @@ handler.confirmDeleteFiles = function(id, i, name) {
|
||||
if (name) file_path += handler.get_path_sep(job.is_remote) + name;
|
||||
handler.msgbox("custom-skip", "Confirm Delete", "<div .form> \
|
||||
<div>Deleting #" + (i + 1) + " of " + n + " files.</div> \
|
||||
<div>Are you sure you want to delete this file?</div> \
|
||||
<div>Are you sure you want to deelte this file?</div> \
|
||||
<div.ellipsis style=\"font-weight: bold;\" .text>" + name + "</div> \
|
||||
<div><button|checkbox(remember) {ts}>Do this for all conflicts</button></div> \
|
||||
</div>", function(res=null) {
|
||||
|
||||
@@ -15,28 +15,10 @@ var svg_insecure = <svg viewBox="0 0 347.97 347.97"><path d="M317.469 61.615c-59
|
||||
var svg_insecure_relay = <svg viewBox="0 0 347.97 347.97"><path d="M317.469 61.615c-59.442 0-104.976-16.082-143.489-51.539-38.504 35.457-84.04 51.539-143.479 51.539 0 92.337-20.177 224.612 143.479 278.324 163.661-53.717 143.489-185.992 143.489-278.324z" fill="none" stroke="red" stroke-width="14.827"/><g fill="red"><path d="M231.442 247.498l-7.754-10.205c-17.268 12.441-38.391 17.705-59.478 14.822-21.087-2.883-39.613-13.569-52.166-30.088-25.916-34.101-17.997-82.738 17.65-108.42 32.871-23.685 78.02-19.704 105.172 7.802l-32.052 7.987 3.082 12.369 48.722-12.142-11.712-46.998-12.822 3.196 4.496 18.039c-31.933-24.008-78.103-25.342-112.642-.458-31.361 22.596-44.3 60.436-35.754 94.723 2.77 11.115 7.801 21.862 15.192 31.588 30.19 39.727 88.538 47.705 130.066 17.785z"/></g></svg>;
|
||||
var svg_secure_relay = <svg viewBox="0 0 347.97 347.97"><path d="M317.469 61.615c-59.442 0-104.976-16.082-143.489-51.539-38.504 35.457-84.04 51.539-143.479 51.539 0 92.337-20.177 224.612 143.479 278.324 163.661-53.717 143.489-185.992 143.489-278.324z" fill="#3f7d46" stroke="#3f7d46" stroke-width="14.827"/><g fill="red"><path d="M231.442 247.498l-7.754-10.205c-17.268 12.441-38.391 17.705-59.478 14.822-21.087-2.883-39.613-13.569-52.166-30.088-25.916-34.101-17.997-82.738 17.65-108.42 32.871-23.685 78.02-19.704 105.172 7.802l-32.052 7.987 3.082 12.369 48.722-12.142-11.712-46.998-12.822 3.196 4.496 18.039c-31.933-24.008-78.103-25.342-112.642-.458-31.361 22.596-44.3 60.436-35.754 94.723 2.77 11.115 7.801 21.862 15.192 31.588 30.19 39.727 88.538 47.705 130.066 17.785z" fill="#fff"/></g></svg>;
|
||||
|
||||
var cur_window_state = view.windowState;
|
||||
function check_state_change() {
|
||||
if (view.windowState != cur_window_state) {
|
||||
stateChanged();
|
||||
}
|
||||
self.timer(30ms, check_state_change);
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
check_state_change();
|
||||
} else {
|
||||
view << event statechange {
|
||||
stateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
function stateChanged() {
|
||||
stdout.println('state changed from ' + cur_window_state + ' -> ' + view.windowState);
|
||||
cur_window_state = view.windowState;
|
||||
view << event statechange {
|
||||
adjustBorder();
|
||||
adaptDisplay();
|
||||
if (!is_linux) view.focus = handler; // this cause windows always topmost on linux
|
||||
view.focus = handler;
|
||||
var fs = view.windowState == View.WINDOW_FULL_SCREEN;
|
||||
var el = $(#fullscreen);
|
||||
if (el) el.attributes.toggleClass("active", fs);
|
||||
@@ -44,11 +26,6 @@ function stateChanged() {
|
||||
if (el) {
|
||||
el.state.disabled = fs;
|
||||
}
|
||||
if (fs) {
|
||||
$(header).style.set {
|
||||
display: "none",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
var header;
|
||||
@@ -79,7 +56,7 @@ class Header: Reactor.Component {
|
||||
var title = handler.get_id();
|
||||
if (pi.hostname) title += "(" + pi.username + "@" + pi.hostname + ")";
|
||||
if ((pi.displays || []).length == 0) {
|
||||
return <div .ellipsis style="size:*;text-align:center;margin:*;">{title}</div>;
|
||||
return <div .ellipsis style={is_osx || is_win ? "size:*;text-align:center;margin:*;" : ""}>{title}</div>;
|
||||
}
|
||||
var screens = pi.displays.map(function(d, i) {
|
||||
return <div #screen class={pi.current_display == i ? "current" : ""}>
|
||||
@@ -91,7 +68,7 @@ class Header: Reactor.Component {
|
||||
if (is_osx) style += "margin: *";
|
||||
self.timer(1ms, toggleMenuState);
|
||||
return <div style={style}>
|
||||
{is_osx || is_xfce ? "" : <span #fullscreen>{svg_fullscreen}</span>}
|
||||
{is_osx ? "" : <span #fullscreen>{svg_fullscreen}</span>}
|
||||
<div #screens>
|
||||
<span #secure title={title_conn}>{icon_conn}</span>
|
||||
<div .remote-id>{handler.get_id()}</div>
|
||||
@@ -133,7 +110,7 @@ class Header: Reactor.Component {
|
||||
return <popup>
|
||||
<menu.context #action-options>
|
||||
<li #transfer-file>Transfer File</li>
|
||||
<li #tunnel>TCP Tunneling</li>
|
||||
<li #tunnel>IP Tunneling</li>
|
||||
{keyboard_enabled && (pi.platform == "Linux" || pi.sas_enabled) ? <li #ctrl-alt-del>Insert Ctrl + Alt + Del</li> : ""}
|
||||
{keyboard_enabled ? <li #lock-screen>Insert Lock</li> : ""}
|
||||
{false && pi.platform == "Windows" ? <li #block-input>Block user input </li> : ""}
|
||||
@@ -187,7 +164,6 @@ class Header: Reactor.Component {
|
||||
view.windowState = View.WINDOW_SHOWN;
|
||||
}
|
||||
view.windowState = View.WINDOW_FULL_SCREEN;
|
||||
if (is_linux) { self.timer(150ms, function() { view.windowState = View.WINDOW_FULL_SCREEN; }); }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -249,7 +249,7 @@ class MyIdMenu: Reactor.Component {
|
||||
}
|
||||
if (value == old_value) return;
|
||||
configOptions["whitelist"] = value.replace("\n", ",");
|
||||
stdout.println("whitelist updated");
|
||||
stdin.println("whitelist updated");
|
||||
handler.set_options(configOptions);
|
||||
}, 300);
|
||||
} else if (me.id == "custom-server") {
|
||||
|
||||
@@ -21,7 +21,7 @@ class PortForward: Reactor.Component {
|
||||
});
|
||||
return <div #file-transfer><section>
|
||||
{pfs.length ? <div style="background: green; color: white; text-align: center; padding: 0.5em;">
|
||||
<span style="font-size: 1.2em">Listening ...</span><br/>
|
||||
<span style="font-size: 1.2em">Listenning ...</span><br/>
|
||||
<span style="font-size: 0.8em; color: #ddd">Don't close this window while your are using tunnel</span>
|
||||
</div> : ""}
|
||||
<table #port-forward>
|
||||
|
||||
@@ -139,7 +139,6 @@ impl sciter::EventHandler for Handler {
|
||||
}
|
||||
|
||||
sciter::dispatch_script_call! {
|
||||
fn is_xfce();
|
||||
fn get_id();
|
||||
fn get_default_pi();
|
||||
fn get_option(String);
|
||||
@@ -280,10 +279,6 @@ impl Handler {
|
||||
self.lc.read().unwrap().remember
|
||||
}
|
||||
|
||||
fn is_xfce(&self) -> bool {
|
||||
crate::platform::is_xfce()
|
||||
}
|
||||
|
||||
fn save_size(&mut self, x: i32, y: i32, w: i32, h: i32) {
|
||||
let size = (x, y, w, h);
|
||||
let mut config = self.load_config();
|
||||
@@ -1587,7 +1582,7 @@ impl Interface for Handler {
|
||||
pi_sciter.set_item("sas_enabled", pi.sas_enabled);
|
||||
if self.is_file_transfer() {
|
||||
if pi.username.is_empty() {
|
||||
self.on_error("No active user logged on, please connect and logon first.");
|
||||
self.on_error("No active console user logged on, please connect and logon first.");
|
||||
return;
|
||||
}
|
||||
} else if !self.is_port_forward() {
|
||||
|
||||
@@ -10,7 +10,6 @@ var display_scale = 1;
|
||||
var keyboard_enabled = true; // server side
|
||||
var clipboard_enabled = true; // server side
|
||||
var audio_enabled = true; // server side
|
||||
var scroll_body = $(body);
|
||||
|
||||
handler.setDisplay = function(x, y, w, h) {
|
||||
display_width = w;
|
||||
@@ -167,7 +166,7 @@ function handler.onMouse(evt)
|
||||
{
|
||||
if (is_file_transfer || is_port_forward) return false;
|
||||
if (view.windowState == View.WINDOW_FULL_SCREEN && !dragging) {
|
||||
if (evt.y - scroll_body.scroll(#top) < 10) {
|
||||
if (evt.y < 10) {
|
||||
if (!wait_window_toolbar) {
|
||||
wait_window_toolbar = true;
|
||||
self.timer(300ms, function() {
|
||||
@@ -393,25 +392,23 @@ handler.adaptSize = function() {
|
||||
size_adapted = true;
|
||||
var (sx, sy, sw, sh) = view.screenBox(#workarea, #rectw);
|
||||
var (fx, fy, fw, fh) = view.screenBox(#frame, #rectw);
|
||||
if (is_osx) workarea_offset = sy;
|
||||
workarea_offset = sy;
|
||||
var r = handler.get_size();
|
||||
if (r[2] > 0) {
|
||||
if (r[2] >= fw && r[3] >= fh && !is_linux) {
|
||||
if (r[2] >= fw && r[3] >= fh) {
|
||||
view.windowState = View.WINDOW_FULL_SCREEN;
|
||||
stdout.println("Initialize to full screen");
|
||||
} else if (r[2] >= sw && r[3] >= sh) {
|
||||
view.windowState = View.WINDOW_MAXIMIZED;
|
||||
stdout.println("Initialize to full screen");
|
||||
} else {
|
||||
view.move(r[0], r[1], r[2], r[3]);
|
||||
}
|
||||
} else {
|
||||
var w = handler.box(#width, #border)
|
||||
var h = handler.box(#height, #border)
|
||||
if (w >= sw || h >= sh) {
|
||||
if (sw == w) {
|
||||
view.windowState = View.WINDOW_MAXIMIZED;
|
||||
return;
|
||||
}
|
||||
var h = $(header).box(#height, #border);
|
||||
// extra for border
|
||||
var extra = 2;
|
||||
centerize(w + extra, handler.box(#height, #border) + h + extra);
|
||||
|
||||
@@ -363,21 +363,4 @@ extern "C"
|
||||
{
|
||||
SHAddToRecentDocs(SHARD_PATHW, path);
|
||||
}
|
||||
|
||||
uint32_t get_active_user(PWSTR bufin, uint32_t nin)
|
||||
{
|
||||
uint32_t nout = 0;
|
||||
auto id = WTSGetActiveConsoleSessionId();
|
||||
PWSTR buf = NULL;
|
||||
DWORD n = 0;
|
||||
if (WTSQuerySessionInformationW(NULL, id, WTSUserName, &buf, &n))
|
||||
{
|
||||
if (buf) {
|
||||
nout = min(nin, n);
|
||||
memcpy(bufin, buf, nout);
|
||||
WTSFreeMemory(buf);
|
||||
}
|
||||
}
|
||||
return nout;
|
||||
}
|
||||
} // end of extern "C"
|
||||
} // end of extern "C"
|
||||
Reference in New Issue
Block a user