mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
Merge pull request #1962 from Kingtous/feat/linux_tray
feat: linux tray
This commit is contained in:
105
src/tray.rs
105
src/tray.rs
@@ -1,8 +1,14 @@
|
||||
use hbb_common::log::{debug, error, info};
|
||||
#[cfg(target_os = "linux")]
|
||||
use libappindicator::AppIndicator;
|
||||
use std::env::temp_dir;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, Mutex},
|
||||
sync::{Arc, Mutex, RwLock},
|
||||
};
|
||||
#[cfg(target_os = "windows")]
|
||||
use trayicon::{MenuBuilder, TrayIconBuilder};
|
||||
#[cfg(target_os = "windows")]
|
||||
use winit::{
|
||||
event::Event,
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
@@ -15,6 +21,7 @@ enum Events {
|
||||
StartService,
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn start_tray(options: Arc<Mutex<HashMap<String, String>>>) {
|
||||
let event_loop = EventLoop::<Events>::with_user_event();
|
||||
let proxy = event_loop.create_proxy();
|
||||
@@ -76,3 +83,99 @@ pub fn start_tray(options: Arc<Mutex<HashMap<String, String>>>) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Start a tray icon in Linux
|
||||
///
|
||||
/// [Block]
|
||||
/// This function will block current execution, show the tray icon and handle events.
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn start_tray(options: Arc<Mutex<HashMap<String, String>>>) {
|
||||
use std::time::Duration;
|
||||
|
||||
use gtk::traits::{GtkMenuItemExt, MenuShellExt, WidgetExt};
|
||||
info!("configuring tray");
|
||||
// init gtk context
|
||||
if let Err(err) = gtk::init() {
|
||||
error!("Error when starting the tray: {}", err);
|
||||
return;
|
||||
}
|
||||
if let Some(mut appindicator) = get_default_app_indicator() {
|
||||
let mut menu = gtk::Menu::new();
|
||||
let running = get_service_status(options.clone());
|
||||
// start/stop service
|
||||
let label = if !running {
|
||||
crate::client::translate("Start Service".to_owned())
|
||||
} else {
|
||||
crate::client::translate("Stop service".to_owned())
|
||||
};
|
||||
let menu_item_service = gtk::MenuItem::with_label(label.as_str());
|
||||
menu_item_service.connect_activate(move |item| {
|
||||
let lock = crate::ui_interface::SENDER.lock().unwrap();
|
||||
update_tray_service_item(options.clone(), item);
|
||||
});
|
||||
menu.append(&menu_item_service);
|
||||
// show tray item
|
||||
menu.show_all();
|
||||
appindicator.set_menu(&mut menu);
|
||||
// start event loop
|
||||
info!("Setting tray event loop");
|
||||
gtk::main();
|
||||
} else {
|
||||
error!("Tray process exit now");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn update_tray_service_item(options: Arc<Mutex<HashMap<String, String>>>, item: >k::MenuItem) {
|
||||
use gtk::{
|
||||
traits::{GtkMenuItemExt, ListBoxRowExt},
|
||||
MenuItem,
|
||||
};
|
||||
if get_service_status(options.clone()) {
|
||||
debug!("Now try to stop service");
|
||||
item.set_label(&crate::client::translate("Start Service".to_owned()));
|
||||
crate::ipc::set_option("stop-service", "Y");
|
||||
} else {
|
||||
debug!("Now try to start service");
|
||||
item.set_label(&crate::client::translate("Stop service".to_owned()));
|
||||
crate::ipc::set_option("stop-service", "");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn get_default_app_indicator() -> Option<AppIndicator> {
|
||||
use libappindicator::AppIndicatorStatus;
|
||||
use std::io::Write;
|
||||
|
||||
let icon = include_bytes!("../res/icon.png");
|
||||
// appindicator does not support icon buffer, so we write it to tmp folder
|
||||
let mut icon_path = temp_dir();
|
||||
icon_path.push("RustDesk");
|
||||
icon_path.push("rustdesk.png");
|
||||
match std::fs::File::create(icon_path.clone()) {
|
||||
Ok(mut f) => {
|
||||
f.write_all(icon).unwrap();
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Error when writing icon to {:?}: {}", icon_path, err);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
debug!("write temp icon complete");
|
||||
let mut appindicator = AppIndicator::new("RustDesk", icon_path.to_str().unwrap_or("rustdesk"));
|
||||
appindicator.set_label("RustDesk", "A remote control software.");
|
||||
appindicator.set_status(AppIndicatorStatus::Active);
|
||||
Some(appindicator)
|
||||
}
|
||||
|
||||
/// Get service status
|
||||
/// Return [`true`] if service is running, [`false`] otherwise.
|
||||
#[inline]
|
||||
fn get_service_status(options: Arc<Mutex<HashMap<String, String>>>) -> bool {
|
||||
if let Some(v) = options.lock().unwrap().get("stop-service") {
|
||||
debug!("service stopped: {}", v);
|
||||
v.is_empty()
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user