mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-07-03 03:31:03 +02:00
refactor: major client code changes
This does away with `lazy_static` singletons for all the clients, instead putting them all inside a `Clients` struct on the `Ironbar` struct. Client code has been refactored in places to accommodate this, and module code has been updated to get the clients the new way. The Wayland client has been re-written from the ground up to remove a lot of the needless complications, provide a nicer interface and reduce some duplicate data. The MPD music client has been overhauled to use the `mpd_utils` crate, which simplifies the code within Ironbar and should offer more robustness and better recovery when connection is lost to the server. The launcher module in particular has been affected by the refactor.
This commit is contained in:
parent
57b57ed002
commit
c702f6fffa
33 changed files with 1081 additions and 1063 deletions
|
@ -49,7 +49,7 @@ const fn default_max_items() -> usize {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ControllerEvent {
|
||||
Add(usize, Arc<ClipboardItem>),
|
||||
Add(usize, ClipboardItem),
|
||||
Remove(usize),
|
||||
Activate(usize),
|
||||
Deactivate,
|
||||
|
@ -78,17 +78,16 @@ impl Module<Button> for ClipboardModule {
|
|||
let max_items = self.max_items;
|
||||
|
||||
let tx = context.tx.clone();
|
||||
let client: Arc<clipboard::Client> = context.client();
|
||||
|
||||
// listen to clipboard events
|
||||
spawn(async move {
|
||||
let mut rx = {
|
||||
let client = clipboard::get_client();
|
||||
client.subscribe(max_items)
|
||||
};
|
||||
let mut rx = client.subscribe(max_items);
|
||||
|
||||
while let Some(event) = rx.recv().await {
|
||||
match event {
|
||||
ClipboardEvent::Add(item) => {
|
||||
let msg = match &item.value {
|
||||
let msg = match item.value.as_ref() {
|
||||
ClipboardValue::Other => {
|
||||
ModuleUpdateEvent::Update(ControllerEvent::Deactivate)
|
||||
}
|
||||
|
@ -108,10 +107,11 @@ impl Module<Button> for ClipboardModule {
|
|||
error!("Clipboard client unexpectedly closed");
|
||||
});
|
||||
|
||||
let client = context.client::<clipboard::Client>();
|
||||
|
||||
// listen to ui events
|
||||
spawn(async move {
|
||||
while let Some(event) = rx.recv().await {
|
||||
let client = clipboard::get_client();
|
||||
match event {
|
||||
UIEvent::Copy(id) => client.copy(id),
|
||||
UIEvent::Remove(id) => client.remove(id),
|
||||
|
@ -172,7 +172,7 @@ impl Module<Button> for ClipboardModule {
|
|||
let row = gtk::Box::new(Orientation::Horizontal, 0);
|
||||
row.style_context().add_class("item");
|
||||
|
||||
let button = match &item.value {
|
||||
let button = match item.value.as_ref() {
|
||||
ClipboardValue::Text(value) => {
|
||||
let button = RadioButton::from_widget(&hidden_option);
|
||||
|
||||
|
|
|
@ -3,12 +3,12 @@ use crate::config::{CommonConfig, TruncateMode};
|
|||
use crate::gtk_helpers::IronbarGtkExt;
|
||||
use crate::image::ImageProvider;
|
||||
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
||||
use crate::{glib_recv, lock, send_async, spawn, try_send};
|
||||
use crate::{glib_recv, send_async, spawn, try_send};
|
||||
use color_eyre::Result;
|
||||
use gtk::prelude::*;
|
||||
use gtk::Label;
|
||||
use serde::Deserialize;
|
||||
use tokio::sync::mpsc::{Receiver, Sender};
|
||||
use tokio::sync::mpsc;
|
||||
use tracing::debug;
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
|
@ -58,21 +58,16 @@ impl Module<gtk::Box> for FocusedModule {
|
|||
&self,
|
||||
_info: &ModuleInfo,
|
||||
context: &WidgetContext<Self::SendMessage, Self::ReceiveMessage>,
|
||||
_rx: Receiver<Self::ReceiveMessage>,
|
||||
_rx: mpsc::Receiver<Self::ReceiveMessage>,
|
||||
) -> Result<()> {
|
||||
let tx = context.tx.clone();
|
||||
spawn(async move {
|
||||
let (mut wlrx, handles) = {
|
||||
let wl = wayland::get_client();
|
||||
let wl = lock!(wl);
|
||||
wl.subscribe_toplevels()
|
||||
};
|
||||
let wl = context.client::<wayland::Client>();
|
||||
|
||||
let focused = handles.values().find_map(|handle| {
|
||||
handle
|
||||
.info()
|
||||
.and_then(|info| if info.focused { Some(info) } else { None })
|
||||
});
|
||||
spawn(async move {
|
||||
let mut wlrx = wl.subscribe_toplevels();
|
||||
let handles = wl.toplevel_info_all();
|
||||
|
||||
let focused = handles.into_iter().find(|info| info.focused);
|
||||
|
||||
if let Some(focused) = focused {
|
||||
try_send!(
|
||||
|
@ -83,9 +78,7 @@ impl Module<gtk::Box> for FocusedModule {
|
|||
|
||||
while let Ok(event) = wlrx.recv().await {
|
||||
match event {
|
||||
ToplevelEvent::Update(handle) => {
|
||||
let info = handle.info().unwrap_or_default();
|
||||
|
||||
ToplevelEvent::Update(info) => {
|
||||
if info.focused {
|
||||
debug!("Changing focus");
|
||||
send_async!(
|
||||
|
@ -99,8 +92,7 @@ impl Module<gtk::Box> for FocusedModule {
|
|||
send_async!(tx, ModuleUpdateEvent::Update(None));
|
||||
}
|
||||
}
|
||||
ToplevelEvent::Remove(handle) => {
|
||||
let info = handle.info().unwrap_or_default();
|
||||
ToplevelEvent::Remove(info) => {
|
||||
if info.focused {
|
||||
debug!("Clearing focus");
|
||||
send_async!(tx, ModuleUpdateEvent::Update(None));
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
use super::open_state::OpenState;
|
||||
use crate::clients::wayland::ToplevelHandle;
|
||||
use crate::clients::wayland::ToplevelInfo;
|
||||
use crate::config::BarPosition;
|
||||
use crate::gtk_helpers::IronbarGtkExt;
|
||||
use crate::image::ImageProvider;
|
||||
use crate::modules::launcher::{ItemEvent, LauncherUpdate};
|
||||
use crate::modules::ModuleUpdateEvent;
|
||||
use crate::{read_lock, try_send};
|
||||
use color_eyre::{Report, Result};
|
||||
use glib::Propagation;
|
||||
use gtk::prelude::*;
|
||||
use gtk::{Button, IconTheme};
|
||||
|
@ -15,7 +14,6 @@ use std::rc::Rc;
|
|||
use std::sync::RwLock;
|
||||
use tokio::sync::mpsc::Sender;
|
||||
use tracing::error;
|
||||
use wayland_client::protocol::wl_seat::WlSeat;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Item {
|
||||
|
@ -38,30 +36,24 @@ impl Item {
|
|||
}
|
||||
|
||||
/// Merges the provided node into this launcher item
|
||||
pub fn merge_toplevel(&mut self, handle: ToplevelHandle) -> Result<Window> {
|
||||
let info = handle
|
||||
.info()
|
||||
.ok_or_else(|| Report::msg("Toplevel is missing associated info"))?;
|
||||
|
||||
pub fn merge_toplevel(&mut self, info: ToplevelInfo) -> Window {
|
||||
let id = info.id;
|
||||
|
||||
if self.windows.is_empty() {
|
||||
self.name = info.title;
|
||||
self.name = info.title.clone();
|
||||
}
|
||||
|
||||
let window = Window::try_from(handle)?;
|
||||
let window = Window::from(info);
|
||||
self.windows.insert(id, window.clone());
|
||||
|
||||
self.recalculate_open_state();
|
||||
|
||||
Ok(window)
|
||||
window
|
||||
}
|
||||
|
||||
pub fn unmerge_toplevel(&mut self, handle: &ToplevelHandle) {
|
||||
if let Some(info) = handle.info() {
|
||||
self.windows.remove(&info.id);
|
||||
self.recalculate_open_state();
|
||||
}
|
||||
pub fn unmerge_toplevel(&mut self, info: &ToplevelInfo) {
|
||||
self.windows.remove(&info.id);
|
||||
self.recalculate_open_state();
|
||||
}
|
||||
|
||||
pub fn set_window_name(&mut self, window_id: usize, name: String) {
|
||||
|
@ -97,29 +89,24 @@ impl Item {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<ToplevelHandle> for Item {
|
||||
type Error = Report;
|
||||
|
||||
fn try_from(handle: ToplevelHandle) -> std::result::Result<Self, Self::Error> {
|
||||
let info = handle
|
||||
.info()
|
||||
.ok_or_else(|| Report::msg("Toplevel is missing associated info"))?;
|
||||
|
||||
impl From<ToplevelInfo> for Item {
|
||||
fn from(info: ToplevelInfo) -> Self {
|
||||
let id = info.id;
|
||||
let name = info.title.clone();
|
||||
let app_id = info.app_id.clone();
|
||||
let open_state = OpenState::from(&info);
|
||||
|
||||
let mut windows = IndexMap::new();
|
||||
let window = Window::try_from(handle)?;
|
||||
windows.insert(info.id, window);
|
||||
let window = Window::from(info);
|
||||
windows.insert(id, window);
|
||||
|
||||
Ok(Self {
|
||||
Self {
|
||||
app_id,
|
||||
favorite: false,
|
||||
open_state,
|
||||
windows,
|
||||
name,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,30 +115,17 @@ pub struct Window {
|
|||
pub id: usize,
|
||||
pub name: String,
|
||||
pub open_state: OpenState,
|
||||
handle: ToplevelHandle,
|
||||
}
|
||||
|
||||
impl TryFrom<ToplevelHandle> for Window {
|
||||
type Error = Report;
|
||||
|
||||
fn try_from(handle: ToplevelHandle) -> Result<Self, Self::Error> {
|
||||
let info = handle
|
||||
.info()
|
||||
.ok_or_else(|| Report::msg("Toplevel is missing associated info"))?;
|
||||
impl From<ToplevelInfo> for Window {
|
||||
fn from(info: ToplevelInfo) -> Self {
|
||||
let open_state = OpenState::from(&info);
|
||||
|
||||
Ok(Self {
|
||||
Self {
|
||||
id: info.id,
|
||||
name: info.title,
|
||||
open_state,
|
||||
handle,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Window {
|
||||
pub fn focus(&self, seat: &WlSeat) {
|
||||
self.handle.focus(seat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
mod item;
|
||||
mod open_state;
|
||||
|
||||
use self::item::{Item, ItemButton, Window};
|
||||
use self::item::{AppearanceOptions, Item, ItemButton, Window};
|
||||
use self::open_state::OpenState;
|
||||
use super::{Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, WidgetContext};
|
||||
use crate::clients::wayland::{self, ToplevelEvent};
|
||||
use crate::config::CommonConfig;
|
||||
use crate::desktop_file::find_desktop_file;
|
||||
use crate::modules::launcher::item::AppearanceOptions;
|
||||
use crate::modules::{
|
||||
Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, WidgetContext,
|
||||
};
|
||||
use crate::{arc_mut, glib_recv, lock, send_async, spawn, try_send, write_lock};
|
||||
use color_eyre::{Help, Report};
|
||||
use gtk::prelude::*;
|
||||
|
@ -112,27 +109,26 @@ impl Module<gtk::Box> for LauncherModule {
|
|||
|
||||
let items2 = Arc::clone(&items);
|
||||
|
||||
let tx = context.tx.clone();
|
||||
let tx2 = context.tx.clone();
|
||||
|
||||
let wl = context.client::<wayland::Client>();
|
||||
spawn(async move {
|
||||
let items = items2;
|
||||
let tx = tx2;
|
||||
|
||||
let (mut wlrx, handles) = {
|
||||
let wl = wayland::get_client();
|
||||
let wl = lock!(wl);
|
||||
wl.subscribe_toplevels()
|
||||
};
|
||||
|
||||
for handle in handles.values() {
|
||||
let Some(info) = handle.info() else { continue };
|
||||
let mut wlrx = wl.subscribe_toplevels();
|
||||
let handles = wl.toplevel_info_all();
|
||||
|
||||
for info in handles {
|
||||
let mut items = lock!(items);
|
||||
let item = items.get_mut(&info.app_id);
|
||||
match item {
|
||||
Some(item) => {
|
||||
item.merge_toplevel(handle.clone())?;
|
||||
item.merge_toplevel(info.clone());
|
||||
}
|
||||
None => {
|
||||
items.insert(info.app_id.clone(), Item::try_from(handle.clone())?);
|
||||
items.insert(info.app_id.clone(), Item::from(info.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -154,22 +150,22 @@ impl Module<gtk::Box> for LauncherModule {
|
|||
trace!("event: {:?}", event);
|
||||
|
||||
match event {
|
||||
ToplevelEvent::New(handle) => {
|
||||
let Some(info) = handle.info() else { continue };
|
||||
ToplevelEvent::New(info) => {
|
||||
let app_id = info.app_id.clone();
|
||||
|
||||
let new_item = {
|
||||
let mut items = lock!(items);
|
||||
let item = items.get_mut(&info.app_id);
|
||||
match item {
|
||||
None => {
|
||||
let item: Item = handle.try_into()?;
|
||||
let item: Item = info.into();
|
||||
|
||||
items.insert(info.app_id.clone(), item.clone());
|
||||
items.insert(app_id.clone(), item.clone());
|
||||
|
||||
ItemOrWindow::Item(item)
|
||||
}
|
||||
Some(item) => {
|
||||
let window = item.merge_toplevel(handle)?;
|
||||
let window = item.merge_toplevel(info);
|
||||
ItemOrWindow::Window(window)
|
||||
}
|
||||
}
|
||||
|
@ -180,14 +176,11 @@ impl Module<gtk::Box> for LauncherModule {
|
|||
send_update(LauncherUpdate::AddItem(item)).await
|
||||
}
|
||||
ItemOrWindow::Window(window) => {
|
||||
send_update(LauncherUpdate::AddWindow(info.app_id.clone(), window))
|
||||
.await
|
||||
send_update(LauncherUpdate::AddWindow(app_id, window)).await
|
||||
}
|
||||
}?;
|
||||
}
|
||||
ToplevelEvent::Update(handle) => {
|
||||
let Some(info) = handle.info() else { continue };
|
||||
|
||||
ToplevelEvent::Update(info) => {
|
||||
if let Some(item) = lock!(items).get_mut(&info.app_id) {
|
||||
item.set_window_focused(info.id, info.focused);
|
||||
item.set_window_name(info.id, info.title.clone());
|
||||
|
@ -202,15 +195,13 @@ impl Module<gtk::Box> for LauncherModule {
|
|||
))
|
||||
.await?;
|
||||
}
|
||||
ToplevelEvent::Remove(handle) => {
|
||||
let Some(info) = handle.info() else { continue };
|
||||
|
||||
ToplevelEvent::Remove(info) => {
|
||||
let remove_item = {
|
||||
let mut items = lock!(items);
|
||||
let item = items.get_mut(&info.app_id);
|
||||
match item {
|
||||
Some(item) => {
|
||||
item.unmerge_toplevel(&handle);
|
||||
item.unmerge_toplevel(&info);
|
||||
|
||||
if item.windows.is_empty() {
|
||||
items.remove(&info.app_id);
|
||||
|
@ -245,6 +236,7 @@ impl Module<gtk::Box> for LauncherModule {
|
|||
});
|
||||
|
||||
// listen to ui events
|
||||
let wl = context.client::<wayland::Client>();
|
||||
spawn(async move {
|
||||
while let Some(event) = rx.recv().await {
|
||||
if let ItemEvent::OpenItem(app_id) = event {
|
||||
|
@ -272,37 +264,29 @@ impl Module<gtk::Box> for LauncherModule {
|
|||
} else {
|
||||
send_async!(tx, ModuleUpdateEvent::ClosePopup);
|
||||
|
||||
let wl = wayland::get_client();
|
||||
let items = lock!(items);
|
||||
|
||||
let id = match event {
|
||||
ItemEvent::FocusItem(app_id) => items.get(&app_id).and_then(|item| {
|
||||
item.windows
|
||||
.iter()
|
||||
.find(|(_, win)| !win.open_state.is_focused())
|
||||
.or_else(|| item.windows.first())
|
||||
.map(|(_, win)| win.id)
|
||||
}),
|
||||
ItemEvent::FocusItem(app_id) => {
|
||||
lock!(items).get(&app_id).and_then(|item| {
|
||||
item.windows
|
||||
.iter()
|
||||
.find(|(_, win)| !win.open_state.is_focused())
|
||||
.or_else(|| item.windows.first())
|
||||
.map(|(_, win)| win.id)
|
||||
})
|
||||
}
|
||||
ItemEvent::FocusWindow(id) => Some(id),
|
||||
ItemEvent::OpenItem(_) => unreachable!(),
|
||||
};
|
||||
|
||||
if let Some(id) = id {
|
||||
if let Some(window) =
|
||||
items.iter().find_map(|(_, item)| item.windows.get(&id))
|
||||
if let Some(window) = lock!(items)
|
||||
.iter()
|
||||
.find_map(|(_, item)| item.windows.get(&id))
|
||||
{
|
||||
debug!("Focusing window {id}: {}", window.name);
|
||||
|
||||
let seat = lock!(wl)
|
||||
.get_seats()
|
||||
.pop()
|
||||
.expect("Failed to get Wayland seat");
|
||||
window.focus(&seat);
|
||||
wl.toplevel_focus(window.id);
|
||||
}
|
||||
}
|
||||
|
||||
// roundtrip to immediately send activate event
|
||||
lock!(wl).roundtrip();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::cell::RefCell;
|
||||
use std::fmt::Debug;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use color_eyre::Result;
|
||||
use glib::IsA;
|
||||
|
@ -10,10 +11,11 @@ use gtk::{Application, Button, EventBox, IconTheme, Orientation, Revealer, Widge
|
|||
use tokio::sync::{broadcast, mpsc};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::clients::ProvidesClient;
|
||||
use crate::config::{BarPosition, CommonConfig, TransitionType};
|
||||
use crate::gtk_helpers::{IronbarGtkExt, WidgetGeometry};
|
||||
use crate::popup::Popup;
|
||||
use crate::{glib_recv_mpsc, send};
|
||||
use crate::{glib_recv_mpsc, send, Ironbar};
|
||||
|
||||
#[cfg(feature = "clipboard")]
|
||||
pub mod clipboard;
|
||||
|
@ -76,6 +78,7 @@ where
|
|||
TSend: Clone,
|
||||
{
|
||||
pub id: usize,
|
||||
pub ironbar: Rc<Ironbar>,
|
||||
pub tx: mpsc::Sender<ModuleUpdateEvent<TSend>>,
|
||||
pub update_tx: broadcast::Sender<TSend>,
|
||||
pub controller_tx: mpsc::Sender<TReceive>,
|
||||
|
@ -87,6 +90,18 @@ impl<TSend, TReceive> WidgetContext<TSend, TReceive>
|
|||
where
|
||||
TSend: Clone,
|
||||
{
|
||||
/// Gets client `T` from the context.
|
||||
///
|
||||
/// This is a shorthand to avoid needing to go through
|
||||
/// `context.ironbar.clients`.
|
||||
pub fn client<T: ?Sized>(&self) -> Arc<T>
|
||||
where
|
||||
WidgetContext<TSend, TReceive>: ProvidesClient<T>,
|
||||
{
|
||||
ProvidesClient::provide(self)
|
||||
}
|
||||
|
||||
/// Subscribes to events sent from this widget.
|
||||
pub fn subscribe(&self) -> broadcast::Receiver<TSend> {
|
||||
self.update_tx.subscribe()
|
||||
}
|
||||
|
@ -194,6 +209,7 @@ where
|
|||
pub fn create_module<TModule, TWidget, TSend, TRec>(
|
||||
module: TModule,
|
||||
id: usize,
|
||||
ironbar: Rc<Ironbar>,
|
||||
name: Option<String>,
|
||||
info: &ModuleInfo,
|
||||
popup: &Rc<RefCell<Popup>>,
|
||||
|
@ -210,6 +226,7 @@ where
|
|||
|
||||
let context = WidgetContext {
|
||||
id,
|
||||
ironbar,
|
||||
tx: ui_tx,
|
||||
update_tx: tx.clone(),
|
||||
controller_tx,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use std::cell::RefMut;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
@ -14,6 +15,7 @@ use tracing::error;
|
|||
use crate::clients::music::{
|
||||
self, MusicClient, PlayerState, PlayerUpdate, ProgressTick, Status, Track,
|
||||
};
|
||||
use crate::clients::Clients;
|
||||
use crate::gtk_helpers::IronbarGtkExt;
|
||||
use crate::image::{new_icon_button, new_icon_label, ImageProvider};
|
||||
use crate::modules::PopupButton;
|
||||
|
@ -67,16 +69,18 @@ pub struct SongUpdate {
|
|||
display_string: String,
|
||||
}
|
||||
|
||||
async fn get_client(
|
||||
fn get_client(
|
||||
mut clients: RefMut<'_, Clients>,
|
||||
player_type: PlayerType,
|
||||
host: &str,
|
||||
host: String,
|
||||
music_dir: PathBuf,
|
||||
) -> Box<Arc<dyn MusicClient>> {
|
||||
match player_type {
|
||||
PlayerType::Mpd => music::get_client(music::ClientType::Mpd { host, music_dir }),
|
||||
PlayerType::Mpris => music::get_client(music::ClientType::Mpris {}),
|
||||
}
|
||||
.await
|
||||
) -> Arc<dyn MusicClient> {
|
||||
let client_type = match player_type {
|
||||
PlayerType::Mpd => music::ClientType::Mpd { host, music_dir },
|
||||
PlayerType::Mpris => music::ClientType::Mpris,
|
||||
};
|
||||
|
||||
clients.music(client_type)
|
||||
}
|
||||
|
||||
impl Module<Button> for MusicModule {
|
||||
|
@ -98,19 +102,21 @@ impl Module<Button> for MusicModule {
|
|||
let re = Regex::new(r"\{([\w-]+)}")?;
|
||||
let tokens = get_tokens(&re, self.format.as_str());
|
||||
|
||||
let client = get_client(
|
||||
context.ironbar.clients.borrow_mut(),
|
||||
self.player_type,
|
||||
self.host.clone(),
|
||||
self.music_dir.clone(),
|
||||
);
|
||||
|
||||
// receive player updates
|
||||
{
|
||||
let player_type = self.player_type;
|
||||
let host = self.host.clone();
|
||||
let music_dir = self.music_dir.clone();
|
||||
let tx = context.tx.clone();
|
||||
let client = client.clone();
|
||||
|
||||
spawn(async move {
|
||||
loop {
|
||||
let mut rx = {
|
||||
let client = get_client(player_type, &host, music_dir.clone()).await;
|
||||
client.subscribe_change()
|
||||
};
|
||||
let mut rx = client.subscribe_change();
|
||||
|
||||
while let Ok(update) = rx.recv().await {
|
||||
match update {
|
||||
|
@ -143,7 +149,6 @@ impl Module<Button> for MusicModule {
|
|||
progress_tick
|
||||
))
|
||||
),
|
||||
PlayerUpdate::Disconnect => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -152,13 +157,8 @@ impl Module<Button> for MusicModule {
|
|||
|
||||
// listen to ui events
|
||||
{
|
||||
let player_type = self.player_type;
|
||||
let host = self.host.clone();
|
||||
let music_dir = self.music_dir.clone();
|
||||
|
||||
spawn(async move {
|
||||
while let Some(event) = rx.recv().await {
|
||||
let client = get_client(player_type, &host, music_dir.clone()).await;
|
||||
let res = match event {
|
||||
PlayerCommand::Previous => client.prev(),
|
||||
PlayerCommand::Play => client.play(),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::clients::system_tray::get_tray_event_client;
|
||||
use crate::clients::system_tray::TrayEventReceiver;
|
||||
use crate::config::CommonConfig;
|
||||
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
||||
use crate::{await_sync, glib_recv, spawn, try_send};
|
||||
use crate::{glib_recv, spawn, try_send};
|
||||
use color_eyre::Result;
|
||||
use glib::ffi::g_strfreev;
|
||||
use glib::translate::ToGlibPtr;
|
||||
|
@ -171,8 +171,10 @@ impl Module<MenuBar> for TrayModule {
|
|||
context: &WidgetContext<Self::SendMessage, Self::ReceiveMessage>,
|
||||
mut rx: Receiver<Self::ReceiveMessage>,
|
||||
) -> Result<()> {
|
||||
let client = await_sync(async { get_tray_event_client().await });
|
||||
let tx = context.tx.clone();
|
||||
|
||||
let client = context.client::<TrayEventReceiver>();
|
||||
|
||||
let (tray_tx, mut tray_rx) = client.subscribe();
|
||||
|
||||
// listen to tray updates
|
||||
|
|
|
@ -6,8 +6,8 @@ use serde::Deserialize;
|
|||
use tokio::sync::{broadcast, mpsc};
|
||||
use upower_dbus::BatteryState;
|
||||
use zbus;
|
||||
use zbus::fdo::PropertiesProxy;
|
||||
|
||||
use crate::clients::upower::get_display_proxy;
|
||||
use crate::config::CommonConfig;
|
||||
use crate::gtk_helpers::IronbarGtkExt;
|
||||
use crate::image::ImageProvider;
|
||||
|
@ -15,7 +15,7 @@ use crate::modules::PopupButton;
|
|||
use crate::modules::{
|
||||
Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, WidgetContext,
|
||||
};
|
||||
use crate::{await_sync, error, glib_recv, send_async, spawn, try_send};
|
||||
use crate::{error, glib_recv, send_async, spawn, try_send};
|
||||
|
||||
const DAY: i64 = 24 * 60 * 60;
|
||||
const HOUR: i64 = 60 * 60;
|
||||
|
@ -65,9 +65,10 @@ impl Module<gtk::Button> for UpowerModule {
|
|||
_rx: mpsc::Receiver<Self::ReceiveMessage>,
|
||||
) -> Result<()> {
|
||||
let tx = context.tx.clone();
|
||||
|
||||
let display_proxy = context.client::<PropertiesProxy>();
|
||||
|
||||
spawn(async move {
|
||||
// await_sync due to strange "higher-ranked lifetime error"
|
||||
let display_proxy = await_sync(async move { get_display_proxy().await });
|
||||
let mut prop_changed_stream = display_proxy.receive_properties_changed().await?;
|
||||
|
||||
let device_interface_name =
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::clients::compositor::{Compositor, Visibility, Workspace, WorkspaceUpdate};
|
||||
use crate::clients::compositor::{Visibility, Workspace, WorkspaceClient, WorkspaceUpdate};
|
||||
use crate::config::CommonConfig;
|
||||
use crate::image::new_icon_button;
|
||||
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
||||
|
@ -98,7 +98,7 @@ fn create_button(
|
|||
}
|
||||
|
||||
if !visibility.is_visible() {
|
||||
style_context.add_class("inactive")
|
||||
style_context.add_class("inactive");
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -155,13 +155,10 @@ impl Module<gtk::Box> for WorkspacesModule {
|
|||
mut rx: Receiver<Self::ReceiveMessage>,
|
||||
) -> Result<()> {
|
||||
let tx = context.tx.clone();
|
||||
let client = context.ironbar.clients.borrow_mut().workspaces();
|
||||
// Subscribe & send events
|
||||
spawn(async move {
|
||||
let mut srx = {
|
||||
let client =
|
||||
Compositor::get_workspace_client().expect("Failed to get workspace client");
|
||||
client.subscribe_workspace_change()
|
||||
};
|
||||
let mut srx = client.subscribe_workspace_change();
|
||||
|
||||
trace!("Set up workspace subscription");
|
||||
|
||||
|
@ -171,13 +168,13 @@ impl Module<gtk::Box> for WorkspacesModule {
|
|||
}
|
||||
});
|
||||
|
||||
let client = context.client::<dyn WorkspaceClient>();
|
||||
|
||||
// Change workspace focus
|
||||
spawn(async move {
|
||||
trace!("Setting up UI event handler");
|
||||
|
||||
while let Some(name) = rx.recv().await {
|
||||
let client =
|
||||
Compositor::get_workspace_client().expect("Failed to get workspace client");
|
||||
client.focus(name)?;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue