commit
647721a37e
@ -158,7 +158,7 @@ enum ControlKey {
|
|||||||
Divide = 70;
|
Divide = 70;
|
||||||
Equals = 71;
|
Equals = 71;
|
||||||
NumpadEnter = 72;
|
NumpadEnter = 72;
|
||||||
RShift= 73;
|
RShift = 73;
|
||||||
RControl = 74;
|
RControl = 74;
|
||||||
RAlt = 75;
|
RAlt = 75;
|
||||||
CtrlAltDel = 100;
|
CtrlAltDel = 100;
|
||||||
@ -173,8 +173,7 @@ message KeyEvent {
|
|||||||
uint32 chr = 4;
|
uint32 chr = 4;
|
||||||
uint32 unicode = 5;
|
uint32 unicode = 5;
|
||||||
string seq = 6;
|
string seq = 6;
|
||||||
}
|
} repeated ControlKey modifiers = 8;
|
||||||
repeated ControlKey modifiers = 8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message CursorData {
|
message CursorData {
|
||||||
@ -348,6 +347,11 @@ message OptionMessage {
|
|||||||
BoolOption disable_clipboard = 8;
|
BoolOption disable_clipboard = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message OptionResponse {
|
||||||
|
OptionMessage opt = 1;
|
||||||
|
string error = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message TestDelay {
|
message TestDelay {
|
||||||
int64 time = 1;
|
int64 time = 1;
|
||||||
bool from_client = 2;
|
bool from_client = 2;
|
||||||
@ -358,9 +362,7 @@ message PublicKey {
|
|||||||
bytes symmetric_value = 2;
|
bytes symmetric_value = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SignedId {
|
message SignedId { bytes id = 1; }
|
||||||
bytes id = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message AudioFormat {
|
message AudioFormat {
|
||||||
uint32 sample_rate = 1;
|
uint32 sample_rate = 1;
|
||||||
@ -378,6 +380,7 @@ message Misc {
|
|||||||
AudioFormat audio_format = 8;
|
AudioFormat audio_format = 8;
|
||||||
string close_reason = 9;
|
string close_reason = 9;
|
||||||
bool refresh_video = 10;
|
bool refresh_video = 10;
|
||||||
|
OptionResponse option_response = 11;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -826,7 +826,7 @@ impl LoginConfigHandler {
|
|||||||
msg.lock_after_session_end = BoolOption::Yes.into();
|
msg.lock_after_session_end = BoolOption::Yes.into();
|
||||||
n += 1;
|
n += 1;
|
||||||
}
|
}
|
||||||
if self.get_toggle_option("privacy_mode") {
|
if self.get_toggle_option("privacy-mode") {
|
||||||
msg.privacy_mode = BoolOption::Yes.into();
|
msg.privacy_mode = BoolOption::Yes.into();
|
||||||
n += 1;
|
n += 1;
|
||||||
}
|
}
|
||||||
|
@ -600,12 +600,13 @@ pub fn lock_screen() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle_privacy_mode(_v: bool) {
|
pub fn toggle_blank_screen(_v: bool) {
|
||||||
// https://unix.stackexchange.com/questions/17170/disable-keyboard-mouse-input-on-unix-under-x
|
// https://unix.stackexchange.com/questions/17170/disable-keyboard-mouse-input-on-unix-under-x
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn block_input(_v: bool) {
|
pub fn block_input(_v: bool) -> bool {
|
||||||
//
|
//
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_installed() -> bool {
|
pub fn is_installed() -> bool {
|
||||||
|
@ -398,12 +398,13 @@ pub fn start_os_service() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle_privacy_mode(_v: bool) {
|
pub fn toggle_blank_screen(_v: bool) {
|
||||||
// https://unix.stackexchange.com/questions/17115/disable-keyboard-mouse-temporarily
|
// https://unix.stackexchange.com/questions/17115/disable-keyboard-mouse-temporarily
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn block_input(_v: bool) {
|
pub fn block_input(_v: bool) -> bool {
|
||||||
//
|
//
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_installed() -> bool {
|
pub fn is_installed() -> bool {
|
||||||
|
@ -1013,19 +1013,16 @@ fn run_cmds(cmds: String, show: bool) -> ResultType<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle_privacy_mode(v: bool) {
|
pub fn toggle_blank_screen(v: bool) {
|
||||||
let v = if v { TRUE } else { FALSE };
|
let v = if v { TRUE } else { FALSE };
|
||||||
unsafe {
|
unsafe {
|
||||||
blank_screen(v);
|
blank_screen(v);
|
||||||
BlockInput(v);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn block_input(v: bool) {
|
pub fn block_input(v: bool) -> bool {
|
||||||
let v = if v { TRUE } else { FALSE };
|
let v = if v { TRUE } else { FALSE };
|
||||||
unsafe {
|
unsafe { BlockInput(v) == TRUE }
|
||||||
BlockInput(v);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_recent_document(path: &str) {
|
pub fn add_recent_document(path: &str) {
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
use super::input_service::*;
|
use super::{input_service::*, *};
|
||||||
use super::*;
|
use crate::{common::update_clipboard, ipc};
|
||||||
use crate::common::update_clipboard;
|
|
||||||
use crate::ipc;
|
|
||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
config::Config,
|
config::Config,
|
||||||
fs,
|
fs,
|
||||||
futures::{SinkExt, StreamExt},
|
futures::{SinkExt, StreamExt},
|
||||||
sleep, timeout,
|
protobuf, sleep, timeout,
|
||||||
tokio::{
|
tokio::{
|
||||||
net::TcpStream,
|
net::TcpStream,
|
||||||
sync::mpsc,
|
sync::mpsc,
|
||||||
@ -15,6 +13,7 @@ use hbb_common::{
|
|||||||
tokio_util::codec::{BytesCodec, Framed},
|
tokio_util::codec::{BytesCodec, Framed},
|
||||||
};
|
};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
|
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
|
||||||
|
|
||||||
pub type Sender = mpsc::UnboundedSender<(Instant, Arc<Message>)>;
|
pub type Sender = mpsc::UnboundedSender<(Instant, Arc<Message>)>;
|
||||||
|
|
||||||
@ -29,6 +28,15 @@ pub struct ConnInner {
|
|||||||
tx_video: Option<Sender>,
|
tx_video: Option<Sender>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum MessageInput {
|
||||||
|
InputFunc(Box<dyn Send + FnMut()>),
|
||||||
|
BlockOn,
|
||||||
|
BlockOff,
|
||||||
|
PrivacyOn,
|
||||||
|
PrivacyOff,
|
||||||
|
Exit,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Connection {
|
pub struct Connection {
|
||||||
inner: ConnInner,
|
inner: ConnInner,
|
||||||
stream: super::Stream,
|
stream: super::Stream,
|
||||||
@ -52,6 +60,8 @@ pub struct Connection {
|
|||||||
ip: String,
|
ip: String,
|
||||||
disable_clipboard: bool, // by peer
|
disable_clipboard: bool, // by peer
|
||||||
disable_audio: bool, // by peer
|
disable_audio: bool, // by peer
|
||||||
|
tx_input: SyncSender<MessageInput>, // handle input messages
|
||||||
|
rx_input_res: Receiver<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Subscriber for ConnInner {
|
impl Subscriber for ConnInner {
|
||||||
@ -100,6 +110,9 @@ impl Connection {
|
|||||||
let (tx_to_cm, rx_to_cm) = mpsc::unbounded_channel::<ipc::Data>();
|
let (tx_to_cm, rx_to_cm) = mpsc::unbounded_channel::<ipc::Data>();
|
||||||
let (tx, mut rx) = mpsc::unbounded_channel::<(Instant, Arc<Message>)>();
|
let (tx, mut rx) = mpsc::unbounded_channel::<(Instant, Arc<Message>)>();
|
||||||
let (tx_video, mut rx_video) = mpsc::unbounded_channel::<(Instant, Arc<Message>)>();
|
let (tx_video, mut rx_video) = mpsc::unbounded_channel::<(Instant, Arc<Message>)>();
|
||||||
|
let (tx_input, rx_input) = sync_channel(1);
|
||||||
|
let (tx_input_res, rx_input_res) = sync_channel(1);
|
||||||
|
|
||||||
let mut conn = Self {
|
let mut conn = Self {
|
||||||
inner: ConnInner {
|
inner: ConnInner {
|
||||||
id,
|
id,
|
||||||
@ -127,6 +140,8 @@ impl Connection {
|
|||||||
ip: "".to_owned(),
|
ip: "".to_owned(),
|
||||||
disable_audio: false,
|
disable_audio: false,
|
||||||
disable_clipboard: false,
|
disable_clipboard: false,
|
||||||
|
tx_input,
|
||||||
|
rx_input_res,
|
||||||
};
|
};
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
if let Err(err) = start_ipc(rx_to_cm, tx_from_cm).await {
|
if let Err(err) = start_ipc(rx_to_cm, tx_from_cm).await {
|
||||||
@ -157,6 +172,8 @@ impl Connection {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let handler_input = std::thread::spawn(move || Self::handle_input(rx_input, tx_input_res));
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
biased; // video has higher priority
|
biased; // video has higher priority
|
||||||
@ -297,6 +314,16 @@ impl Connection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conn.tx_input.send(MessageInput::Exit).unwrap();
|
||||||
|
if let Err(e) = handler_input.join() {
|
||||||
|
log::error!("Failed to join input thread, {:?}", e);
|
||||||
|
} else {
|
||||||
|
log::info!("Blank thread exited");
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = crate::platform::block_input(false);
|
||||||
|
crate::platform::toggle_blank_screen(false);
|
||||||
|
|
||||||
video_service::notify_video_frame_feched(id, None);
|
video_service::notify_video_frame_feched(id, None);
|
||||||
super::video_service::update_test_latency(id, 0);
|
super::video_service::update_test_latency(id, 0);
|
||||||
super::video_service::update_image_quality(id, None);
|
super::video_service::update_image_quality(id, None);
|
||||||
@ -305,6 +332,94 @@ impl Connection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_input(receiver: Receiver<MessageInput>, tx_input_res: SyncSender<bool>) {
|
||||||
|
let mut block_input_mode = false;
|
||||||
|
let (tx_blank, rx_blank) = sync_channel(1);
|
||||||
|
|
||||||
|
let handler_blank = std::thread::spawn(|| Self::handle_blank(rx_blank));
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match receiver.recv_timeout(std::time::Duration::from_millis(500)) {
|
||||||
|
Ok(v) => match v {
|
||||||
|
MessageInput::InputFunc(mut f) => {
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
MessageInput::BlockOn => {
|
||||||
|
if crate::platform::block_input(true) {
|
||||||
|
block_input_mode = true;
|
||||||
|
tx_input_res.send(true).unwrap();
|
||||||
|
} else {
|
||||||
|
tx_input_res.send(false).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MessageInput::BlockOff => {
|
||||||
|
if crate::platform::block_input(false) {
|
||||||
|
block_input_mode = false;
|
||||||
|
tx_input_res.send(true).unwrap();
|
||||||
|
} else {
|
||||||
|
tx_input_res.send(false).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MessageInput::PrivacyOn => {
|
||||||
|
if crate::platform::block_input(true) {
|
||||||
|
block_input_mode = true;
|
||||||
|
tx_input_res.send(true).unwrap();
|
||||||
|
} else {
|
||||||
|
tx_input_res.send(false).unwrap();
|
||||||
|
}
|
||||||
|
tx_blank.send(MessageInput::PrivacyOn).unwrap();
|
||||||
|
}
|
||||||
|
MessageInput::PrivacyOff => {
|
||||||
|
if crate::platform::block_input(false) {
|
||||||
|
block_input_mode = false;
|
||||||
|
tx_input_res.send(true).unwrap();
|
||||||
|
} else {
|
||||||
|
tx_input_res.send(false).unwrap();
|
||||||
|
}
|
||||||
|
tx_blank.send(MessageInput::PrivacyOff).unwrap();
|
||||||
|
}
|
||||||
|
MessageInput::Exit => break,
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
if block_input_mode {
|
||||||
|
let _ = crate::platform::block_input(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tx_blank.send(MessageInput::Exit).unwrap();
|
||||||
|
if let Err(_) = handler_blank.join() {
|
||||||
|
log::error!("Failed to join blank thread handler");
|
||||||
|
} else {
|
||||||
|
log::info!("Blank thread exited");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_blank(receiver: Receiver<MessageInput>) {
|
||||||
|
let mut last_privacy = false;
|
||||||
|
loop {
|
||||||
|
match receiver.recv_timeout(std::time::Duration::from_millis(500)) {
|
||||||
|
Ok(v) => match v {
|
||||||
|
MessageInput::PrivacyOn => {
|
||||||
|
crate::platform::toggle_blank_screen(true);
|
||||||
|
last_privacy = true;
|
||||||
|
}
|
||||||
|
MessageInput::PrivacyOff => {
|
||||||
|
crate::platform::toggle_blank_screen(false);
|
||||||
|
last_privacy = false;
|
||||||
|
}
|
||||||
|
_ => break,
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
if last_privacy {
|
||||||
|
crate::platform::toggle_blank_screen(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn try_port_forward_loop(
|
async fn try_port_forward_loop(
|
||||||
&mut self,
|
&mut self,
|
||||||
rx_from_cm: &mut mpsc::UnboundedReceiver<Data>,
|
rx_from_cm: &mut mpsc::UnboundedReceiver<Data>,
|
||||||
@ -536,10 +651,22 @@ impl Connection {
|
|||||||
self.send(msg_out).await;
|
self.send(msg_out).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn send_option_error<T: std::string::ToString>(&mut self, err: T, opt: OptionMessage) {
|
||||||
|
let mut msg_out = Message::new();
|
||||||
|
let mut res = OptionResponse::new();
|
||||||
|
let mut misc = Misc::new();
|
||||||
|
res.opt = protobuf::MessageField::some(opt);
|
||||||
|
res.error = err.to_string();
|
||||||
|
|
||||||
|
misc.set_option_response(res);
|
||||||
|
msg_out.set_misc(misc);
|
||||||
|
self.send(msg_out).await;
|
||||||
|
}
|
||||||
|
|
||||||
async fn on_message(&mut self, msg: Message) -> bool {
|
async fn on_message(&mut self, msg: Message) -> bool {
|
||||||
if let Some(message::Union::login_request(lr)) = msg.union {
|
if let Some(message::Union::login_request(lr)) = msg.union {
|
||||||
if let Some(o) = lr.option.as_ref() {
|
if let Some(o) = lr.option.as_ref() {
|
||||||
self.update_option(o);
|
self.update_option(o).await;
|
||||||
}
|
}
|
||||||
if self.authorized {
|
if self.authorized {
|
||||||
return true;
|
return true;
|
||||||
@ -654,7 +781,12 @@ impl Connection {
|
|||||||
match msg.union {
|
match msg.union {
|
||||||
Some(message::Union::mouse_event(me)) => {
|
Some(message::Union::mouse_event(me)) => {
|
||||||
if self.keyboard {
|
if self.keyboard {
|
||||||
handle_mouse(&me, self.inner.id());
|
let conn_id = self.inner.id();
|
||||||
|
self.tx_input
|
||||||
|
.send(MessageInput::InputFunc(Box::new(move || {
|
||||||
|
handle_mouse(&me, conn_id)
|
||||||
|
})))
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(message::Union::key_event(mut me)) => {
|
Some(message::Union::key_event(mut me)) => {
|
||||||
@ -669,17 +801,31 @@ impl Connection {
|
|||||||
};
|
};
|
||||||
if is_press {
|
if is_press {
|
||||||
if let Some(key_event::Union::unicode(_)) = me.union {
|
if let Some(key_event::Union::unicode(_)) = me.union {
|
||||||
handle_key(&me);
|
self.tx_input
|
||||||
|
.send(MessageInput::InputFunc(Box::new(move || {
|
||||||
|
handle_key(&me)
|
||||||
|
})))
|
||||||
|
.unwrap();
|
||||||
} else if let Some(key_event::Union::seq(_)) = me.union {
|
} else if let Some(key_event::Union::seq(_)) = me.union {
|
||||||
handle_key(&me);
|
self.tx_input
|
||||||
|
.send(MessageInput::InputFunc(Box::new(move || {
|
||||||
|
handle_key(&me)
|
||||||
|
})))
|
||||||
|
.unwrap();
|
||||||
} else {
|
} else {
|
||||||
|
self.tx_input
|
||||||
|
.send(MessageInput::InputFunc(Box::new(move || {
|
||||||
me.down = true;
|
me.down = true;
|
||||||
handle_key(&me);
|
handle_key(&me);
|
||||||
me.down = false;
|
me.down = false;
|
||||||
handle_key(&me);
|
handle_key(&me);
|
||||||
|
})))
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
handle_key(&me);
|
self.tx_input
|
||||||
|
.send(MessageInput::InputFunc(Box::new(move || handle_key(&me))))
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -782,7 +928,7 @@ impl Connection {
|
|||||||
self.send_to_cm(ipc::Data::ChatMessage { text: c.text });
|
self.send_to_cm(ipc::Data::ChatMessage { text: c.text });
|
||||||
}
|
}
|
||||||
Some(misc::Union::option(o)) => {
|
Some(misc::Union::option(o)) => {
|
||||||
self.update_option(&o);
|
self.update_option(&o).await;
|
||||||
}
|
}
|
||||||
Some(misc::Union::refresh_video(r)) => {
|
Some(misc::Union::refresh_video(r)) => {
|
||||||
if r {
|
if r {
|
||||||
@ -797,7 +943,7 @@ impl Connection {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_option(&mut self, o: &OptionMessage) {
|
async fn update_option(&mut self, o: &OptionMessage) {
|
||||||
log::info!("Option update: {:?}", o);
|
log::info!("Option update: {:?}", o);
|
||||||
if let Ok(q) = o.image_quality.enum_value() {
|
if let Ok(q) = o.image_quality.enum_value() {
|
||||||
self.image_quality = q.value();
|
self.image_quality = q.value();
|
||||||
@ -855,17 +1001,54 @@ impl Connection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Ok(q) = o.privacy_mode.enum_value() {
|
if let Ok(q) = o.privacy_mode.enum_value() {
|
||||||
if q != BoolOption::NotSet {
|
if self.keyboard {
|
||||||
self.privacy_mode = q == BoolOption::Yes;
|
match q {
|
||||||
if self.privacy_mode && self.keyboard {
|
BoolOption::Yes => {
|
||||||
crate::platform::toggle_privacy_mode(true);
|
self.privacy_mode = true;
|
||||||
|
self.tx_input.send(MessageInput::PrivacyOn).unwrap();
|
||||||
|
if self.rx_input_res.recv().unwrap() {
|
||||||
|
log::info!("Privacy mode on");
|
||||||
|
} else {
|
||||||
|
log::error!("Failed to trun on privacy mode");
|
||||||
|
self.send_option_error("Failed to turn on privacy mode", o.clone())
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BoolOption::No => {
|
||||||
|
self.privacy_mode = false;
|
||||||
|
self.tx_input.send(MessageInput::PrivacyOff).unwrap();
|
||||||
|
if self.rx_input_res.recv().unwrap() {
|
||||||
|
log::info!("Privacy mode off");
|
||||||
|
} else {
|
||||||
|
log::warn!("Failed to trun off privacy mode")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.keyboard {
|
if self.keyboard {
|
||||||
if let Ok(q) = o.block_input.enum_value() {
|
if let Ok(q) = o.block_input.enum_value() {
|
||||||
if q != BoolOption::NotSet {
|
match q {
|
||||||
crate::platform::block_input(q == BoolOption::Yes);
|
BoolOption::Yes => {
|
||||||
|
self.tx_input.send(MessageInput::BlockOn).unwrap();
|
||||||
|
if self.rx_input_res.recv().unwrap() {
|
||||||
|
log::info!("Block input mode on");
|
||||||
|
} else {
|
||||||
|
log::error!("Failed to trun on block input mode");
|
||||||
|
self.send_option_error("Failed to turn on block input mode", o.clone())
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BoolOption::No => {
|
||||||
|
self.tx_input.send(MessageInput::BlockOff).unwrap();
|
||||||
|
if self.rx_input_res.recv().unwrap() {
|
||||||
|
log::info!("Block input mode off");
|
||||||
|
} else {
|
||||||
|
log::error!("Failed to trun off block input mode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -880,9 +1063,6 @@ impl Connection {
|
|||||||
crate::platform::lock_screen();
|
crate::platform::lock_screen();
|
||||||
super::video_service::switch_to_primary();
|
super::video_service::switch_to_primary();
|
||||||
}
|
}
|
||||||
if self.privacy_mode {
|
|
||||||
crate::platform::toggle_privacy_mode(false);
|
|
||||||
}
|
|
||||||
self.port_forward_socket.take();
|
self.port_forward_socket.take();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +130,8 @@ class Header: Reactor.Component {
|
|||||||
{audio_enabled ? <li #disable-audio .toggle-option><span>{svg_checkmark}</span>{translate('Mute')}</li> : ""}
|
{audio_enabled ? <li #disable-audio .toggle-option><span>{svg_checkmark}</span>{translate('Mute')}</li> : ""}
|
||||||
{keyboard_enabled && clipboard_enabled ? <li #disable-clipboard .toggle-option><span>{svg_checkmark}</span>{translate('Disable clipboard')}</li> : ""}
|
{keyboard_enabled && clipboard_enabled ? <li #disable-clipboard .toggle-option><span>{svg_checkmark}</span>{translate('Disable clipboard')}</li> : ""}
|
||||||
{keyboard_enabled ? <li #lock-after-session-end .toggle-option><span>{svg_checkmark}</span>{translate('Lock after session end')}</li> : ""}
|
{keyboard_enabled ? <li #lock-after-session-end .toggle-option><span>{svg_checkmark}</span>{translate('Lock after session end')}</li> : ""}
|
||||||
{false && pi.platform == "Windows" ? <li #privacy-mode .toggle-option><span>{svg_checkmark}</span>{translate('Privacy mode')}</li> : ""}
|
{pi.platform == "Windows" ? <li #block-input>Block user input </li> : ""}
|
||||||
|
{pi.platform == "Windows" ? <li #privacy-mode .toggle-option><span>{svg_checkmark}</span>{translate('Privacy mode')}</li> : ""}
|
||||||
</menu>
|
</menu>
|
||||||
</popup>;
|
</popup>;
|
||||||
}
|
}
|
||||||
|
@ -1727,6 +1727,9 @@ impl Remote {
|
|||||||
self.handler.msgbox("error", "Connection Error", &c);
|
self.handler.msgbox("error", "Connection Error", &c);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Some(misc::Union::option_response(resp)) => {
|
||||||
|
self.handler.msgbox("warn", "Option Error", &resp.error);
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
Some(message::Union::test_delay(t)) => {
|
Some(message::Union::test_delay(t)) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user