diff --git a/Cargo.toml b/Cargo.toml index 233b102..dbee372 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" description = "A wip universal Linux settings application." [dependencies] -reset_daemon = "0.3.7" -ReSet-Lib = "0.6.2" +reset_daemon = "0.3.8" +ReSet-Lib = "0.6.3" 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/bluetooth_box.rs b/src/components/bluetooth/bluetooth_box.rs index ccc83fb..f5b1780 100644 --- a/src/components/bluetooth/bluetooth_box.rs +++ b/src/components/bluetooth/bluetooth_box.rs @@ -12,7 +12,7 @@ use dbus::message::SignalArgs; use dbus::{Error, Path}; use glib::{clone, Cast}; use gtk::glib::Variant; -use gtk::prelude::{ActionableExt, BoxExt, ListBoxRowExt, WidgetExt}; +use gtk::prelude::{ActionableExt, BoxExt, ButtonExt, ListBoxRowExt, WidgetExt}; use gtk::{gio, StringObject, Widget}; use ReSet_Lib::bluetooth::bluetooth::{BluetoothAdapter, BluetoothDevice}; use ReSet_Lib::signals::{BluetoothDeviceAdded, BluetoothDeviceChanged, BluetoothDeviceRemoved}; @@ -42,46 +42,70 @@ fn setup_callbacks( listeners: Arc, bluetooth_box: Arc, ) -> Arc { + let bluetooth_box_button_ref = bluetooth_box.clone(); let bluetooth_box_ref = bluetooth_box.clone(); + let listeners_ref = listeners.clone(); let imp = bluetooth_box.imp(); - // let bluetooth_box_ref = bluetooth_box.clone(); imp.reset_visibility.set_activatable(true); - imp.reset_visibility.set_action_name(Some("navigation.push")); + imp.reset_visibility + .set_action_name(Some("navigation.push")); imp.reset_visibility .set_action_target_value(Some(&Variant::from("visibility"))); imp.reset_bluetooth_main_tab .set_action_name(Some("navigation.pop")); - // TODO add a manual search button here - imp.reset_bluetooth_switch.connect_state_set(move |_, state| { - if !state { - let imp = bluetooth_box_ref.imp(); - for x in imp - .reset_bluetooth_connected_devices - .observe_children() - .iter::() - .flatten() - { - // todo test this - if let Some(item) = x.downcast_ref::() { - imp.reset_bluetooth_available_devices.remove(item); + + imp.reset_bluetooth_refresh_button.set_sensitive(false); + imp.reset_bluetooth_refresh_button + .connect_clicked(move |button| { + button.set_sensitive(false); + start_bluetooth_listener(listeners.clone(), bluetooth_box_button_ref.clone()); + }); + + imp.reset_bluetooth_discoverable_switch + .connect_state_set(clone!(@weak imp => @default-return glib::Propagation::Proceed,move |_, state| { + set_bluetooth_adapter_visibility(imp.reset_current_bluetooth_adapter.borrow().path.clone(), state); + glib::Propagation::Proceed + })); + + imp.reset_bluetooth_pairable_switch + .connect_state_set(clone!(@weak imp => @default-return glib::Propagation::Proceed,move |_, state| { + set_bluetooth_adapter_pairability(imp.reset_current_bluetooth_adapter.borrow().path.clone(), state); + glib::Propagation::Proceed + })); + + imp.reset_bluetooth_switch + .connect_state_set(move |_, state| { + if !state { + let imp = bluetooth_box_ref.imp(); + for x in imp + .reset_bluetooth_connected_devices + .observe_children() + .iter::() + .flatten() + { + // todo test this + if let Some(item) = x.downcast_ref::() { + imp.reset_bluetooth_available_devices.remove(item); + } } + listeners_ref + .bluetooth_listener + .store(false, Ordering::SeqCst); + set_adapter_enabled( + imp.reset_current_bluetooth_adapter.borrow().path.clone(), + false, + ); + } else { + let imp = bluetooth_box_ref.imp(); + set_adapter_enabled( + imp.reset_current_bluetooth_adapter.borrow().path.clone(), + true, + ); + start_bluetooth_listener(listeners_ref.clone(), bluetooth_box_ref.clone()); } - listeners.bluetooth_listener.store(false, Ordering::SeqCst); - set_adapter_enabled( - imp.reset_current_bluetooth_adapter.borrow().path.clone(), - false, - ); - } else { - let imp = bluetooth_box_ref.imp(); - set_adapter_enabled( - imp.reset_current_bluetooth_adapter.borrow().path.clone(), - true, - ); - start_bluetooth_listener(listeners.clone(), bluetooth_box_ref.clone()); - } - glib::Propagation::Proceed - }); + glib::Propagation::Proceed + }); bluetooth_box } @@ -114,6 +138,23 @@ pub fn populate_conntected_bluetooth_devices(bluetooth_box: Arc) { if let Some(index) = map.get(&device.alias) { imp.reset_bluetooth_adapter.set_selected(index.1); } + + { + let current_adapter = imp.reset_current_bluetooth_adapter.borrow(); + imp.reset_bluetooth_switch + .set_state(current_adapter.powered); + imp.reset_bluetooth_switch + .set_active(current_adapter.powered); + imp.reset_bluetooth_discoverable_switch + .set_state(current_adapter.discoverable); + imp.reset_bluetooth_discoverable_switch + .set_active(current_adapter.discoverable); + imp.reset_bluetooth_pairable_switch + .set_state(current_adapter.pairable); + imp.reset_bluetooth_pairable_switch + .set_active(current_adapter.pairable); + } + imp.reset_bluetooth_adapter.connect_selected_notify( clone!(@weak imp => move |dropdown| { let selected = dropdown.selected_item(); @@ -155,8 +196,10 @@ pub fn populate_conntected_bluetooth_devices(bluetooth_box: Arc) { pub fn start_bluetooth_listener(listeners: Arc, bluetooth_box: Arc) { gio::spawn_blocking(move || { if listeners.bluetooth_listener.load(Ordering::SeqCst) { + println!("bluetooth listener was active"); return; } + println!("starting bluetooth listener"); let conn = Connection::new_session().unwrap(); let proxy = conn.with_proxy( @@ -164,13 +207,8 @@ pub fn start_bluetooth_listener(listeners: Arc, bluetooth_box: Arc = proxy.method_call( - "org.Xetibo.ReSetBluetooth", - "StartBluetoothListener", - #[allow(clippy::unnecessary_cast)] - (25000 as u32,), - // leave me alone clippy, I am dealing with C code - ); + let _: Result<(), Error> = + proxy.method_call("org.Xetibo.ReSetBluetooth", "StartBluetoothListener", ()); let device_added = BluetoothDeviceAdded::match_rule( Some(&"org.Xetibo.ReSetDaemon".into()), Some(&Path::from("/org/Xetibo/ReSetDaemon")), @@ -258,9 +296,17 @@ pub fn start_bluetooth_listener(listeners: Arc, bluetooth_box: Arc, bluetooth_box: Arc Duration::from_millis(25000) { + listeners.bluetooth_listener.store(false, Ordering::SeqCst); glib::spawn_future(async move { glib::idle_add_once(move || { let imp = loop_box.imp(); - for x in imp - .reset_bluetooth_available_devices - .observe_children() - .iter::() - .flatten() - { - if let Some(item) = x.downcast_ref::() { - imp.reset_bluetooth_available_devices.remove(item); - } + let mut entries = imp.available_devices.borrow_mut(); + for entry in entries.iter() { + imp.reset_bluetooth_available_devices.remove(&*entry.1 .1); } + entries.clear(); + imp.reset_bluetooth_refresh_button.set_sensitive(true); }); }); + let _: Result<(), Error> = + proxy.method_call("org.Xetibo.ReSetBluetooth", "StopBluetoothListener", ()); println!("stopping bluetooth listener"); break; } @@ -348,6 +393,34 @@ fn set_bluetooth_adapter(path: Path<'static>) { proxy.method_call("org.Xetibo.ReSetBluetooth", "SetBluetoothAdapter", (path,)); } +fn set_bluetooth_adapter_visibility(path: Path<'static>, visible: bool) { + 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", + "SetBluetoothAdapterVisibility", + (path, visible), + ); +} + +fn set_bluetooth_adapter_pairability(path: Path<'static>, visible: bool) { + 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", + "SetBluetoothAdapterPairability", + (path, visible), + ); +} + fn set_adapter_enabled(path: Path<'static>, enabled: bool) { let conn = Connection::new_session().unwrap(); let proxy = conn.with_proxy( diff --git a/src/components/bluetooth/bluetooth_box_impl.rs b/src/components/bluetooth/bluetooth_box_impl.rs index 34593ab..656405d 100644 --- a/src/components/bluetooth/bluetooth_box_impl.rs +++ b/src/components/bluetooth/bluetooth_box_impl.rs @@ -32,6 +32,10 @@ pub struct BluetoothBox { pub reset_visibility: TemplateChild, #[template_child] pub reset_bluetooth_main_tab: TemplateChild, + #[template_child] + pub reset_bluetooth_discoverable_switch: TemplateChild, + #[template_child] + pub reset_bluetooth_pairable_switch: TemplateChild, pub available_devices: BluetoothMap, pub connected_devices: BluetoothMap, pub reset_bluetooth_adapters: Arc>>, diff --git a/src/resources/resetBluetooth.ui b/src/resources/resetBluetooth.ui index 0d4d296..c04804b 100644 --- a/src/resources/resetBluetooth.ui +++ b/src/resources/resetBluetooth.ui @@ -156,6 +156,42 @@ 5 + + + 5 + 5 + 5 + + + start + True + True + Pairable + + + + + + + + + + 5 + 5 + 5 + + + start + True + True + Discoverable + + + + + + + diff --git a/src/resources/resetUI.cmb b/src/resources/resetUI.cmb index 8213e71..add0ef5 100644 --- a/src/resources/resetUI.cmb +++ b/src/resources/resetUI.cmb @@ -140,7 +140,7 @@ (10,144,"GtkSwitch","reset_bluetooth_switch",142,None,None,None,1,None), (10,153,"GtkBox",None,138,None,None,None,None,None), (10,154,"GtkListBox",None,153,None,None,None,None,None), - (10,155,"resetListBoxRow","reset_bluetooth_main_tab",154,None,None,None,None,None), + (10,155,"resetListBoxRow","reset_bluetooth_main_tab",154,None,None,None,1,None), (10,156,"GtkBox",None,155,None,None,None,None,None), (10,157,"GtkLabel",None,156,None,None,None,None,None), (10,158,"GtkImage",None,156,None,None,None,1,None), @@ -158,6 +158,12 @@ (10,183,"GtkScrolledWindow",None,181,None,None,None,None,None), (10,184,"GtkViewport",None,183,None,None,None,None,None), (10,185,"GtkBox","reset_bluetooth_connected_devices",184,None,None,None,None,None), + (10,188,"GtkBox",None,153,None,None,None,4,None), + (10,193,"GtkLabel",None,188,None,None,None,None,None), + (10,196,"GtkSwitch","reset_bluetooth_discoverable_switch",188,None,None,None,1,None), + (10,197,"GtkBox",None,153,None,None,None,3,None), + (10,198,"GtkLabel",None,197,None,None,None,None,None), + (10,199,"GtkSwitch","reset_bluetooth_pairable_switch",197,None,None,None,1,None), (11,2,"GtkBox","resetBluetoothEntry",None,None,None,None,None,None), (11,3,"GtkImage","reset_bluetooth_device_type",2,None,None,None,None,None), (11,5,"GtkButton","reset_bluetooth_button",2,None,None,None,3,None), @@ -587,6 +593,20 @@ (10,183,"GtkScrolledWindow","min-content-height","100",None,None,None,None,None,None,None,None,None), (10,183,"GtkScrolledWindow","propagate-natural-height","True",None,None,None,None,None,None,None,None,None), (10,185,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None), + (10,188,"GtkWidget","margin-bottom","5",None,None,None,None,None,None,None,None,None), + (10,188,"GtkWidget","margin-start","5",None,None,None,None,None,None,None,None,None), + (10,188,"GtkWidget","margin-top","5",None,None,None,None,None,None,None,None,None), + (10,193,"GtkLabel","label","Discoverable",None,None,None,None,None,None,None,None,None), + (10,193,"GtkWidget","halign","start",None,None,None,None,None,None,None,None,None), + (10,193,"GtkWidget","hexpand","True",None,None,None,None,None,None,None,None,None), + (10,193,"GtkWidget","hexpand-set","True",None,None,None,None,None,None,None,None,None), + (10,197,"GtkWidget","margin-bottom","5",None,None,None,None,None,None,None,None,None), + (10,197,"GtkWidget","margin-start","5",None,None,None,None,None,None,None,None,None), + (10,197,"GtkWidget","margin-top","5",None,None,None,None,None,None,None,None,None), + (10,198,"GtkLabel","label","Pairable",None,None,None,None,None,None,None,None,None), + (10,198,"GtkWidget","halign","start",None,None,None,None,None,None,None,None,None), + (10,198,"GtkWidget","hexpand","True",None,None,None,None,None,None,None,None,None), + (10,198,"GtkWidget","hexpand-set","True",None,None,None,None,None,None,None,None,None), (11,2,"GtkWidget","margin-start","5",None,None,None,None,None,None,None,None,None), (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),