diff --git a/lan-mouse-gtk/src/lib.rs b/lan-mouse-gtk/src/lib.rs index 75199b5..f5e72b7 100644 --- a/lan-mouse-gtk/src/lib.rs +++ b/lan-mouse-gtk/src/lib.rs @@ -12,9 +12,7 @@ use window::Window; use lan_mouse_ipc::FrontendEvent; use adw::Application; -use gtk::{ - gdk::Display, glib::clone, prelude::*, subclass::prelude::ObjectSubclassIsExt, IconTheme, -}; +use gtk::{gdk::Display, glib::clone, prelude::*, IconTheme}; use gtk::{gio, glib, prelude::ApplicationExt}; use self::client_object::ClientObject; @@ -128,50 +126,27 @@ fn build_ui(app: &Application) { let notify = receiver.recv().await.unwrap_or_else(|_| process::exit(1)); match notify { FrontendEvent::Created(handle, client, state) => { - window.new_client(handle, client, state); - } - FrontendEvent::Deleted(client) => { - window.delete_client(client); + window.new_client(handle, client, state) } + FrontendEvent::Deleted(client) => window.delete_client(client), FrontendEvent::State(handle, config, state) => { window.update_client_config(handle, config); window.update_client_state(handle, state); } FrontendEvent::NoSuchClient(_) => {} - FrontendEvent::Error(e) => { - window.show_toast(e.as_str()); + FrontendEvent::Error(e) => window.show_toast(e.as_str()), + FrontendEvent::Enumerate(clients) => window.update_client_list(clients), + FrontendEvent::PortChanged(port, msg) => window.update_port(port, msg), + FrontendEvent::CaptureStatus(s) => window.set_capture(s.into()), + FrontendEvent::EmulationStatus(s) => window.set_emulation(s.into()), + FrontendEvent::AuthorizedUpdated(keys) => window.set_authorized_keys(keys), + FrontendEvent::PublicKeyFingerprint(fp) => window.set_pk_fp(&fp), + FrontendEvent::IncomingConnected(_fingerprint, addr, pos) => { + window.show_toast(format!("device connected: {addr} ({pos})").as_str()); } - FrontendEvent::Enumerate(clients) => { - for (handle, client, state) in clients { - if window.client_idx(handle).is_some() { - window.update_client_config(handle, client); - window.update_client_state(handle, state); - } else { - window.new_client(handle, client, state); - } - } + FrontendEvent::IncomingDisconnected(addr) => { + window.show_toast(format!("{addr} disconnected").as_str()); } - FrontendEvent::PortChanged(port, msg) => { - match msg { - None => window.show_toast(format!("port changed: {port}").as_str()), - Some(msg) => window.show_toast(msg.as_str()), - } - window.imp().set_port(port); - } - FrontendEvent::CaptureStatus(s) => { - window.set_capture(s.into()); - } - FrontendEvent::EmulationStatus(s) => { - window.set_emulation(s.into()); - } - FrontendEvent::AuthorizedUpdated(keys) => { - window.set_authorized_keys(keys); - } - FrontendEvent::PublicKeyFingerprint(fp) => { - window.set_pk_fp(&fp); - } - FrontendEvent::IncomingConnected(..) => {} - FrontendEvent::IncomingDisconnected(..) => {} } } } diff --git a/lan-mouse-gtk/src/window.rs b/lan-mouse-gtk/src/window.rs index c52a77d..a2beca1 100644 --- a/lan-mouse-gtk/src/window.rs +++ b/lan-mouse-gtk/src/window.rs @@ -28,7 +28,7 @@ glib::wrapper! { } impl Window { - pub(crate) fn new(app: &adw::Application, conn: FrontendRequestWriter) -> Self { + pub(super) fn new(app: &adw::Application, conn: FrontendRequestWriter) -> Self { let window: Self = Object::builder().property("application", app).build(); window .imp() @@ -38,7 +38,7 @@ impl Window { window } - pub fn clients(&self) -> gio::ListStore { + fn clients(&self) -> gio::ListStore { self.imp() .clients .borrow() @@ -46,7 +46,7 @@ impl Window { .expect("Could not get clients") } - pub fn authorized(&self) -> gio::ListStore { + fn authorized(&self) -> gio::ListStore { self.imp() .authorized .borrow() @@ -58,6 +58,10 @@ impl Window { self.clients().item(idx).map(|o| o.downcast().unwrap()) } + fn authorized_by_idx(&self, idx: u32) -> Option { + self.authorized().item(idx).map(|o| o.downcast().unwrap()) + } + fn row_by_idx(&self, idx: i32) -> Option { self.imp() .client_list @@ -66,10 +70,6 @@ impl Window { .map(|o| o.downcast().expect("expected ClientRow")) } - fn authorized_by_idx(&self, idx: u32) -> Option { - self.authorized().item(idx).map(|o| o.downcast().unwrap()) - } - fn setup_authorized(&self) { let store = gio::ListStore::new::(); self.imp().authorized.replace(Some(store)); @@ -231,10 +231,14 @@ impl Window { ); } + fn setup_icon(&self) { + self.set_icon_name(Some("de.feschber.LanMouse")); + } + /// workaround for a bug in libadwaita that shows an ugly line beneath /// the last element if a placeholder is set. /// https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/6308 - pub fn update_placeholder_visibility(&self) { + fn update_placeholder_visibility(&self) { let visible = self.clients().n_items() == 0; let placeholder = self.imp().client_placeholder.get(); self.imp().client_list.set_placeholder(match visible { @@ -243,7 +247,7 @@ impl Window { }); } - pub fn update_auth_placeholder_visibility(&self) { + fn update_auth_placeholder_visibility(&self) { let visible = self.authorized().n_items() == 0; let placeholder = self.imp().authorized_placeholder.get(); self.imp().authorized_list.set_placeholder(match visible { @@ -252,10 +256,6 @@ impl Window { }); } - fn setup_icon(&self) { - self.set_icon_name(Some("de.feschber.LanMouse")); - } - fn create_client_row(&self, client_object: &ClientObject) -> ClientRow { let row = ClientRow::new(client_object); row.bind(client_object); @@ -268,20 +268,47 @@ impl Window { row } - pub fn new_client(&self, handle: ClientHandle, client: ClientConfig, state: ClientState) { + pub(super) fn new_client( + &self, + handle: ClientHandle, + client: ClientConfig, + state: ClientState, + ) { let client = ClientObject::new(handle, client, state.clone()); self.clients().append(&client); self.update_placeholder_visibility(); self.update_dns_state(handle, !state.ips.is_empty()); } - pub(super) fn client_idx(&self, handle: ClientHandle) -> Option { + pub(super) fn update_client_list( + &self, + clients: Vec<(ClientHandle, ClientConfig, ClientState)>, + ) { + for (handle, client, state) in clients { + if self.client_idx(handle).is_some() { + self.update_client_config(handle, client); + self.update_client_state(handle, state); + } else { + self.new_client(handle, client, state); + } + } + } + + pub(super) fn update_port(&self, port: u16, msg: Option) { + match msg { + None => self.show_toast(format!("port changed: {port}").as_str()), + Some(msg) => self.show_toast(msg.as_str()), + } + self.imp().set_port(port); + } + + fn client_idx(&self, handle: ClientHandle) -> Option { self.clients() .iter::() .position(|c| c.ok().map(|c| c.handle() == handle).unwrap_or_default()) } - pub fn delete_client(&self, handle: ClientHandle) { + pub(super) fn delete_client(&self, handle: ClientHandle) { let Some(idx) = self.client_idx(handle) else { log::warn!("could not find client with handle {handle}"); return; @@ -293,7 +320,7 @@ impl Window { } } - pub fn update_client_config(&self, handle: ClientHandle, client: ClientConfig) { + pub(super) fn update_client_config(&self, handle: ClientHandle, client: ClientConfig) { let Some(row) = self.row_for_handle(handle) else { log::warn!("could not find row for handle {}", handle); return; @@ -303,7 +330,7 @@ impl Window { row.set_position(client.pos); } - pub fn update_client_state(&self, handle: ClientHandle, state: ClientState) { + pub(super) fn update_client_state(&self, handle: ClientHandle, state: ClientState) { let Some(row) = self.row_for_handle(handle) else { log::warn!("could not find row for handle {}", handle); return; @@ -374,7 +401,7 @@ impl Window { self.request(FrontendRequest::Create); } - pub fn open_fingerprint_dialog(&self) { + fn open_fingerprint_dialog(&self) { let window = FingerprintWindow::new(); window.set_transient_for(Some(self)); window.connect_closure( @@ -392,15 +419,15 @@ impl Window { window.present(); } - pub fn request_fingerprint_add(&self, desc: String, fp: String) { + fn request_fingerprint_add(&self, desc: String, fp: String) { self.request(FrontendRequest::AuthorizeKey(desc, fp)); } - pub fn request_fingerprint_remove(&self, fp: String) { + fn request_fingerprint_remove(&self, fp: String) { self.request(FrontendRequest::RemoveAuthorizedKey(fp)); } - pub fn request(&self, request: FrontendRequest) { + fn request(&self, request: FrontendRequest) { let mut requester = self.imp().frontend_request_writer.borrow_mut(); let requester = requester.as_mut().unwrap(); if let Err(e) = requester.request(request) { @@ -408,18 +435,18 @@ impl Window { }; } - pub fn show_toast(&self, msg: &str) { + pub(super) fn show_toast(&self, msg: &str) { let toast = adw::Toast::new(msg); let toast_overlay = &self.imp().toast_overlay; toast_overlay.add_toast(toast); } - pub fn set_capture(&self, active: bool) { + pub(super) fn set_capture(&self, active: bool) { self.imp().capture_active.replace(active); self.update_capture_emulation_status(); } - pub fn set_emulation(&self, active: bool) { + pub(super) fn set_emulation(&self, active: bool) { self.imp().emulation_active.replace(active); self.update_capture_emulation_status(); } @@ -434,7 +461,7 @@ impl Window { .set_visible(!capture || !emulation); } - pub(crate) fn set_authorized_keys(&self, fingerprints: HashMap) { + pub(super) fn set_authorized_keys(&self, fingerprints: HashMap) { let authorized = self.authorized(); // clear list authorized.remove_all(); @@ -446,7 +473,7 @@ impl Window { self.update_auth_placeholder_visibility(); } - pub(crate) fn set_pk_fp(&self, fingerprint: &str) { + pub(super) fn set_pk_fp(&self, fingerprint: &str) { self.imp().fingerprint_row.set_subtitle(fingerprint); } }