mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-04-13 06:01:27 +03:00
Frontend improvement (#27)
* removed redundant dns lookups * frontend now correctly reflects the state of the backend * config.toml is loaded when starting gtk frontend
This commit is contained in:
committed by
Ferdinand Schober
parent
603646c799
commit
06725f4b14
@@ -2,16 +2,18 @@ mod window;
|
||||
mod client_object;
|
||||
mod client_row;
|
||||
|
||||
use std::{io::Result, thread::{self, JoinHandle}};
|
||||
use std::{io::{Result, Read, ErrorKind}, thread::{self, JoinHandle}, env, process, path::Path, os::unix::net::UnixStream, str};
|
||||
|
||||
use crate::frontend::gtk::window::Window;
|
||||
use crate::{frontend::gtk::window::Window, config::DEFAULT_PORT};
|
||||
|
||||
use gtk::{prelude::*, IconTheme, gdk::Display, gio::{SimpleAction, SimpleActionGroup}, glib::clone, CssProvider};
|
||||
use gtk::{prelude::*, IconTheme, gdk::Display, gio::{SimpleAction, SimpleActionGroup}, glib::{clone, MainContext, Priority}, CssProvider, subclass::prelude::ObjectSubclassIsExt};
|
||||
use adw::Application;
|
||||
use gtk::{gio, glib, prelude::ApplicationExt};
|
||||
|
||||
use self::client_object::ClientObject;
|
||||
|
||||
use super::FrontendNotify;
|
||||
|
||||
pub fn start() -> Result<JoinHandle<glib::ExitCode>> {
|
||||
thread::Builder::new()
|
||||
.name("gtk-thread".into())
|
||||
@@ -49,45 +51,137 @@ fn load_icons() {
|
||||
}
|
||||
|
||||
fn build_ui(app: &Application) {
|
||||
let xdg_runtime_dir = match env::var("XDG_RUNTIME_DIR") {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
log::error!("{e}");
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
let socket_path = Path::new(xdg_runtime_dir.as_str())
|
||||
.join("lan-mouse-socket.sock");
|
||||
let Ok(mut rx) = UnixStream::connect(&socket_path) else {
|
||||
log::error!("Could not connect to lan-mouse-socket @ {socket_path:?}");
|
||||
process::exit(1);
|
||||
};
|
||||
let tx = match rx.try_clone() {
|
||||
Ok(sock) => sock,
|
||||
Err(e) => {
|
||||
log::error!("{e}");
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
let (sender, receiver) = MainContext::channel::<FrontendNotify>(Priority::default());
|
||||
|
||||
gio::spawn_blocking(move || {
|
||||
match loop {
|
||||
// read length
|
||||
let mut len = [0u8; 8];
|
||||
match rx.read_exact(&mut len) {
|
||||
Ok(_) => (),
|
||||
Err(e) if e.kind() == ErrorKind::UnexpectedEof => break Ok(()),
|
||||
Err(e) => break Err(e),
|
||||
};
|
||||
let len = usize::from_ne_bytes(len);
|
||||
|
||||
// read payload
|
||||
let mut buf = vec![0u8; len];
|
||||
match rx.read_exact(&mut buf) {
|
||||
Ok(_) => (),
|
||||
Err(e) if e.kind() == ErrorKind::UnexpectedEof => break Ok(()),
|
||||
Err(e) => break Err(e),
|
||||
};
|
||||
|
||||
// parse json
|
||||
let json = str::from_utf8(&buf)
|
||||
.unwrap();
|
||||
match serde_json::from_str(json) {
|
||||
Ok(notify) => sender.send(notify).unwrap(),
|
||||
Err(e) => log::error!("{e}"),
|
||||
}
|
||||
} {
|
||||
Ok(()) => {},
|
||||
Err(e) => log::error!("{e}"),
|
||||
}
|
||||
});
|
||||
|
||||
let window = Window::new(app);
|
||||
let action_client_activate = SimpleAction::new(
|
||||
"activate-client",
|
||||
Some(&i32::static_variant_type()),
|
||||
window.imp().stream.borrow_mut().replace(tx);
|
||||
receiver.attach(None, clone!(@weak window => @default-return glib::ControlFlow::Break,
|
||||
move |notify| {
|
||||
match notify {
|
||||
FrontendNotify::NotifyClientCreate(client, hostname, port, position) => {
|
||||
window.new_client(client, hostname, port, position, false);
|
||||
},
|
||||
FrontendNotify::NotifyClientUpdate(client, hostname, port, position) => {
|
||||
log::info!("client updated: {client}, {}:{port}, {position}", hostname.unwrap_or("".to_string()));
|
||||
}
|
||||
FrontendNotify::NotifyError(e) => {
|
||||
// TODO
|
||||
log::error!("{e}");
|
||||
},
|
||||
FrontendNotify::NotifyClientDelete(client) => {
|
||||
window.delete_client(client);
|
||||
}
|
||||
FrontendNotify::Enumerate(clients) => {
|
||||
for (client, active) in clients {
|
||||
if window.client_idx(client.handle).is_some() {
|
||||
continue
|
||||
}
|
||||
window.new_client(
|
||||
client.handle,
|
||||
client.hostname,
|
||||
client.addrs
|
||||
.iter()
|
||||
.next()
|
||||
.map(|s| s.port())
|
||||
.unwrap_or(DEFAULT_PORT),
|
||||
client.pos,
|
||||
active,
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
glib::ControlFlow::Continue
|
||||
}
|
||||
));
|
||||
|
||||
let action_request_client_update = SimpleAction::new(
|
||||
"request-client-update",
|
||||
Some(&u32::static_variant_type()),
|
||||
);
|
||||
|
||||
// remove client
|
||||
let action_client_delete = SimpleAction::new(
|
||||
"delete-client",
|
||||
Some(&i32::static_variant_type()),
|
||||
"request-client-delete",
|
||||
Some(&u32::static_variant_type()),
|
||||
);
|
||||
action_client_activate.connect_activate(clone!(@weak window => move |_action, param| {
|
||||
log::debug!("activate-client");
|
||||
|
||||
// update client state
|
||||
action_request_client_update.connect_activate(clone!(@weak window => move |_action, param| {
|
||||
log::debug!("request-client-update");
|
||||
let index = param.unwrap()
|
||||
.get::<i32>()
|
||||
.get::<u32>()
|
||||
.unwrap();
|
||||
let Some(client) = window.clients().item(index as u32) else {
|
||||
return;
|
||||
};
|
||||
let client = client.downcast_ref::<ClientObject>().unwrap();
|
||||
window.update_client(client);
|
||||
window.request_client_update(client);
|
||||
}));
|
||||
|
||||
action_client_delete.connect_activate(clone!(@weak window => move |_action, param| {
|
||||
log::debug!("delete-client");
|
||||
let index = param.unwrap()
|
||||
.get::<i32>()
|
||||
let idx = param.unwrap()
|
||||
.get::<u32>()
|
||||
.unwrap();
|
||||
let Some(client) = window.clients().item(index as u32) else {
|
||||
return;
|
||||
};
|
||||
let client = client.downcast_ref::<ClientObject>().unwrap();
|
||||
window.update_client(client);
|
||||
window.clients().remove(index as u32);
|
||||
if window.clients().n_items() == 0 {
|
||||
window.set_placeholder_visible(true);
|
||||
}
|
||||
window.request_client_delete(idx);
|
||||
}));
|
||||
|
||||
let actions = SimpleActionGroup::new();
|
||||
window.insert_action_group("win", Some(&actions));
|
||||
actions.add_action(&action_client_activate);
|
||||
actions.add_action(&action_request_client_update);
|
||||
actions.add_action(&action_client_delete);
|
||||
window.present();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user