mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-03-07 20:09:59 +03:00
Activate on startup (#70)
Frontends are now properly synced among each other and on startup the correct state is reflected. Closes #75 Closes #68
This commit is contained in:
committed by
GitHub
parent
2e52660714
commit
d90eb0cd0f
@@ -204,7 +204,7 @@ port = 4242
|
|||||||
# define a client on the right side with host name "iridium"
|
# define a client on the right side with host name "iridium"
|
||||||
[right]
|
[right]
|
||||||
# hostname
|
# hostname
|
||||||
host_name = "iridium"
|
hostname = "iridium"
|
||||||
# optional list of (known) ip addresses
|
# optional list of (known) ip addresses
|
||||||
ips = ["192.168.178.156"]
|
ips = ["192.168.178.156"]
|
||||||
|
|
||||||
@@ -212,7 +212,7 @@ ips = ["192.168.178.156"]
|
|||||||
[left]
|
[left]
|
||||||
# The hostname is optional: When no hostname is specified,
|
# The hostname is optional: When no hostname is specified,
|
||||||
# at least one ip address needs to be specified.
|
# at least one ip address needs to be specified.
|
||||||
host_name = "thorium"
|
hostname = "thorium"
|
||||||
# ips for ethernet and wifi
|
# ips for ethernet and wifi
|
||||||
ips = ["192.168.178.189", "192.168.178.172"]
|
ips = ["192.168.178.189", "192.168.178.172"]
|
||||||
# optional port
|
# optional port
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ port = 4242
|
|||||||
# define a client on the right side with host name "iridium"
|
# define a client on the right side with host name "iridium"
|
||||||
[right]
|
[right]
|
||||||
# hostname
|
# hostname
|
||||||
host_name = "iridium"
|
hostname = "iridium"
|
||||||
# optional list of (known) ip addresses
|
# optional list of (known) ip addresses
|
||||||
ips = ["192.168.178.156"]
|
ips = ["192.168.178.156"]
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ ips = ["192.168.178.156"]
|
|||||||
[left]
|
[left]
|
||||||
# The hostname is optional: When no hostname is specified,
|
# The hostname is optional: When no hostname is specified,
|
||||||
# at least one ip address needs to be specified.
|
# at least one ip address needs to be specified.
|
||||||
host_name = "thorium"
|
hostname = "thorium"
|
||||||
# ips for ethernet and wifi
|
# ips for ethernet and wifi
|
||||||
ips = ["192.168.178.189", "192.168.178.172"]
|
ips = ["192.168.178.189", "192.168.178.172"]
|
||||||
# optional port
|
# optional port
|
||||||
|
|||||||
@@ -46,6 +46,20 @@ impl Display for Position {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&str> for Position {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||||
|
match s {
|
||||||
|
"left" => Ok(Position::Left),
|
||||||
|
"right" => Ok(Position::Right),
|
||||||
|
"top" => Ok(Position::Top),
|
||||||
|
"bottom" => Ok(Position::Bottom),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
/// hostname of this client
|
/// hostname of this client
|
||||||
@@ -112,6 +126,7 @@ impl ClientManager {
|
|||||||
ips: HashSet<IpAddr>,
|
ips: HashSet<IpAddr>,
|
||||||
port: u16,
|
port: u16,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
|
active: bool,
|
||||||
) -> ClientHandle {
|
) -> ClientHandle {
|
||||||
// get a new client_handle
|
// get a new client_handle
|
||||||
let handle = self.free_id();
|
let handle = self.free_id();
|
||||||
@@ -135,7 +150,7 @@ impl ClientManager {
|
|||||||
// client was never seen, nor pinged
|
// client was never seen, nor pinged
|
||||||
let client_state = ClientState {
|
let client_state = ClientState {
|
||||||
client,
|
client,
|
||||||
active: false,
|
active,
|
||||||
active_addr: None,
|
active_addr: None,
|
||||||
alive: false,
|
alive: false,
|
||||||
pressed_keys: HashSet::new(),
|
pressed_keys: HashSet::new(),
|
||||||
|
|||||||
@@ -15,17 +15,19 @@ pub const DEFAULT_PORT: u16 = 4242;
|
|||||||
pub struct ConfigToml {
|
pub struct ConfigToml {
|
||||||
pub port: Option<u16>,
|
pub port: Option<u16>,
|
||||||
pub frontend: Option<String>,
|
pub frontend: Option<String>,
|
||||||
pub left: Option<Client>,
|
pub left: Option<TomlClient>,
|
||||||
pub right: Option<Client>,
|
pub right: Option<TomlClient>,
|
||||||
pub top: Option<Client>,
|
pub top: Option<TomlClient>,
|
||||||
pub bottom: Option<Client>,
|
pub bottom: Option<TomlClient>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
|
||||||
pub struct Client {
|
pub struct TomlClient {
|
||||||
|
pub hostname: Option<String>,
|
||||||
pub host_name: Option<String>,
|
pub host_name: Option<String>,
|
||||||
pub ips: Option<Vec<IpAddr>>,
|
pub ips: Option<Vec<IpAddr>>,
|
||||||
pub port: Option<u16>,
|
pub port: Option<u16>,
|
||||||
|
pub activate_on_startup: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConfigToml {
|
impl ConfigToml {
|
||||||
@@ -66,10 +68,18 @@ pub enum Frontend {
|
|||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub frontend: Frontend,
|
pub frontend: Frontend,
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
pub clients: Vec<(Client, Position)>,
|
pub clients: Vec<(TomlClient, Position)>,
|
||||||
pub daemon: bool,
|
pub daemon: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ConfigClient {
|
||||||
|
pub ips: HashSet<IpAddr>,
|
||||||
|
pub hostname: Option<String>,
|
||||||
|
pub port: u16,
|
||||||
|
pub pos: Position,
|
||||||
|
pub active: bool,
|
||||||
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn new() -> Result<Self> {
|
pub fn new() -> Result<Self> {
|
||||||
let args = CliArgs::parse();
|
let args = CliArgs::parse();
|
||||||
@@ -128,7 +138,7 @@ impl Config {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut clients: Vec<(Client, Position)> = vec![];
|
let mut clients: Vec<(TomlClient, Position)> = vec![];
|
||||||
|
|
||||||
if let Some(config_toml) = config_toml {
|
if let Some(config_toml) = config_toml {
|
||||||
if let Some(c) = config_toml.right {
|
if let Some(c) = config_toml.right {
|
||||||
@@ -155,18 +165,28 @@ impl Config {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_clients(&self) -> Vec<(HashSet<IpAddr>, Option<String>, u16, Position)> {
|
pub fn get_clients(&self) -> Vec<ConfigClient> {
|
||||||
self.clients
|
self.clients
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(c, p)| {
|
.map(|(c, pos)| {
|
||||||
let port = c.port.unwrap_or(DEFAULT_PORT);
|
let port = c.port.unwrap_or(DEFAULT_PORT);
|
||||||
let ips: HashSet<IpAddr> = if let Some(ips) = c.ips.as_ref() {
|
let ips: HashSet<IpAddr> = if let Some(ips) = c.ips.as_ref() {
|
||||||
HashSet::from_iter(ips.iter().cloned())
|
HashSet::from_iter(ips.iter().cloned())
|
||||||
} else {
|
} else {
|
||||||
HashSet::new()
|
HashSet::new()
|
||||||
};
|
};
|
||||||
let host_name = c.host_name.clone();
|
let hostname = match &c.hostname {
|
||||||
(ips, host_name, port, *p)
|
Some(h) => Some(h.clone()),
|
||||||
|
None => c.host_name.clone(),
|
||||||
|
};
|
||||||
|
let active = c.activate_on_startup.unwrap_or(false);
|
||||||
|
ConfigClient {
|
||||||
|
ips,
|
||||||
|
hostname,
|
||||||
|
port,
|
||||||
|
pos: *pos,
|
||||||
|
active,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,8 +103,9 @@ pub enum FrontendEvent {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub enum FrontendNotify {
|
pub enum FrontendNotify {
|
||||||
NotifyClientCreate(ClientHandle, Option<String>, u16, Position),
|
NotifyClientActivate(ClientHandle, bool),
|
||||||
NotifyClientUpdate(ClientHandle, Option<String>, u16, Position),
|
NotifyClientCreate(Client),
|
||||||
|
NotifyClientUpdate(Client),
|
||||||
NotifyClientDelete(ClientHandle),
|
NotifyClientDelete(ClientHandle),
|
||||||
/// new port, reason of failure (if failed)
|
/// new port, reason of failure (if failed)
|
||||||
NotifyPortChange(u16, Option<String>),
|
NotifyPortChange(u16, Option<String>),
|
||||||
@@ -224,7 +225,6 @@ impl FrontendListener {
|
|||||||
log::debug!("json: {json}, len: {}", payload.len());
|
log::debug!("json: {json}, len: {}", payload.len());
|
||||||
|
|
||||||
let mut keep = vec![];
|
let mut keep = vec![];
|
||||||
|
|
||||||
// TODO do simultaneously
|
// TODO do simultaneously
|
||||||
for tx in self.tx_streams.iter_mut() {
|
for tx in self.tx_streams.iter_mut() {
|
||||||
// write len + payload
|
// write len + payload
|
||||||
|
|||||||
@@ -83,17 +83,26 @@ pub fn run() -> Result<()> {
|
|||||||
Err(e) => break log::error!("{e}"),
|
Err(e) => break log::error!("{e}"),
|
||||||
};
|
};
|
||||||
match notify {
|
match notify {
|
||||||
FrontendNotify::NotifyClientCreate(client, host, port, pos) => {
|
FrontendNotify::NotifyClientActivate(handle, active) => {
|
||||||
log::info!(
|
if active {
|
||||||
"new client ({client}): {}:{port} - {pos}",
|
log::info!("client {handle} activated");
|
||||||
host.as_deref().unwrap_or("")
|
} else {
|
||||||
);
|
log::info!("client {handle} deactivated");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
FrontendNotify::NotifyClientUpdate(client, host, port, pos) => {
|
FrontendNotify::NotifyClientCreate(client) => {
|
||||||
log::info!(
|
let handle = client.handle;
|
||||||
"client ({client}) updated: {}:{port} - {pos}",
|
let port = client.port;
|
||||||
host.as_deref().unwrap_or("")
|
let pos = client.pos;
|
||||||
);
|
let hostname = client.hostname.as_deref().unwrap_or("");
|
||||||
|
log::info!("new client ({handle}): {hostname}:{port} - {pos}");
|
||||||
|
}
|
||||||
|
FrontendNotify::NotifyClientUpdate(client) => {
|
||||||
|
let handle = client.handle;
|
||||||
|
let port = client.port;
|
||||||
|
let pos = client.pos;
|
||||||
|
let hostname = client.hostname.as_deref().unwrap_or("");
|
||||||
|
log::info!("client ({handle}) updated: {hostname}:{port} - {pos}");
|
||||||
}
|
}
|
||||||
FrontendNotify::NotifyClientDelete(client) => {
|
FrontendNotify::NotifyClientDelete(client) => {
|
||||||
log::info!("client ({client}) deleted.");
|
log::info!("client ({client}) deleted.");
|
||||||
|
|||||||
@@ -8,16 +8,12 @@ use std::{
|
|||||||
process, str,
|
process, str,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{config::DEFAULT_PORT, frontend::gtk::window::Window};
|
use crate::frontend::gtk::window::Window;
|
||||||
|
|
||||||
use adw::Application;
|
use adw::Application;
|
||||||
use gtk::{
|
use gtk::{
|
||||||
gdk::Display,
|
gdk::Display, glib::clone, prelude::*, subclass::prelude::ObjectSubclassIsExt, CssProvider,
|
||||||
gio::{SimpleAction, SimpleActionGroup},
|
IconTheme,
|
||||||
glib::clone,
|
|
||||||
prelude::*,
|
|
||||||
subclass::prelude::ObjectSubclassIsExt,
|
|
||||||
CssProvider, IconTheme,
|
|
||||||
};
|
};
|
||||||
use gtk::{gio, glib, prelude::ApplicationExt};
|
use gtk::{gio, glib, prelude::ApplicationExt};
|
||||||
|
|
||||||
@@ -68,8 +64,8 @@ fn load_css() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn load_icons() {
|
fn load_icons() {
|
||||||
let icon_theme =
|
let display = &Display::default().expect("Could not connect to a display.");
|
||||||
IconTheme::for_display(&Display::default().expect("Could not connect to a display."));
|
let icon_theme = IconTheme::for_display(display);
|
||||||
icon_theme.add_resource_path("/de/feschber/LanMouse/icons");
|
icon_theme.add_resource_path("/de/feschber/LanMouse/icons");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,15 +126,17 @@ fn build_ui(app: &Application) {
|
|||||||
loop {
|
loop {
|
||||||
let notify = receiver.recv().await.unwrap();
|
let notify = receiver.recv().await.unwrap();
|
||||||
match notify {
|
match notify {
|
||||||
FrontendNotify::NotifyClientCreate(client, hostname, port, position) => {
|
FrontendNotify::NotifyClientActivate(handle, active) => {
|
||||||
window.new_client(client, hostname, port, position, false);
|
window.activate_client(handle, active);
|
||||||
|
}
|
||||||
|
FrontendNotify::NotifyClientCreate(client) => {
|
||||||
|
window.new_client(client, false);
|
||||||
},
|
},
|
||||||
FrontendNotify::NotifyClientUpdate(client, hostname, port, position) => {
|
FrontendNotify::NotifyClientUpdate(client) => {
|
||||||
log::info!("client updated: {client}, {}:{port}, {position}", hostname.unwrap_or("".to_string()));
|
window.update_client(client);
|
||||||
}
|
}
|
||||||
FrontendNotify::NotifyError(e) => {
|
FrontendNotify::NotifyError(e) => {
|
||||||
// TODO
|
window.show_toast(e.as_str());
|
||||||
log::error!("{e}");
|
|
||||||
},
|
},
|
||||||
FrontendNotify::NotifyClientDelete(client) => {
|
FrontendNotify::NotifyClientDelete(client) => {
|
||||||
window.delete_client(client);
|
window.delete_client(client);
|
||||||
@@ -146,19 +144,11 @@ fn build_ui(app: &Application) {
|
|||||||
FrontendNotify::Enumerate(clients) => {
|
FrontendNotify::Enumerate(clients) => {
|
||||||
for (client, active) in clients {
|
for (client, active) in clients {
|
||||||
if window.client_idx(client.handle).is_some() {
|
if window.client_idx(client.handle).is_some() {
|
||||||
continue
|
window.activate_client(client.handle, active);
|
||||||
|
window.update_client(client);
|
||||||
|
} else {
|
||||||
|
window.new_client(client, active);
|
||||||
}
|
}
|
||||||
window.new_client(
|
|
||||||
client.handle,
|
|
||||||
client.hostname,
|
|
||||||
client.addrs
|
|
||||||
.iter()
|
|
||||||
.next()
|
|
||||||
.map(|s| s.port())
|
|
||||||
.unwrap_or(DEFAULT_PORT),
|
|
||||||
client.pos,
|
|
||||||
active,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
FrontendNotify::NotifyPortChange(port, msg) => {
|
FrontendNotify::NotifyPortChange(port, msg) => {
|
||||||
@@ -172,37 +162,5 @@ fn build_ui(app: &Application) {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let action_request_client_update =
|
|
||||||
SimpleAction::new("request-client-update", Some(&u32::static_variant_type()));
|
|
||||||
|
|
||||||
// remove client
|
|
||||||
let action_client_delete =
|
|
||||||
SimpleAction::new("request-client-delete", Some(&u32::static_variant_type()));
|
|
||||||
|
|
||||||
// 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::<u32>()
|
|
||||||
.unwrap();
|
|
||||||
let Some(client) = window.clients().item(index) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let client = client.downcast_ref::<ClientObject>().unwrap();
|
|
||||||
window.request_client_update(client);
|
|
||||||
}));
|
|
||||||
|
|
||||||
action_client_delete.connect_activate(clone!(@weak window => move |_action, param| {
|
|
||||||
log::debug!("delete-client");
|
|
||||||
let idx = param.unwrap()
|
|
||||||
.get::<u32>()
|
|
||||||
.unwrap();
|
|
||||||
window.request_client_delete(idx);
|
|
||||||
}));
|
|
||||||
|
|
||||||
let actions = SimpleActionGroup::new();
|
|
||||||
window.insert_action_group("win", Some(&actions));
|
|
||||||
actions.add_action(&action_request_client_update);
|
|
||||||
actions.add_action(&action_client_delete);
|
|
||||||
window.present();
|
window.present();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,26 +3,20 @@ mod imp;
|
|||||||
use adw::subclass::prelude::*;
|
use adw::subclass::prelude::*;
|
||||||
use gtk::glib::{self, Object};
|
use gtk::glib::{self, Object};
|
||||||
|
|
||||||
use crate::client::ClientHandle;
|
use crate::client::{Client, ClientHandle};
|
||||||
|
|
||||||
glib::wrapper! {
|
glib::wrapper! {
|
||||||
pub struct ClientObject(ObjectSubclass<imp::ClientObject>);
|
pub struct ClientObject(ObjectSubclass<imp::ClientObject>);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientObject {
|
impl ClientObject {
|
||||||
pub fn new(
|
pub fn new(client: Client, active: bool) -> Self {
|
||||||
handle: ClientHandle,
|
|
||||||
hostname: Option<String>,
|
|
||||||
port: u32,
|
|
||||||
position: String,
|
|
||||||
active: bool,
|
|
||||||
) -> Self {
|
|
||||||
Object::builder()
|
Object::builder()
|
||||||
.property("handle", handle)
|
.property("handle", client.handle)
|
||||||
.property("hostname", hostname)
|
.property("hostname", client.hostname)
|
||||||
.property("port", port)
|
.property("port", client.port as u32)
|
||||||
|
.property("position", client.pos.to_string())
|
||||||
.property("active", active)
|
.property("active", active)
|
||||||
.property("position", position)
|
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,12 @@ impl ClientRow {
|
|||||||
.sync_create()
|
.sync_create()
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
let switch_position_binding = client_object
|
||||||
|
.bind_property("active", &self.imp().enable_switch.get(), "active")
|
||||||
|
.bidirectional()
|
||||||
|
.sync_create()
|
||||||
|
.build();
|
||||||
|
|
||||||
let hostname_binding = client_object
|
let hostname_binding = client_object
|
||||||
.bind_property("hostname", &self.imp().hostname.get(), "text")
|
.bind_property("hostname", &self.imp().hostname.get(), "text")
|
||||||
.transform_to(|_, v: Option<String>| {
|
.transform_to(|_, v: Option<String>| {
|
||||||
@@ -104,6 +110,7 @@ impl ClientRow {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
bindings.push(active_binding);
|
bindings.push(active_binding);
|
||||||
|
bindings.push(switch_position_binding);
|
||||||
bindings.push(hostname_binding);
|
bindings.push(hostname_binding);
|
||||||
bindings.push(title_binding);
|
bindings.push(title_binding);
|
||||||
bindings.push(port_binding);
|
bindings.push(port_binding);
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ use adw::subclass::prelude::*;
|
|||||||
use adw::{prelude::*, ActionRow, ComboRow};
|
use adw::{prelude::*, ActionRow, ComboRow};
|
||||||
use glib::{subclass::InitializingObject, Binding};
|
use glib::{subclass::InitializingObject, Binding};
|
||||||
use gtk::glib::clone;
|
use gtk::glib::clone;
|
||||||
|
use gtk::glib::once_cell::sync::Lazy;
|
||||||
|
use gtk::glib::subclass::Signal;
|
||||||
use gtk::{glib, Button, CompositeTemplate, Switch};
|
use gtk::{glib, Button, CompositeTemplate, Switch};
|
||||||
|
|
||||||
#[derive(CompositeTemplate, Default)]
|
#[derive(CompositeTemplate, Default)]
|
||||||
@@ -28,6 +30,8 @@ pub struct ClientRow {
|
|||||||
impl ObjectSubclass for ClientRow {
|
impl ObjectSubclass for ClientRow {
|
||||||
// `NAME` needs to match `class` attribute of template
|
// `NAME` needs to match `class` attribute of template
|
||||||
const NAME: &'static str = "ClientRow";
|
const NAME: &'static str = "ClientRow";
|
||||||
|
const ABSTRACT: bool = false;
|
||||||
|
|
||||||
type Type = super::ClientRow;
|
type Type = super::ClientRow;
|
||||||
type ParentType = adw::ExpanderRow;
|
type ParentType = adw::ExpanderRow;
|
||||||
|
|
||||||
@@ -49,28 +53,33 @@ impl ObjectImpl for ClientRow {
|
|||||||
row.handle_client_delete(button);
|
row.handle_client_delete(button);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn signals() -> &'static [glib::subclass::Signal] {
|
||||||
|
static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| {
|
||||||
|
vec![
|
||||||
|
Signal::builder("request-update")
|
||||||
|
.param_types([bool::static_type()])
|
||||||
|
.build(),
|
||||||
|
Signal::builder("request-delete").build(),
|
||||||
|
]
|
||||||
|
});
|
||||||
|
SIGNALS.as_ref()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gtk::template_callbacks]
|
#[gtk::template_callbacks]
|
||||||
impl ClientRow {
|
impl ClientRow {
|
||||||
#[template_callback]
|
#[template_callback]
|
||||||
fn handle_client_set_state(&self, state: bool, switch: &Switch) -> bool {
|
fn handle_client_set_state(&self, state: bool, _switch: &Switch) -> bool {
|
||||||
let idx = self.obj().index() as u32;
|
log::debug!("state change -> requesting update");
|
||||||
switch
|
self.obj().emit_by_name::<()>("request-update", &[&state]);
|
||||||
.activate_action("win.request-client-update", Some(&idx.to_variant()))
|
|
||||||
.unwrap();
|
|
||||||
switch.set_state(state);
|
|
||||||
|
|
||||||
true // dont run default handler
|
true // dont run default handler
|
||||||
}
|
}
|
||||||
|
|
||||||
#[template_callback]
|
#[template_callback]
|
||||||
fn handle_client_delete(&self, button: &Button) {
|
fn handle_client_delete(&self, _button: &Button) {
|
||||||
log::debug!("delete button pressed");
|
log::debug!("delete button pressed -> requesting delete");
|
||||||
let idx = self.obj().index() as u32;
|
self.obj().emit_by_name::<()>("request-delete", &[]);
|
||||||
button
|
|
||||||
.activate_action("win.request-client-delete", Some(&idx.to_variant()))
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,14 @@ use std::io::Write;
|
|||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use adw::subclass::prelude::*;
|
use adw::subclass::prelude::*;
|
||||||
use glib::{clone, Object};
|
use glib::{clone, Object};
|
||||||
use gtk::{gio, glib, NoSelection};
|
use gtk::{
|
||||||
|
gio,
|
||||||
|
glib::{self, closure_local},
|
||||||
|
NoSelection,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
client::{ClientHandle, Position},
|
client::{Client, ClientHandle, Position},
|
||||||
config::DEFAULT_PORT,
|
config::DEFAULT_PORT,
|
||||||
frontend::{gtk::client_object::ClientObject, FrontendEvent},
|
frontend::{gtk::client_object::ClientObject, FrontendEvent},
|
||||||
};
|
};
|
||||||
@@ -45,6 +49,18 @@ impl Window {
|
|||||||
clone!(@weak self as window => @default-panic, move |obj| {
|
clone!(@weak self as window => @default-panic, move |obj| {
|
||||||
let client_object = obj.downcast_ref().expect("Expected object of type `ClientObject`.");
|
let client_object = obj.downcast_ref().expect("Expected object of type `ClientObject`.");
|
||||||
let row = window.create_client_row(client_object);
|
let row = window.create_client_row(client_object);
|
||||||
|
row.connect_closure("request-update", false, closure_local!(@strong window => move |row: ClientRow, active: bool| {
|
||||||
|
let index = row.index() as u32;
|
||||||
|
let Some(client) = window.clients().item(index) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let client = client.downcast_ref::<ClientObject>().unwrap();
|
||||||
|
window.request_client_update(client, active);
|
||||||
|
}));
|
||||||
|
row.connect_closure("request-delete", false, closure_local!(@strong window => move |row: ClientRow| {
|
||||||
|
let index = row.index() as u32;
|
||||||
|
window.request_client_delete(index);
|
||||||
|
}));
|
||||||
row.upcast()
|
row.upcast()
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -71,15 +87,8 @@ impl Window {
|
|||||||
row
|
row
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_client(
|
pub fn new_client(&self, client: Client, active: bool) {
|
||||||
&self,
|
let client = ClientObject::new(client, active);
|
||||||
handle: ClientHandle,
|
|
||||||
hostname: Option<String>,
|
|
||||||
port: u16,
|
|
||||||
position: Position,
|
|
||||||
active: bool,
|
|
||||||
) {
|
|
||||||
let client = ClientObject::new(handle, hostname, port as u32, position.to_string(), active);
|
|
||||||
self.clients().append(&client);
|
self.clients().append(&client);
|
||||||
self.set_placeholder_visible(false);
|
self.set_placeholder_visible(false);
|
||||||
}
|
}
|
||||||
@@ -106,6 +115,42 @@ impl Window {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn update_client(&self, client: Client) {
|
||||||
|
let Some(idx) = self.client_idx(client.handle) else {
|
||||||
|
log::warn!("could not find client with handle {}", client.handle);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let client_object = self.clients().item(idx as u32).unwrap();
|
||||||
|
let client_object: &ClientObject = client_object.downcast_ref().unwrap();
|
||||||
|
let data = client_object.get_data();
|
||||||
|
|
||||||
|
/* only change if it actually has changed, otherwise
|
||||||
|
* the update signal is triggered */
|
||||||
|
if data.hostname != client.hostname {
|
||||||
|
client_object.set_hostname(client.hostname.unwrap_or("".into()));
|
||||||
|
}
|
||||||
|
if data.port != client.port as u32 {
|
||||||
|
client_object.set_port(client.port as u32);
|
||||||
|
}
|
||||||
|
if data.position != client.pos.to_string() {
|
||||||
|
client_object.set_position(client.pos.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn activate_client(&self, handle: ClientHandle, active: bool) {
|
||||||
|
let Some(idx) = self.client_idx(handle) else {
|
||||||
|
log::warn!("could not find client with handle {handle}");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let client_object = self.clients().item(idx as u32).unwrap();
|
||||||
|
let client_object: &ClientObject = client_object.downcast_ref().unwrap();
|
||||||
|
let data = client_object.get_data();
|
||||||
|
if data.active != active {
|
||||||
|
client_object.set_active(active);
|
||||||
|
log::debug!("set active to {active}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn request_client_create(&self) {
|
pub fn request_client_create(&self) {
|
||||||
let event = FrontendEvent::AddClient(None, DEFAULT_PORT, Position::default());
|
let event = FrontendEvent::AddClient(None, DEFAULT_PORT, Position::default());
|
||||||
self.imp().set_port(DEFAULT_PORT);
|
self.imp().set_port(DEFAULT_PORT);
|
||||||
@@ -121,13 +166,10 @@ impl Window {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request_client_update(&self, client: &ClientObject) {
|
pub fn request_client_update(&self, client: &ClientObject, active: bool) {
|
||||||
let data = client.get_data();
|
let data = client.get_data();
|
||||||
let position = match data.position.as_str() {
|
let position = match Position::try_from(data.position.as_str()) {
|
||||||
"left" => Position::Left,
|
Ok(pos) => pos,
|
||||||
"right" => Position::Right,
|
|
||||||
"top" => Position::Top,
|
|
||||||
"bottom" => Position::Bottom,
|
|
||||||
_ => {
|
_ => {
|
||||||
log::error!("invalid position: {}", data.position);
|
log::error!("invalid position: {}", data.position);
|
||||||
return;
|
return;
|
||||||
@@ -135,10 +177,13 @@ impl Window {
|
|||||||
};
|
};
|
||||||
let hostname = data.hostname;
|
let hostname = data.hostname;
|
||||||
let port = data.port as u16;
|
let port = data.port as u16;
|
||||||
|
|
||||||
let event = FrontendEvent::UpdateClient(client.handle(), hostname, port, position);
|
let event = FrontendEvent::UpdateClient(client.handle(), hostname, port, position);
|
||||||
|
log::debug!("requesting update: {event:?}");
|
||||||
self.request(event);
|
self.request(event);
|
||||||
|
|
||||||
let event = FrontendEvent::ActivateClient(client.handle(), !client.active());
|
let event = FrontendEvent::ActivateClient(client.handle(), active);
|
||||||
|
log::debug!("requesting activate: {event:?}");
|
||||||
self.request(event);
|
self.request(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,7 @@ use std::net::TcpStream;
|
|||||||
use std::os::unix::net::UnixStream;
|
use std::os::unix::net::UnixStream;
|
||||||
|
|
||||||
use adw::subclass::prelude::*;
|
use adw::subclass::prelude::*;
|
||||||
use adw::{
|
use adw::{prelude::*, ActionRow, ToastOverlay};
|
||||||
prelude::{EditableExt, WidgetExt},
|
|
||||||
ActionRow, ToastOverlay,
|
|
||||||
};
|
|
||||||
use glib::subclass::InitializingObject;
|
use glib::subclass::InitializingObject;
|
||||||
use gtk::{gio, glib, Button, CompositeTemplate, Entry, ListBox};
|
use gtk::{gio, glib, Button, CompositeTemplate, Entry, ListBox};
|
||||||
|
|
||||||
@@ -42,6 +39,8 @@ pub struct Window {
|
|||||||
impl ObjectSubclass for Window {
|
impl ObjectSubclass for Window {
|
||||||
// `NAME` needs to match `class` attribute of template
|
// `NAME` needs to match `class` attribute of template
|
||||||
const NAME: &'static str = "LanMouseWindow";
|
const NAME: &'static str = "LanMouseWindow";
|
||||||
|
const ABSTRACT: bool = false;
|
||||||
|
|
||||||
type Type = super::Window;
|
type Type = super::Window;
|
||||||
type ParentType = adw::ApplicationWindow;
|
type ParentType = adw::ApplicationWindow;
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ pub fn run() -> Result<()> {
|
|||||||
// run a frontend
|
// run a frontend
|
||||||
let mut service = start_service()?;
|
let mut service = start_service()?;
|
||||||
frontend::run_frontend(&config)?;
|
frontend::run_frontend(&config)?;
|
||||||
log::info!("terminating service");
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
// on unix we give the service a chance to terminate gracefully
|
// on unix we give the service a chance to terminate gracefully
|
||||||
|
|||||||
191
src/server.rs
191
src/server.rs
@@ -67,14 +67,6 @@ pub enum ConsumerEvent {
|
|||||||
Terminate,
|
Terminate,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct ClientUpdate {
|
|
||||||
client: ClientHandle,
|
|
||||||
hostname: Option<String>,
|
|
||||||
port: u16,
|
|
||||||
pos: Position,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
active_client: Rc<Cell<Option<ClientHandle>>>,
|
active_client: Rc<Cell<Option<ClientHandle>>>,
|
||||||
@@ -89,8 +81,14 @@ impl Server {
|
|||||||
let client_manager = Rc::new(RefCell::new(ClientManager::new()));
|
let client_manager = Rc::new(RefCell::new(ClientManager::new()));
|
||||||
let state = Rc::new(Cell::new(State::Receiving));
|
let state = Rc::new(Cell::new(State::Receiving));
|
||||||
let port = Rc::new(Cell::new(config.port));
|
let port = Rc::new(Cell::new(config.port));
|
||||||
for (ips, host, port, pos) in config.get_clients() {
|
for config_client in config.get_clients() {
|
||||||
client_manager.borrow_mut().add_client(host, ips, port, pos);
|
client_manager.borrow_mut().add_client(
|
||||||
|
config_client.hostname,
|
||||||
|
config_client.ips,
|
||||||
|
config_client.port,
|
||||||
|
config_client.pos,
|
||||||
|
config_client.active,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Self {
|
Self {
|
||||||
active_client,
|
active_client,
|
||||||
@@ -212,7 +210,7 @@ impl Server {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
server.handle_frontend_stream(&mut frontend, &frontend_ch, stream).await;
|
server.handle_frontend_stream(&frontend_ch, stream).await;
|
||||||
}
|
}
|
||||||
event = frontend_rx.recv() => {
|
event = frontend_rx.recv() => {
|
||||||
let frontend_event = event.ok_or(anyhow!("frontend channel closed"))?;
|
let frontend_event = event.ok_or(anyhow!("frontend channel closed"))?;
|
||||||
@@ -421,6 +419,23 @@ impl Server {
|
|||||||
|
|
||||||
// initial sync of clients
|
// initial sync of clients
|
||||||
frontend_tx.send(FrontendEvent::Enumerate()).await?;
|
frontend_tx.send(FrontendEvent::Enumerate()).await?;
|
||||||
|
let active = self
|
||||||
|
.client_manager
|
||||||
|
.borrow()
|
||||||
|
.get_client_states()
|
||||||
|
.filter_map(|s| {
|
||||||
|
if s.active {
|
||||||
|
Some(s.client.handle)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
for client in active {
|
||||||
|
frontend_tx
|
||||||
|
.send(FrontendEvent::ActivateClient(client, true))
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
_ = signal::ctrl_c() => {
|
_ = signal::ctrl_c() => {
|
||||||
@@ -477,7 +492,6 @@ impl Server {
|
|||||||
pub async fn add_client(
|
pub async fn add_client(
|
||||||
&self,
|
&self,
|
||||||
resolver_tx: &Sender<(String, ClientHandle)>,
|
resolver_tx: &Sender<(String, ClientHandle)>,
|
||||||
frontend: &mut FrontendListener,
|
|
||||||
hostname: Option<String>,
|
hostname: Option<String>,
|
||||||
addr: HashSet<IpAddr>,
|
addr: HashSet<IpAddr>,
|
||||||
port: u16,
|
port: u16,
|
||||||
@@ -489,20 +503,18 @@ impl Server {
|
|||||||
hostname.as_deref().unwrap_or(""),
|
hostname.as_deref().unwrap_or(""),
|
||||||
&addr
|
&addr
|
||||||
);
|
);
|
||||||
let client = self
|
let handle =
|
||||||
.client_manager
|
self.client_manager
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.add_client(hostname.clone(), addr, port, pos);
|
.add_client(hostname.clone(), addr, port, pos, false);
|
||||||
|
|
||||||
log::debug!("add_client {client}");
|
log::debug!("add_client {handle}");
|
||||||
if let Some(hostname) = hostname.clone() {
|
|
||||||
let _ = resolver_tx.send((hostname, client)).await;
|
if let Some(hostname) = hostname {
|
||||||
};
|
let _ = resolver_tx.send((hostname, handle)).await;
|
||||||
let notify = FrontendNotify::NotifyClientCreate(client, hostname, port, pos);
|
}
|
||||||
if let Err(e) = frontend.notify_all(notify).await {
|
|
||||||
log::error!("error notifying frontend: {e}");
|
handle
|
||||||
};
|
|
||||||
client
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn activate_client(
|
pub async fn activate_client(
|
||||||
@@ -572,41 +584,40 @@ impl Server {
|
|||||||
producer_notify_tx: &Sender<ProducerEvent>,
|
producer_notify_tx: &Sender<ProducerEvent>,
|
||||||
consumer_notify_tx: &Sender<ConsumerEvent>,
|
consumer_notify_tx: &Sender<ConsumerEvent>,
|
||||||
resolve_tx: &Sender<(String, ClientHandle)>,
|
resolve_tx: &Sender<(String, ClientHandle)>,
|
||||||
client_update: ClientUpdate,
|
client_update: (ClientHandle, Option<String>, u16, Position),
|
||||||
) {
|
) {
|
||||||
|
let (handle, hostname, port, pos) = client_update;
|
||||||
let (hostname, handle, active) = {
|
let (hostname, handle, active) = {
|
||||||
// retrieve state
|
// retrieve state
|
||||||
let mut client_manager = self.client_manager.borrow_mut();
|
let mut client_manager = self.client_manager.borrow_mut();
|
||||||
let Some(state) = client_manager.get_mut(client_update.client) else {
|
let Some(state) = client_manager.get_mut(handle) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
// update pos
|
// update pos
|
||||||
state.client.pos = client_update.pos;
|
state.client.pos = pos;
|
||||||
|
|
||||||
// update port
|
// update port
|
||||||
if state.client.port != client_update.port {
|
if state.client.port != port {
|
||||||
state.client.port = client_update.port;
|
state.client.port = port;
|
||||||
state.client.addrs = state
|
state.client.addrs = state
|
||||||
.client
|
.client
|
||||||
.addrs
|
.addrs
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.map(|mut a| {
|
.map(|mut a| {
|
||||||
a.set_port(client_update.port);
|
a.set_port(port);
|
||||||
a
|
a
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
state.active_addr = state
|
state.active_addr = state.active_addr.map(|a| SocketAddr::new(a.ip(), port));
|
||||||
.active_addr
|
|
||||||
.map(|a| SocketAddr::new(a.ip(), client_update.port));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update hostname
|
// update hostname
|
||||||
if state.client.hostname != client_update.hostname {
|
if state.client.hostname != hostname {
|
||||||
state.client.addrs = HashSet::new();
|
state.client.addrs = HashSet::new();
|
||||||
state.active_addr = None;
|
state.active_addr = None;
|
||||||
state.client.hostname = client_update.hostname;
|
state.client.hostname = hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
log::debug!("client updated: {:?}", state);
|
log::debug!("client updated: {:?}", state);
|
||||||
@@ -625,26 +636,16 @@ impl Server {
|
|||||||
// update state in event consumer & producer
|
// update state in event consumer & producer
|
||||||
if active {
|
if active {
|
||||||
let _ = producer_notify_tx
|
let _ = producer_notify_tx
|
||||||
.send(ProducerEvent::ClientEvent(ClientEvent::Destroy(
|
.send(ProducerEvent::ClientEvent(ClientEvent::Destroy(handle)))
|
||||||
client_update.client,
|
|
||||||
)))
|
|
||||||
.await;
|
.await;
|
||||||
let _ = consumer_notify_tx
|
let _ = consumer_notify_tx
|
||||||
.send(ConsumerEvent::ClientEvent(ClientEvent::Destroy(
|
.send(ConsumerEvent::ClientEvent(ClientEvent::Destroy(handle)))
|
||||||
client_update.client,
|
|
||||||
)))
|
|
||||||
.await;
|
.await;
|
||||||
let _ = producer_notify_tx
|
let _ = producer_notify_tx
|
||||||
.send(ProducerEvent::ClientEvent(ClientEvent::Create(
|
.send(ProducerEvent::ClientEvent(ClientEvent::Create(handle, pos)))
|
||||||
client_update.client,
|
|
||||||
client_update.pos,
|
|
||||||
)))
|
|
||||||
.await;
|
.await;
|
||||||
let _ = consumer_notify_tx
|
let _ = consumer_notify_tx
|
||||||
.send(ConsumerEvent::ClientEvent(ClientEvent::Create(
|
.send(ConsumerEvent::ClientEvent(ClientEvent::Create(handle, pos)))
|
||||||
client_update.client,
|
|
||||||
client_update.pos,
|
|
||||||
)))
|
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -853,7 +854,6 @@ impl Server {
|
|||||||
|
|
||||||
async fn handle_frontend_stream(
|
async fn handle_frontend_stream(
|
||||||
&self,
|
&self,
|
||||||
frontend: &mut FrontendListener,
|
|
||||||
frontend_tx: &Sender<FrontendEvent>,
|
frontend_tx: &Sender<FrontendEvent>,
|
||||||
#[cfg(unix)] mut stream: ReadHalf<UnixStream>,
|
#[cfg(unix)] mut stream: ReadHalf<UnixStream>,
|
||||||
#[cfg(windows)] mut stream: ReadHalf<TcpStream>,
|
#[cfg(windows)] mut stream: ReadHalf<TcpStream>,
|
||||||
@@ -880,55 +880,85 @@ impl Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.enumerate(frontend).await;
|
let _ = frontend_tx.send(FrontendEvent::Enumerate()).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_frontend_event(
|
async fn handle_frontend_event(
|
||||||
&self,
|
&self,
|
||||||
producer_notify_tx: &Sender<ProducerEvent>,
|
producer_tx: &Sender<ProducerEvent>,
|
||||||
consumer_notify_tx: &Sender<ConsumerEvent>,
|
consumer_tx: &Sender<ConsumerEvent>,
|
||||||
resolve_tx: &Sender<(String, ClientHandle)>,
|
resolve_tx: &Sender<(String, ClientHandle)>,
|
||||||
frontend: &mut FrontendListener,
|
frontend: &mut FrontendListener,
|
||||||
port_tx: &Sender<u16>,
|
port_tx: &Sender<u16>,
|
||||||
event: FrontendEvent,
|
event: FrontendEvent,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
log::debug!("frontend: {event:?}");
|
log::debug!("frontend: {event:?}");
|
||||||
match event {
|
let response = match event {
|
||||||
FrontendEvent::AddClient(hostname, port, pos) => {
|
FrontendEvent::AddClient(hostname, port, pos) => {
|
||||||
self.add_client(resolve_tx, frontend, hostname, HashSet::new(), port, pos)
|
let handle = self
|
||||||
|
.add_client(resolve_tx, hostname, HashSet::new(), port, pos)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
let client = self
|
||||||
|
.client_manager
|
||||||
|
.borrow()
|
||||||
|
.get(handle)
|
||||||
|
.unwrap()
|
||||||
|
.client
|
||||||
|
.clone();
|
||||||
|
Some(FrontendNotify::NotifyClientCreate(client))
|
||||||
}
|
}
|
||||||
FrontendEvent::ActivateClient(client, active) => {
|
FrontendEvent::ActivateClient(handle, active) => {
|
||||||
self.activate_client(producer_notify_tx, consumer_notify_tx, client, active)
|
self.activate_client(producer_tx, consumer_tx, handle, active)
|
||||||
.await
|
.await;
|
||||||
|
Some(FrontendNotify::NotifyClientActivate(handle, active))
|
||||||
}
|
}
|
||||||
FrontendEvent::ChangePort(port) => {
|
FrontendEvent::ChangePort(port) => {
|
||||||
let _ = port_tx.send(port).await;
|
let _ = port_tx.send(port).await;
|
||||||
|
None
|
||||||
}
|
}
|
||||||
FrontendEvent::DelClient(client) => {
|
FrontendEvent::DelClient(handle) => {
|
||||||
self.remove_client(producer_notify_tx, consumer_notify_tx, frontend, client)
|
self.remove_client(producer_tx, consumer_tx, frontend, handle)
|
||||||
.await;
|
.await;
|
||||||
|
Some(FrontendNotify::NotifyClientDelete(handle))
|
||||||
|
}
|
||||||
|
FrontendEvent::Enumerate() => {
|
||||||
|
let clients = self
|
||||||
|
.client_manager
|
||||||
|
.borrow()
|
||||||
|
.get_client_states()
|
||||||
|
.map(|s| (s.client.clone(), s.active))
|
||||||
|
.collect();
|
||||||
|
Some(FrontendNotify::Enumerate(clients))
|
||||||
}
|
}
|
||||||
FrontendEvent::Enumerate() => self.enumerate(frontend).await,
|
|
||||||
FrontendEvent::Shutdown() => {
|
FrontendEvent::Shutdown() => {
|
||||||
log::info!("terminating gracefully...");
|
log::info!("terminating gracefully...");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
FrontendEvent::UpdateClient(client, hostname, port, pos) => {
|
FrontendEvent::UpdateClient(handle, hostname, port, pos) => {
|
||||||
let client_update = ClientUpdate {
|
|
||||||
client,
|
|
||||||
hostname,
|
|
||||||
port,
|
|
||||||
pos,
|
|
||||||
};
|
|
||||||
self.update_client(
|
self.update_client(
|
||||||
producer_notify_tx,
|
producer_tx,
|
||||||
consumer_notify_tx,
|
consumer_tx,
|
||||||
resolve_tx,
|
resolve_tx,
|
||||||
client_update,
|
(handle, hostname, port, pos),
|
||||||
)
|
)
|
||||||
.await
|
.await;
|
||||||
|
|
||||||
|
let client = self
|
||||||
|
.client_manager
|
||||||
|
.borrow()
|
||||||
|
.get(handle)
|
||||||
|
.unwrap()
|
||||||
|
.client
|
||||||
|
.clone();
|
||||||
|
Some(FrontendNotify::NotifyClientUpdate(client))
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
let Some(response) = response else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
if let Err(e) = frontend.notify_all(response).await {
|
||||||
|
log::error!("error notifying frontend: {e}");
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@@ -964,21 +994,6 @@ impl Server {
|
|||||||
.consume(Event::Keyboard(modifiers_event), client)
|
.consume(Event::Keyboard(modifiers_event), client)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn enumerate(&self, frontend: &mut FrontendListener) {
|
|
||||||
let clients = self
|
|
||||||
.client_manager
|
|
||||||
.borrow()
|
|
||||||
.get_client_states()
|
|
||||||
.map(|s| (s.client.clone(), s.active))
|
|
||||||
.collect();
|
|
||||||
if let Err(e) = frontend
|
|
||||||
.notify_all(FrontendNotify::Enumerate(clients))
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
log::error!("error notifying frontend: {e}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn receive_event(socket: &UdpSocket) -> anyhow::Result<(Event, SocketAddr)> {
|
async fn receive_event(socket: &UdpSocket) -> anyhow::Result<(Event, SocketAddr)> {
|
||||||
|
|||||||
Reference in New Issue
Block a user