mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-03-30 16:40:52 +03:00
formatting
This commit is contained in:
@@ -1,12 +1,16 @@
|
||||
use anyhow::{anyhow, Result, Context};
|
||||
use std::{thread, io::{Write, Read, ErrorKind}, str::SplitWhitespace};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
#[cfg(windows)]
|
||||
use std::net::SocketAddrV4;
|
||||
use std::{
|
||||
io::{ErrorKind, Read, Write},
|
||||
str::SplitWhitespace,
|
||||
thread,
|
||||
};
|
||||
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::net::UnixStream;
|
||||
#[cfg(windows)]
|
||||
use std::net::TcpStream;
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::net::UnixStream;
|
||||
|
||||
use crate::{client::Position, config::DEFAULT_PORT};
|
||||
|
||||
@@ -31,40 +35,40 @@ pub fn run() -> Result<()> {
|
||||
let reader = thread::Builder::new()
|
||||
.name("cli-frontend".to_string())
|
||||
.spawn(move || {
|
||||
// all further prompts
|
||||
prompt();
|
||||
loop {
|
||||
let mut buf = String::new();
|
||||
match std::io::stdin().read_line(&mut buf) {
|
||||
Ok(0) => break,
|
||||
Ok(len) => {
|
||||
if let Some(events) = parse_cmd(buf, len) {
|
||||
for event in events.iter() {
|
||||
let json = serde_json::to_string(&event).unwrap();
|
||||
let bytes = json.as_bytes();
|
||||
let len = bytes.len().to_be_bytes();
|
||||
if let Err(e) = tx.write(&len) {
|
||||
log::error!("error sending message: {e}");
|
||||
};
|
||||
if let Err(e) = tx.write(bytes) {
|
||||
log::error!("error sending message: {e}");
|
||||
};
|
||||
if *event == FrontendEvent::Shutdown() {
|
||||
return;
|
||||
// all further prompts
|
||||
prompt();
|
||||
loop {
|
||||
let mut buf = String::new();
|
||||
match std::io::stdin().read_line(&mut buf) {
|
||||
Ok(0) => break,
|
||||
Ok(len) => {
|
||||
if let Some(events) = parse_cmd(buf, len) {
|
||||
for event in events.iter() {
|
||||
let json = serde_json::to_string(&event).unwrap();
|
||||
let bytes = json.as_bytes();
|
||||
let len = bytes.len().to_be_bytes();
|
||||
if let Err(e) = tx.write(&len) {
|
||||
log::error!("error sending message: {e}");
|
||||
};
|
||||
if let Err(e) = tx.write(bytes) {
|
||||
log::error!("error sending message: {e}");
|
||||
};
|
||||
if *event == FrontendEvent::Shutdown() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// prompt is printed after the server response is received
|
||||
} else {
|
||||
prompt();
|
||||
}
|
||||
// prompt is printed after the server response is received
|
||||
} else {
|
||||
prompt();
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("error reading from stdin: {e}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("error reading from stdin: {e}");
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
})?;
|
||||
})?;
|
||||
|
||||
let writer = thread::Builder::new()
|
||||
.name("cli-frontend-notify".to_string())
|
||||
@@ -93,35 +97,43 @@ pub fn run() -> Result<()> {
|
||||
};
|
||||
match notify {
|
||||
FrontendNotify::NotifyClientCreate(client, host, port, pos) => {
|
||||
log::info!("new client ({client}): {}:{port} - {pos}", host.as_deref().unwrap_or(""));
|
||||
},
|
||||
log::info!(
|
||||
"new client ({client}): {}:{port} - {pos}",
|
||||
host.as_deref().unwrap_or("")
|
||||
);
|
||||
}
|
||||
FrontendNotify::NotifyClientUpdate(client, host, port, pos) => {
|
||||
log::info!("client ({client}) updated: {}:{port} - {pos}", host.as_deref().unwrap_or(""));
|
||||
},
|
||||
log::info!(
|
||||
"client ({client}) updated: {}:{port} - {pos}",
|
||||
host.as_deref().unwrap_or("")
|
||||
);
|
||||
}
|
||||
FrontendNotify::NotifyClientDelete(client) => {
|
||||
log::info!("client ({client}) deleted.");
|
||||
},
|
||||
}
|
||||
FrontendNotify::NotifyError(e) => {
|
||||
log::warn!("{e}");
|
||||
},
|
||||
}
|
||||
FrontendNotify::Enumerate(clients) => {
|
||||
for (client, active) in clients.into_iter() {
|
||||
log::info!("client ({}) [{}]: active: {}, associated addresses: [{}]",
|
||||
log::info!(
|
||||
"client ({}) [{}]: active: {}, associated addresses: [{}]",
|
||||
client.handle,
|
||||
client.hostname.as_deref().unwrap_or(""),
|
||||
if active { "yes" } else { "no" },
|
||||
client.addrs.into_iter().map(|a| a.to_string())
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ")
|
||||
client
|
||||
.addrs
|
||||
.into_iter()
|
||||
.map(|a| a.to_string())
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ")
|
||||
);
|
||||
}
|
||||
},
|
||||
FrontendNotify::NotifyPortChange(port, msg) => {
|
||||
match msg {
|
||||
Some(msg) => log::info!("could not change port: {msg}"),
|
||||
None => log::info!("port changed: {port}"),
|
||||
}
|
||||
}
|
||||
FrontendNotify::NotifyPortChange(port, msg) => match msg {
|
||||
Some(msg) => log::info!("could not change port: {msg}"),
|
||||
None => log::info!("port changed: {port}"),
|
||||
},
|
||||
}
|
||||
prompt();
|
||||
}
|
||||
@@ -132,10 +144,10 @@ pub fn run() -> Result<()> {
|
||||
let msg = match (e.downcast_ref::<&str>(), e.downcast_ref::<String>()) {
|
||||
(Some(&s), _) => s,
|
||||
(_, Some(s)) => s,
|
||||
_ => "no panic info"
|
||||
_ => "no panic info",
|
||||
};
|
||||
log::error!("reader thread paniced: {msg}");
|
||||
},
|
||||
}
|
||||
}
|
||||
match writer.join() {
|
||||
Ok(_) => (),
|
||||
@@ -143,10 +155,10 @@ pub fn run() -> Result<()> {
|
||||
let msg = match (e.downcast_ref::<&str>(), e.downcast_ref::<String>()) {
|
||||
(Some(&s), _) => s,
|
||||
(_, Some(s)) => s,
|
||||
_ => "no panic info"
|
||||
_ => "no panic info",
|
||||
};
|
||||
log::error!("writer thread paniced: {msg}");
|
||||
},
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -158,7 +170,7 @@ fn prompt() {
|
||||
|
||||
fn parse_cmd(s: String, len: usize) -> Option<Vec<FrontendEvent>> {
|
||||
if len == 0 {
|
||||
return Some(vec![FrontendEvent::Shutdown()])
|
||||
return Some(vec![FrontendEvent::Shutdown()]);
|
||||
}
|
||||
let mut l = s.split_whitespace();
|
||||
let cmd = l.next()?;
|
||||
@@ -191,7 +203,7 @@ fn parse_cmd(s: String, len: usize) -> Option<Vec<FrontendEvent>> {
|
||||
log::warn!("{e}");
|
||||
None
|
||||
}
|
||||
_ => None
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,22 +221,34 @@ fn parse_connect(mut l: SplitWhitespace) -> Result<Vec<FrontendEvent>> {
|
||||
} else {
|
||||
DEFAULT_PORT
|
||||
};
|
||||
Ok(vec![FrontendEvent::AddClient(Some(host), port, pos), FrontendEvent::Enumerate()])
|
||||
Ok(vec![
|
||||
FrontendEvent::AddClient(Some(host), port, pos),
|
||||
FrontendEvent::Enumerate(),
|
||||
])
|
||||
}
|
||||
|
||||
fn parse_disconnect(mut l: SplitWhitespace) -> Result<Vec<FrontendEvent>> {
|
||||
let client = l.next().context("usage: disconnect <client_id>")?.parse()?;
|
||||
Ok(vec![FrontendEvent::DelClient(client), FrontendEvent::Enumerate()])
|
||||
Ok(vec![
|
||||
FrontendEvent::DelClient(client),
|
||||
FrontendEvent::Enumerate(),
|
||||
])
|
||||
}
|
||||
|
||||
fn parse_activate(mut l: SplitWhitespace) -> Result<Vec<FrontendEvent>> {
|
||||
let client = l.next().context("usage: activate <client_id>")?.parse()?;
|
||||
Ok(vec![FrontendEvent::ActivateClient(client, true), FrontendEvent::Enumerate()])
|
||||
Ok(vec![
|
||||
FrontendEvent::ActivateClient(client, true),
|
||||
FrontendEvent::Enumerate(),
|
||||
])
|
||||
}
|
||||
|
||||
fn parse_deactivate(mut l: SplitWhitespace) -> Result<Vec<FrontendEvent>> {
|
||||
let client = l.next().context("usage: deactivate <client_id>")?.parse()?;
|
||||
Ok(vec![FrontendEvent::ActivateClient(client, false), FrontendEvent::Enumerate()])
|
||||
Ok(vec![
|
||||
FrontendEvent::ActivateClient(client, false),
|
||||
FrontendEvent::Enumerate(),
|
||||
])
|
||||
}
|
||||
|
||||
fn parse_port(mut l: SplitWhitespace) -> Result<Vec<FrontendEvent>> {
|
||||
|
||||
@@ -1,13 +1,24 @@
|
||||
mod window;
|
||||
mod client_object;
|
||||
mod client_row;
|
||||
mod window;
|
||||
|
||||
use std::{io::{Read, ErrorKind}, env, process, str};
|
||||
use std::{
|
||||
env,
|
||||
io::{ErrorKind, Read},
|
||||
process, str,
|
||||
};
|
||||
|
||||
use crate::{frontend::gtk::window::Window, config::DEFAULT_PORT};
|
||||
use crate::{config::DEFAULT_PORT, frontend::gtk::window::Window};
|
||||
|
||||
use gtk::{prelude::*, IconTheme, gdk::Display, gio::{SimpleAction, SimpleActionGroup}, glib::{clone, MainContext, Priority}, CssProvider, subclass::prelude::ObjectSubclassIsExt};
|
||||
use adw::Application;
|
||||
use gtk::{
|
||||
gdk::Display,
|
||||
gio::{SimpleAction, SimpleActionGroup},
|
||||
glib::{clone, MainContext, Priority},
|
||||
prelude::*,
|
||||
subclass::prelude::ObjectSubclassIsExt,
|
||||
CssProvider, IconTheme,
|
||||
};
|
||||
use gtk::{gio, glib, prelude::ApplicationExt};
|
||||
|
||||
use self::client_object::ClientObject;
|
||||
@@ -22,8 +33,7 @@ pub fn run() -> glib::ExitCode {
|
||||
}
|
||||
|
||||
fn gtk_main() -> glib::ExitCode {
|
||||
gio::resources_register_include!("lan-mouse.gresource")
|
||||
.expect("Failed to register resources.");
|
||||
gio::resources_register_include!("lan-mouse.gresource").expect("Failed to register resources.");
|
||||
|
||||
let app = Application::builder()
|
||||
.application_id("de.feschber.lan-mouse")
|
||||
@@ -41,14 +51,15 @@ fn load_css() {
|
||||
let provider = CssProvider::new();
|
||||
provider.load_from_resource("de/feschber/LanMouse/style.css");
|
||||
gtk::style_context_add_provider_for_display(
|
||||
&Display::default().expect("Could not connect to a display."),
|
||||
&Display::default().expect("Could not connect to a display."),
|
||||
&provider,
|
||||
gtk::STYLE_PROVIDER_PRIORITY_APPLICATION,
|
||||
);
|
||||
}
|
||||
|
||||
fn load_icons() {
|
||||
let icon_theme = IconTheme::for_display(&Display::default().expect("Could not connect to a display."));
|
||||
let icon_theme =
|
||||
IconTheme::for_display(&Display::default().expect("Could not connect to a display."));
|
||||
icon_theme.add_resource_path("/de/feschber/LanMouse/icons");
|
||||
}
|
||||
|
||||
@@ -69,7 +80,7 @@ fn build_ui(app: &Application) {
|
||||
}
|
||||
};
|
||||
log::debug!("connected to lan-mouse-socket");
|
||||
|
||||
|
||||
let (sender, receiver) = MainContext::channel::<FrontendNotify>(Priority::default());
|
||||
|
||||
gio::spawn_blocking(move || {
|
||||
@@ -92,14 +103,13 @@ fn build_ui(app: &Application) {
|
||||
};
|
||||
|
||||
// parse json
|
||||
let json = str::from_utf8(&buf)
|
||||
.unwrap();
|
||||
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(()) => {},
|
||||
Ok(()) => {}
|
||||
Err(e) => log::error!("{e}"),
|
||||
}
|
||||
});
|
||||
@@ -152,16 +162,12 @@ fn build_ui(app: &Application) {
|
||||
}
|
||||
));
|
||||
|
||||
let action_request_client_update = SimpleAction::new(
|
||||
"request-client-update",
|
||||
Some(&u32::static_variant_type()),
|
||||
);
|
||||
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()),
|
||||
);
|
||||
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| {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
mod imp;
|
||||
|
||||
use gtk::glib::{self, Object};
|
||||
use adw::subclass::prelude::*;
|
||||
use gtk::glib::{self, Object};
|
||||
|
||||
use crate::client::ClientHandle;
|
||||
|
||||
@@ -10,7 +10,13 @@ glib::wrapper! {
|
||||
}
|
||||
|
||||
impl ClientObject {
|
||||
pub fn new(handle: ClientHandle, hostname: Option<String>, port: u32, position: String, active: bool) -> Self {
|
||||
pub fn new(
|
||||
handle: ClientHandle,
|
||||
hostname: Option<String>,
|
||||
port: u32,
|
||||
position: String,
|
||||
active: bool,
|
||||
) -> Self {
|
||||
Object::builder()
|
||||
.property("handle", handle)
|
||||
.property("hostname", hostname)
|
||||
|
||||
@@ -16,8 +16,7 @@ glib::wrapper! {
|
||||
|
||||
impl ClientRow {
|
||||
pub fn new(_client_object: &ClientObject) -> Self {
|
||||
Object::builder()
|
||||
.build()
|
||||
Object::builder().build()
|
||||
}
|
||||
|
||||
pub fn bind(&self, client_object: &ClientObject) {
|
||||
@@ -86,24 +85,19 @@ impl ClientRow {
|
||||
.sync_create()
|
||||
.build();
|
||||
|
||||
|
||||
let position_binding = client_object
|
||||
.bind_property("position", &self.imp().position.get(), "selected")
|
||||
.transform_from(|_, v: u32| {
|
||||
match v {
|
||||
1 => Some("right"),
|
||||
2 => Some("top"),
|
||||
3 => Some("bottom"),
|
||||
_ => Some("left"),
|
||||
}
|
||||
.transform_from(|_, v: u32| match v {
|
||||
1 => Some("right"),
|
||||
2 => Some("top"),
|
||||
3 => Some("bottom"),
|
||||
_ => Some("left"),
|
||||
})
|
||||
.transform_to(|_, v: String| {
|
||||
match v.as_str() {
|
||||
"right" => Some(1),
|
||||
"top" => Some(2u32),
|
||||
"bottom" => Some(3u32),
|
||||
_ => Some(0u32),
|
||||
}
|
||||
.transform_to(|_, v: String| match v.as_str() {
|
||||
"right" => Some(1),
|
||||
"top" => Some(2u32),
|
||||
"bottom" => Some(3u32),
|
||||
_ => Some(0u32),
|
||||
})
|
||||
.bidirectional()
|
||||
.sync_create()
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use std::cell::RefCell;
|
||||
|
||||
use glib::{Binding, subclass::InitializingObject};
|
||||
use adw::{prelude::*, ComboRow, ActionRow};
|
||||
use adw::subclass::prelude::*;
|
||||
use adw::{prelude::*, ActionRow, ComboRow};
|
||||
use glib::{subclass::InitializingObject, Binding};
|
||||
use gtk::glib::clone;
|
||||
use gtk::{glib, CompositeTemplate, Switch, Button};
|
||||
use gtk::{glib, Button, CompositeTemplate, Switch};
|
||||
|
||||
#[derive(CompositeTemplate, Default)]
|
||||
#[template(resource = "/de/feschber/LanMouse/client_row.ui")]
|
||||
@@ -44,9 +44,10 @@ impl ObjectSubclass for ClientRow {
|
||||
impl ObjectImpl for ClientRow {
|
||||
fn constructed(&self) {
|
||||
self.parent_constructed();
|
||||
self.delete_button.connect_clicked(clone!(@weak self as row => move |button| {
|
||||
row.handle_client_delete(button);
|
||||
}));
|
||||
self.delete_button
|
||||
.connect_clicked(clone!(@weak self as row => move |button| {
|
||||
row.handle_client_delete(button);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +56,9 @@ impl ClientRow {
|
||||
#[template_callback]
|
||||
fn handle_client_set_state(&self, state: bool, switch: &Switch) -> bool {
|
||||
let idx = self.obj().index() as u32;
|
||||
switch.activate_action("win.request-client-update", Some(&idx.to_variant())).unwrap();
|
||||
switch
|
||||
.activate_action("win.request-client-update", Some(&idx.to_variant()))
|
||||
.unwrap();
|
||||
switch.set_state(state);
|
||||
|
||||
true // dont run default handler
|
||||
|
||||
@@ -4,10 +4,14 @@ use std::io::Write;
|
||||
|
||||
use adw::prelude::*;
|
||||
use adw::subclass::prelude::*;
|
||||
use gtk::{glib, gio, NoSelection};
|
||||
use glib::{clone, Object};
|
||||
use gtk::{gio, glib, NoSelection};
|
||||
|
||||
use crate::{frontend::{gtk::client_object::ClientObject, FrontendEvent}, client::{Position, ClientHandle}, config::DEFAULT_PORT};
|
||||
use crate::{
|
||||
client::{ClientHandle, Position},
|
||||
config::DEFAULT_PORT,
|
||||
frontend::{gtk::client_object::ClientObject, FrontendEvent},
|
||||
};
|
||||
|
||||
use super::client_row::ClientRow;
|
||||
|
||||
@@ -67,7 +71,14 @@ impl Window {
|
||||
row
|
||||
}
|
||||
|
||||
pub fn new_client(&self, handle: ClientHandle, hostname: Option<String>, port: u16, position: Position, active: bool) {
|
||||
pub fn new_client(
|
||||
&self,
|
||||
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.set_placeholder_visible(false);
|
||||
@@ -122,7 +133,7 @@ impl Window {
|
||||
"bottom" => Position::Bottom,
|
||||
_ => {
|
||||
log::error!("invalid position: {}", data.position);
|
||||
return
|
||||
return;
|
||||
}
|
||||
};
|
||||
let hostname = data.hostname;
|
||||
@@ -133,7 +144,7 @@ impl Window {
|
||||
let event = FrontendEvent::ActivateClient(client.handle(), !client.active());
|
||||
self.request(event);
|
||||
}
|
||||
|
||||
|
||||
pub fn request_client_delete(&self, idx: u32) {
|
||||
if let Some(obj) = self.clients().item(idx) {
|
||||
let client_object: &ClientObject = obj
|
||||
@@ -145,7 +156,7 @@ impl Window {
|
||||
}
|
||||
}
|
||||
|
||||
fn request(&self, event: FrontendEvent) {
|
||||
fn request(&self, event: FrontendEvent) {
|
||||
let json = serde_json::to_string(&event).unwrap();
|
||||
log::debug!("requesting {json}");
|
||||
let mut stream = self.imp().stream.borrow_mut();
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
use std::{cell::{Cell, RefCell}, os::unix::net::UnixStream};
|
||||
use std::{
|
||||
cell::{Cell, RefCell},
|
||||
os::unix::net::UnixStream,
|
||||
};
|
||||
|
||||
use glib::subclass::InitializingObject;
|
||||
use adw::{ActionRow, ToastOverlay, prelude::{WidgetExt, EditableExt}};
|
||||
use adw::subclass::prelude::*;
|
||||
use gtk::{glib, Button, CompositeTemplate, ListBox, gio, Entry};
|
||||
use adw::{
|
||||
prelude::{EditableExt, WidgetExt},
|
||||
ActionRow, ToastOverlay,
|
||||
};
|
||||
use glib::subclass::InitializingObject;
|
||||
use gtk::{gio, glib, Button, CompositeTemplate, Entry, ListBox};
|
||||
|
||||
use crate::config::DEFAULT_PORT;
|
||||
|
||||
@@ -65,7 +71,8 @@ impl Window {
|
||||
#[template_callback]
|
||||
fn handle_port_edit_cancel(&self) {
|
||||
log::debug!("cancel port edit");
|
||||
self.port_entry.set_text(self.port.get().to_string().as_str());
|
||||
self.port_entry
|
||||
.set_text(self.port.get().to_string().as_str());
|
||||
self.port_edit_apply.set_visible(false);
|
||||
self.port_edit_cancel.set_visible(false);
|
||||
}
|
||||
@@ -82,7 +89,6 @@ impl Window {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl ObjectImpl for Window {
|
||||
fn constructed(&self) {
|
||||
self.parent_constructed();
|
||||
|
||||
Reference in New Issue
Block a user