diff --git a/Cargo.toml b/Cargo.toml index c7f6200..f380968 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ description = "A wip universal Linux settings application." [dependencies] reset_daemon = "0.3.3" -ReSet-Lib = "0.4.9" +ReSet-Lib = "0.5.4" adw = { version = "0.5.3", package = "libadwaita", features = ["v1_4"] } dbus = "0.9.7" gtk = { version = "0.7.3", package = "gtk4", features = ["v4_12"] } diff --git a/src/components/bluetooth/bluetoothBox.rs b/src/components/bluetooth/bluetoothBox.rs index d493847..bcc6342 100644 --- a/src/components/bluetooth/bluetoothBox.rs +++ b/src/components/bluetooth/bluetoothBox.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::sync::atomic::Ordering; use std::sync::Arc; use std::thread; @@ -12,6 +13,7 @@ use dbus::{Error, Path}; use gtk::gio; use gtk::glib::Variant; use gtk::prelude::{ActionableExt, ListBoxRowExt}; +use ReSet_Lib::bluetooth::bluetooth::BluetoothDevice; use ReSet_Lib::signals::{BluetoothDeviceAdded, BluetoothDeviceRemoved}; use crate::components::base::listEntry::ListEntry; @@ -48,50 +50,33 @@ impl BluetoothBox { .resetBluetoothMainTab .set_action_name(Some("navigation.pop")); } +} - pub fn scanForDevices(&self) { - // let selfImp = self.imp(); - // let mut wifiEntries = selfImp.availableDevices.borrow_mut(); - // wifiEntries.push(ListEntry::new(&BluetoothEntry::new( - // DeviceTypes::Mouse, - // "ina mouse", - // ))); - // wifiEntries.push(ListEntry::new(&BluetoothEntry::new( - // DeviceTypes::Keyboard, - // "inaboard", - // ))); - // wifiEntries.push(ListEntry::new(&BluetoothEntry::new( - // DeviceTypes::Controller, - // "ina controller", - // ))); - // wifiEntries.push( - // ListEntry::new(&BluetoothEntry::new( - // DeviceTypes::Controller, - // "ina best waifu", - // )) - // ); - // - // for wifiEntry in wifiEntries.iter() { - // selfImp.resetBluetoothAvailableDevices.append(wifiEntry); - // } - } +pub fn populate_conntected_bluetooth_devices(bluetooth_box: Arc) { + gio::spawn_blocking(move || { + let ref_box = bluetooth_box.clone(); + let devices = get_connected_devices(); - pub fn addConnectedDevices(&self) { - // let selfImp = self.imp(); - // let mut wifiEntries = selfImp.connectedDevices.borrow_mut(); - // wifiEntries.push(ListEntry::new(&BluetoothEntry::new( - // DeviceTypes::Mouse, - // "why are we still here?", - // ))); - // wifiEntries.push(ListEntry::new(&BluetoothEntry::new( - // DeviceTypes::Keyboard, - // "just to suffer?", - // ))); - // - // for wifiEntry in wifiEntries.iter() { - // selfImp.resetBluetoothConnectedDevices.append(wifiEntry); - // } - } + glib::spawn_future(async move { + glib::idle_add_once(move || { + let imp = ref_box.imp(); + for device in devices { + let path = device.path.clone(); + let connected = device.connected; + let bluetooth_entry = Arc::new(BluetoothEntry::new(device)); + let entry = Arc::new(ListEntry::new(&*bluetooth_entry)); + imp.availableDevices + .borrow_mut() + .insert(path, (bluetooth_entry.clone(), entry.clone())); + if connected { + imp.resetBluetoothConnectedDevices.append(&*entry); + } else { + imp.resetBluetoothAvailableDevices.append(&*entry); + } + } + }); + }); + }); } pub fn start_bluetooth_listener(listeners: Arc, bluetooth_box: Arc) { @@ -110,7 +95,7 @@ pub fn start_bluetooth_listener(listeners: Arc, bluetooth_box: Arc, bluetooth_box: Arc, bluetooth_box: Arc, bluetooth_box: Arc, bluetooth_box: Arc Duration::from_millis(5000) + || time.elapsed().unwrap() > Duration::from_millis(25000) { glib::spawn_future(async move { glib::idle_add_once(move || { let imp = loop_box.imp(); - imp.resetBluetoothConnectedDevices.remove_all(); + imp.resetBluetoothAvailableDevices.remove_all(); }); }); println!("stopping bluetooth listener"); @@ -191,3 +184,21 @@ pub fn start_bluetooth_listener(listeners: Arc, bluetooth_box: Arc Vec { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy( + "org.Xetibo.ReSetDaemon", + "/org/Xetibo/ReSetDaemon", + Duration::from_millis(1000), + ); + let res: Result<(Vec,), Error> = proxy.method_call( + "org.Xetibo.ReSetBluetooth", + "GetConnectedBluetoothDevices", + (), + ); + if res.is_err() { + return Vec::new(); + } + res.unwrap().0 +} diff --git a/src/components/bluetooth/bluetoothBoxImpl.rs b/src/components/bluetooth/bluetoothBoxImpl.rs index a718625..55cbd30 100644 --- a/src/components/bluetooth/bluetoothBoxImpl.rs +++ b/src/components/bluetooth/bluetoothBoxImpl.rs @@ -52,8 +52,6 @@ impl ObjectImpl for BluetoothBox { self.parent_constructed(); let obj = self.obj(); obj.setupCallbacks(); - obj.scanForDevices(); - obj.addConnectedDevices(); } } diff --git a/src/components/bluetooth/bluetoothEntry.rs b/src/components/bluetooth/bluetoothEntry.rs index 924f126..718e2c1 100644 --- a/src/components/bluetooth/bluetoothEntry.rs +++ b/src/components/bluetooth/bluetoothEntry.rs @@ -1,3 +1,5 @@ +use std::rc::Rc; +use std::sync::Arc; use std::time::Duration; use crate::components::bluetooth::bluetoothEntryImpl; @@ -8,7 +10,7 @@ use adw::subclass::prelude::ObjectSubclassIsExt; use dbus::blocking::Connection; use dbus::{Error, Path}; use glib::clone; -use gtk::prelude::WidgetExt; +use gtk::prelude::{ButtonExt, WidgetExt}; use gtk::{gio, GestureClick}; use ReSet_Lib::bluetooth::bluetooth::BluetoothDevice; @@ -23,10 +25,7 @@ impl BluetoothEntry { let entry: BluetoothEntry = Object::builder().build(); let entryImp = entry.imp(); entryImp.resetBluetoothLabel.get().set_text(&device.name); - entryImp - .resetBluetoothAddress - .get() - .set_text(&device.address); + entryImp.resetBluetoothAddress.get().set_text(&device.alias); // entryImp // .resetBluetoothDeviceType // .get() @@ -37,9 +36,17 @@ impl BluetoothEntry { // DeviceTypes::Controller => Some("input-gaming-symbolic"), // DeviceTypes::None => Some("text-x-generic-symbolic"), // no generic bluetooth device icon found // }); + if device.paired { + entryImp.resetBluetoothButton.set_sensitive(true); + } else { + entryImp.resetBluetoothButton.set_sensitive(false); + } + let path = Arc::new(device.path.clone()); + entryImp.resetBluetoothButton.connect_clicked(move |_| { + remove_device_pairing((*path).clone()); + }); let gesture = GestureClick::new(); - let connected = false; - // TODO implement this connected + let connected = device.connected; entryImp.device.replace(device); gesture.connect_released(clone!(@weak entryImp => move |_, _, _, _| { let device = entryImp.device.borrow_mut(); @@ -48,7 +55,7 @@ impl BluetoothEntry { } else if device.paired { connect_to_device(device.path.clone()); } else { - pair_with_device(device.path.clone()); + pair_with_device(device.path.clone()); } })); entry.add_controller(gesture); @@ -64,8 +71,11 @@ fn connect_to_device(path: Path<'static>) { "/org/Xetibo/ReSetDaemon", Duration::from_millis(1000), ); - let _: Result<(bool,), Error> = - proxy.method_call("org.Xetibo.ReSetBluetooth", "ConnectToBluetoothDevice", (path,)); + let _: Result<(bool,), Error> = proxy.method_call( + "org.Xetibo.ReSetBluetooth", + "ConnectToBluetoothDevice", + (path,), + ); }); } @@ -77,8 +87,11 @@ fn pair_with_device(path: Path<'static>) { "/org/Xetibo/ReSetDaemon", Duration::from_millis(1000), ); - let _: Result<(bool,), Error> = - proxy.method_call("org.Xetibo.ReSetBluetooth", "PairWithBluetoothDevice", (path,)); + let _: Result<(bool,), Error> = proxy.method_call( + "org.Xetibo.ReSetBluetooth", + "PairWithBluetoothDevice", + (path,), + ); }); } @@ -90,7 +103,23 @@ fn disconnect_from_device(path: Path<'static>) { "/org/Xetibo/ReSetDaemon", Duration::from_millis(1000), ); - let _: Result<(bool,), Error> = - proxy.method_call("org.Xetibo.ReSetBluetooth", "DisconnectFromBluetoothDevice", (path,)); + let _: Result<(bool,), Error> = proxy.method_call( + "org.Xetibo.ReSetBluetooth", + "DisconnectFromBluetoothDevice", + (path,), + ); + }); +} + +fn remove_device_pairing(path: Path<'static>) { + gio::spawn_blocking(move || { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy( + "org.Xetibo.ReSetDaemon", + "/org/Xetibo/ReSetDaemon", + Duration::from_millis(1000), + ); + let _: Result<(bool,), Error> = + proxy.method_call("org.Xetibo.ReSetBluetooth", "RemoveDevicePairing", (path,)); }); } diff --git a/src/components/window/handleSidebarClick.rs b/src/components/window/handleSidebarClick.rs index 292ad90..7ad3183 100644 --- a/src/components/window/handleSidebarClick.rs +++ b/src/components/window/handleSidebarClick.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use crate::components::base::settingBox::SettingBox; use crate::components::base::utils::{start_audio_listener, Listeners}; -use crate::components::bluetooth::bluetoothBox::{start_bluetooth_listener, BluetoothBox}; +use crate::components::bluetooth::bluetoothBox::{start_bluetooth_listener, BluetoothBox, populate_conntected_bluetooth_devices}; use crate::components::input::sourceBox::{populate_sources, SourceBox}; use crate::components::output::sinkBox::{populate_sinks, SinkBox}; use crate::components::wifi::wifiBox::{ @@ -22,6 +22,7 @@ pub const HANDLE_CONNECTIVITY_CLICK: fn(Arc, FlowBox) = scanForWifi(listeners.clone(), wifiBox.clone()); let wifiFrame = wrapInFrame(SettingBox::new(&*wifiBox)); let bluetooth_box = Arc::new(BluetoothBox::new()); + populate_conntected_bluetooth_devices(bluetooth_box.clone()); start_bluetooth_listener(listeners.clone(), bluetooth_box.clone()); let bluetoothFrame = wrapInFrame(SettingBox::new(&*bluetooth_box)); resetMain.remove_all(); @@ -50,6 +51,7 @@ pub const HANDLE_BLUETOOTH_CLICK: fn(Arc, FlowBox) = listeners.stop_audio_listener(); let bluetooth_box = Arc::new(BluetoothBox::new()); start_bluetooth_listener(listeners.clone(), bluetooth_box.clone()); + populate_conntected_bluetooth_devices(bluetooth_box.clone()); let bluetoothFrame = wrapInFrame(SettingBox::new(&*bluetooth_box)); resetMain.remove_all(); resetMain.insert(&bluetoothFrame, -1); diff --git a/src/main.rs b/src/main.rs index f5c6c4a..69cc7a1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -34,6 +34,7 @@ async fn main() { }); app.connect_activate(buildUI); + app.connect_shutdown(shutdown); app.run(); } @@ -54,6 +55,19 @@ fn buildUI(app: &Application) { window.present(); } +fn shutdown(_: &Application) { + thread::spawn(|| { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy( + "org.Xetibo.ReSetDaemon", + "/org/Xetibo/ReSetDaemon", + Duration::from_millis(100), + ); + let res: Result<(), Error> = proxy.method_call("org.Xetibo.ReSetDaemon", "UnregisterClient", ("ReSet",)); + res + }); +} + async fn daemon_check() { let handle = thread::spawn(|| { let conn = Connection::new_session().unwrap(); @@ -62,7 +76,7 @@ async fn daemon_check() { "/org/Xetibo/ReSetDaemon", Duration::from_millis(100), ); - let res: Result<(), Error> = proxy.method_call("org.Xetibo.ReSetDaemon", "Check", ()); + let res: Result<(), Error> = proxy.method_call("org.Xetibo.ReSetDaemon", "RegisterClient", ("ReSet",)); res }); let res = handle.join(); diff --git a/src/resources/resetBluetoothEntry.ui b/src/resources/resetBluetoothEntry.ui index 6f50c07..fa705b8 100644 --- a/src/resources/resetBluetoothEntry.ui +++ b/src/resources/resetBluetoothEntry.ui @@ -44,7 +44,7 @@ False - emblem-system-symbolic + user-trash-symbolic diff --git a/src/resources/resetUI.cmb b/src/resources/resetUI.cmb index 2a325c1..65ef1bd 100644 --- a/src/resources/resetUI.cmb +++ b/src/resources/resetUI.cmb @@ -165,9 +165,9 @@ (11,2,"GtkBox","resetBluetoothEntry",None,None,None,None,None,None), (11,3,"GtkImage","resetBluetoothDeviceType",2,None,None,None,None,None), (11,5,"GtkButton","resetBluetoothButton",2,None,None,None,3,None), - (11,6,"GtkBox",None,2,None,None,None,2,None), + (11,6,"GtkBox",None,2,None,None,None,1,None), (11,7,"GtkLabel","resetBluetoothLabel",6,None,None,None,None,None), - (11,8,"GtkLabel","resetBluetoothAddress",6,None,None,None,1,None), + (11,8,"GtkLabel","resetBluetoothAddress",6,None,None,None,2,None), (12,11,"GtkBox","resetAudioInput",None,None,None,None,None,None), (12,12,"GtkLabel",None,11,None,None,None,None,None), (12,13,"AdwNavigationView",None,11,None,None,None,1,None), @@ -598,7 +598,7 @@ (11,3,"GtkImage","icon-name","input-mouse-symbolic",None,None,None,None,None,None,None,None,None), (11,3,"GtkWidget","margin-end","15",None,None,None,None,None,None,None,None,None), (11,5,"GtkButton","has-frame","False",None,None,None,None,None,None,None,None,None), - (11,5,"GtkButton","icon-name","emblem-system-symbolic",None,None,None,None,None,None,None,None,None), + (11,5,"GtkButton","icon-name","user-trash-symbolic",None,None,None,None,None,None,None,None,None), (11,6,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None), (11,7,"GtkLabel","ellipsize","end",None,None,None,None,None,None,None,None,None), (11,7,"GtkLabel","label","LoremIpsum Wireless Mouse",None,None,None,None,None,None,None,None,None),