mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-07-03 03:31:03 +02:00
refactor: update gtk/glib, remove glib channels
This is a major refactor which updates GTK, GLib and GTK Layer Shell to their latest versions. GLib channels, previously used for receiving events on the GLib Main Context thread have been deprecated and a new method for running Futures on the main thread has been added instead. This commit also replaces all the deprecated code with this. As part of the above, a bug was uncovered related to creating the GLib main context inside the Tokio runtime. Spawning of Tokio tasks has been refactored to fix this.
This commit is contained in:
parent
2c2f1c1243
commit
bea442ed96
39 changed files with 426 additions and 465 deletions
|
@ -5,7 +5,8 @@ use crate::image::new_icon_button;
|
|||
use crate::modules::{
|
||||
Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, PopupButton, WidgetContext,
|
||||
};
|
||||
use crate::try_send;
|
||||
use crate::{glib_recv, spawn, try_send};
|
||||
use glib::Propagation;
|
||||
use gtk::gdk_pixbuf::Pixbuf;
|
||||
use gtk::gio::{Cancellable, MemoryInputStream};
|
||||
use gtk::prelude::*;
|
||||
|
@ -13,8 +14,7 @@ use gtk::{Button, EventBox, Image, Label, Orientation, RadioButton, Widget};
|
|||
use serde::Deserialize;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use tokio::spawn;
|
||||
use tokio::sync::mpsc::{Receiver, Sender};
|
||||
use tokio::sync::{broadcast, mpsc};
|
||||
use tracing::{debug, error};
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
|
@ -72,8 +72,8 @@ impl Module<Button> for ClipboardModule {
|
|||
fn spawn_controller(
|
||||
&self,
|
||||
_info: &ModuleInfo,
|
||||
tx: Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
||||
mut rx: Receiver<Self::ReceiveMessage>,
|
||||
tx: mpsc::Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
||||
mut rx: mpsc::Receiver<Self::ReceiveMessage>,
|
||||
) -> color_eyre::Result<()> {
|
||||
let max_items = self.max_items;
|
||||
|
||||
|
@ -129,19 +129,14 @@ impl Module<Button> for ClipboardModule {
|
|||
let button = new_icon_button(&self.icon, info.icon_theme, self.icon_size);
|
||||
button.style_context().add_class("btn");
|
||||
|
||||
let tx = context.tx.clone();
|
||||
button.connect_clicked(move |button| {
|
||||
try_send!(
|
||||
context.tx,
|
||||
ModuleUpdateEvent::TogglePopup(button.popup_id())
|
||||
);
|
||||
try_send!(tx, ModuleUpdateEvent::TogglePopup(button.popup_id()));
|
||||
});
|
||||
|
||||
// we need to bind to the receiver as the channel does not open
|
||||
// until the popup is first opened.
|
||||
context.widget_rx.attach(None, |_| Continue(true));
|
||||
|
||||
let rx = context.subscribe();
|
||||
let popup = self
|
||||
.into_popup(context.controller_tx, context.popup_rx, info)
|
||||
.into_popup(context.controller_tx, rx, info)
|
||||
.into_popup_parts(vec![&button]);
|
||||
|
||||
Ok(ModuleParts::new(button, popup))
|
||||
|
@ -149,8 +144,8 @@ impl Module<Button> for ClipboardModule {
|
|||
|
||||
fn into_popup(
|
||||
self,
|
||||
tx: Sender<Self::ReceiveMessage>,
|
||||
rx: glib::Receiver<Self::SendMessage>,
|
||||
tx: mpsc::Sender<Self::ReceiveMessage>,
|
||||
mut rx: broadcast::Receiver<Self::SendMessage>,
|
||||
_info: &ModuleInfo,
|
||||
) -> Option<gtk::Box>
|
||||
where
|
||||
|
@ -168,7 +163,7 @@ impl Module<Button> for ClipboardModule {
|
|||
|
||||
{
|
||||
let hidden_option = hidden_option.clone();
|
||||
rx.attach(None, move |event| {
|
||||
glib_recv!(rx, event => {
|
||||
match event {
|
||||
ControllerEvent::Add(id, item) => {
|
||||
debug!("Adding new value with ID {}", id);
|
||||
|
@ -234,7 +229,7 @@ impl Module<Button> for ClipboardModule {
|
|||
try_send!(tx, UIEvent::Copy(id));
|
||||
}
|
||||
|
||||
Inhibit(true)
|
||||
Propagation::Stop
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -293,8 +288,6 @@ impl Module<Button> for ClipboardModule {
|
|||
hidden_option.set_active(true);
|
||||
}
|
||||
}
|
||||
|
||||
Continue(true)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,10 @@ use std::env;
|
|||
|
||||
use chrono::{DateTime, Local, Locale};
|
||||
use color_eyre::Result;
|
||||
use glib::Continue;
|
||||
use gtk::prelude::*;
|
||||
use gtk::{Align, Button, Calendar, Label, Orientation};
|
||||
use serde::Deserialize;
|
||||
use tokio::spawn;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::sync::{broadcast, mpsc};
|
||||
use tokio::time::sleep;
|
||||
|
||||
use crate::config::CommonConfig;
|
||||
|
@ -15,7 +13,7 @@ use crate::gtk_helpers::IronbarGtkExt;
|
|||
use crate::modules::{
|
||||
Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, PopupButton, WidgetContext,
|
||||
};
|
||||
use crate::{send_async, try_send};
|
||||
use crate::{glib_recv, send_async, spawn, try_send};
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct ClockModule {
|
||||
|
@ -104,24 +102,22 @@ impl Module<Button> for ClockModule {
|
|||
label.set_angle(info.bar_position.get_angle());
|
||||
button.add(&label);
|
||||
|
||||
let tx = context.tx.clone();
|
||||
button.connect_clicked(move |button| {
|
||||
try_send!(
|
||||
context.tx,
|
||||
ModuleUpdateEvent::TogglePopup(button.popup_id())
|
||||
);
|
||||
try_send!(tx, ModuleUpdateEvent::TogglePopup(button.popup_id()));
|
||||
});
|
||||
|
||||
let format = self.format.clone();
|
||||
let locale = Locale::try_from(self.locale.as_str()).unwrap_or(Locale::POSIX);
|
||||
|
||||
context.widget_rx.attach(None, move |date| {
|
||||
let mut rx = context.subscribe();
|
||||
glib_recv!(rx, date => {
|
||||
let date_string = format!("{}", date.format_localized(&format, locale));
|
||||
label.set_label(&date_string);
|
||||
Continue(true)
|
||||
});
|
||||
|
||||
let popup = self
|
||||
.into_popup(context.controller_tx, context.popup_rx, info)
|
||||
.into_popup(context.controller_tx.clone(), context.subscribe(), info)
|
||||
.into_popup_parts(vec![&button]);
|
||||
|
||||
Ok(ModuleParts::new(button, popup))
|
||||
|
@ -130,7 +126,7 @@ impl Module<Button> for ClockModule {
|
|||
fn into_popup(
|
||||
self,
|
||||
_tx: mpsc::Sender<Self::ReceiveMessage>,
|
||||
rx: glib::Receiver<Self::SendMessage>,
|
||||
mut rx: broadcast::Receiver<Self::SendMessage>,
|
||||
_info: &ModuleInfo,
|
||||
) -> Option<gtk::Box> {
|
||||
let container = gtk::Box::new(Orientation::Vertical, 0);
|
||||
|
@ -147,10 +143,9 @@ impl Module<Button> for ClockModule {
|
|||
let format = self.format_popup;
|
||||
let locale = Locale::try_from(self.locale.as_str()).unwrap_or(Locale::POSIX);
|
||||
|
||||
rx.attach(None, move |date| {
|
||||
glib_recv!(rx, date => {
|
||||
let date_string = format!("{}", date.format_localized(&format, locale));
|
||||
clock.set_label(&date_string);
|
||||
Continue(true)
|
||||
});
|
||||
|
||||
container.show_all();
|
||||
|
|
|
@ -30,7 +30,6 @@ impl CustomWidget for ButtonWidget {
|
|||
|
||||
dynamic_string(&text, move |string| {
|
||||
label.set_markup(&string);
|
||||
Continue(true)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -34,8 +34,6 @@ impl CustomWidget for ImageWidget {
|
|||
dynamic_string(&self.src, move |src| {
|
||||
ImageProvider::parse(&src, &icon_theme, false, self.size)
|
||||
.map(|image| image.load_into_image(gtk_image.clone()));
|
||||
|
||||
Continue(true)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ impl CustomWidget for LabelWidget {
|
|||
let label = label.clone();
|
||||
dynamic_string(&self.label, move |string| {
|
||||
label.set_markup(&string);
|
||||
Continue(true)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -16,15 +16,14 @@ use crate::modules::{
|
|||
wrap_widget, Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, WidgetContext,
|
||||
};
|
||||
use crate::script::Script;
|
||||
use crate::send_async;
|
||||
use crate::{send_async, spawn};
|
||||
use color_eyre::{Report, Result};
|
||||
use gtk::prelude::*;
|
||||
use gtk::{Button, IconTheme, Orientation};
|
||||
use serde::Deserialize;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use tokio::spawn;
|
||||
use tokio::sync::mpsc::{Receiver, Sender};
|
||||
use tokio::sync::{broadcast, mpsc};
|
||||
use tracing::{debug, error};
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
|
@ -59,7 +58,7 @@ pub enum Widget {
|
|||
|
||||
#[derive(Clone)]
|
||||
struct CustomWidgetContext<'a> {
|
||||
tx: &'a Sender<ExecEvent>,
|
||||
tx: &'a mpsc::Sender<ExecEvent>,
|
||||
bar_orientation: Orientation,
|
||||
icon_theme: &'a IconTheme,
|
||||
popup_buttons: Rc<RefCell<Vec<Button>>>,
|
||||
|
@ -159,8 +158,8 @@ impl Module<gtk::Box> for CustomModule {
|
|||
fn spawn_controller(
|
||||
&self,
|
||||
_info: &ModuleInfo,
|
||||
tx: Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
||||
mut rx: Receiver<Self::ReceiveMessage>,
|
||||
tx: mpsc::Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
||||
mut rx: mpsc::Receiver<Self::ReceiveMessage>,
|
||||
) -> Result<()> {
|
||||
spawn(async move {
|
||||
while let Some(event) = rx.recv().await {
|
||||
|
@ -213,7 +212,7 @@ impl Module<gtk::Box> for CustomModule {
|
|||
});
|
||||
|
||||
let popup = self
|
||||
.into_popup(context.controller_tx, context.popup_rx, info)
|
||||
.into_popup(context.controller_tx.clone(), context.subscribe(), info)
|
||||
.into_popup_parts_owned(popup_buttons.take());
|
||||
|
||||
Ok(ModuleParts {
|
||||
|
@ -224,8 +223,8 @@ impl Module<gtk::Box> for CustomModule {
|
|||
|
||||
fn into_popup(
|
||||
self,
|
||||
tx: Sender<Self::ReceiveMessage>,
|
||||
_rx: glib::Receiver<Self::SendMessage>,
|
||||
tx: mpsc::Sender<Self::ReceiveMessage>,
|
||||
_rx: broadcast::Receiver<Self::SendMessage>,
|
||||
info: &ModuleInfo,
|
||||
) -> Option<gtk::Box>
|
||||
where
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use gtk::prelude::*;
|
||||
use gtk::ProgressBar;
|
||||
use serde::Deserialize;
|
||||
use tokio::spawn;
|
||||
use tokio::sync::mpsc;
|
||||
use tracing::error;
|
||||
|
||||
use crate::dynamic_value::dynamic_string;
|
||||
use crate::modules::custom::set_length;
|
||||
use crate::script::{OutputStream, Script, ScriptInput};
|
||||
use crate::{build, send};
|
||||
use crate::{build, glib_recv_mpsc, spawn, try_send};
|
||||
|
||||
use super::{try_get_orientation, CustomWidget, CustomWidgetContext};
|
||||
|
||||
|
@ -47,13 +47,13 @@ impl CustomWidget for ProgressWidget {
|
|||
let script = Script::from(value);
|
||||
let progress = progress.clone();
|
||||
|
||||
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
||||
let (tx, mut rx) = mpsc::channel(128);
|
||||
|
||||
spawn(async move {
|
||||
script
|
||||
.run(None, move |stream, _success| match stream {
|
||||
OutputStream::Stdout(out) => match out.parse::<f64>() {
|
||||
Ok(value) => send!(tx, value),
|
||||
Ok(value) => try_send!(tx, value),
|
||||
Err(err) => error!("{err:?}"),
|
||||
},
|
||||
OutputStream::Stderr(err) => error!("{err:?}"),
|
||||
|
@ -61,10 +61,7 @@ impl CustomWidget for ProgressWidget {
|
|||
.await;
|
||||
});
|
||||
|
||||
rx.attach(None, move |value| {
|
||||
progress.set_fraction(value / self.max);
|
||||
Continue(true)
|
||||
});
|
||||
glib_recv_mpsc!(rx, value => progress.set_fraction(value / self.max));
|
||||
}
|
||||
|
||||
if let Some(text) = self.label {
|
||||
|
@ -73,7 +70,6 @@ impl CustomWidget for ProgressWidget {
|
|||
|
||||
dynamic_string(&text, move |string| {
|
||||
progress.set_text(Some(&string));
|
||||
Continue(true)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
use glib::Propagation;
|
||||
use std::cell::Cell;
|
||||
use std::ops::Neg;
|
||||
|
||||
use gtk::prelude::*;
|
||||
use gtk::Scale;
|
||||
use serde::Deserialize;
|
||||
use tokio::spawn;
|
||||
use tokio::sync::mpsc;
|
||||
use tracing::error;
|
||||
|
||||
use crate::modules::custom::set_length;
|
||||
use crate::script::{OutputStream, Script, ScriptInput};
|
||||
use crate::{build, send, try_send};
|
||||
use crate::{build, glib_recv_mpsc, spawn, try_send};
|
||||
|
||||
use super::{try_get_orientation, CustomWidget, CustomWidgetContext, ExecEvent};
|
||||
|
||||
|
@ -77,7 +78,7 @@ impl CustomWidget for SliderWidget {
|
|||
};
|
||||
|
||||
scale.set_value(value + delta);
|
||||
Inhibit(false)
|
||||
Propagation::Proceed
|
||||
});
|
||||
|
||||
scale.connect_change_value(move |_, _, val| {
|
||||
|
@ -97,7 +98,7 @@ impl CustomWidget for SliderWidget {
|
|||
prev_value.set(val);
|
||||
}
|
||||
|
||||
Inhibit(false)
|
||||
Propagation::Proceed
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -105,13 +106,13 @@ impl CustomWidget for SliderWidget {
|
|||
let script = Script::from(value);
|
||||
let scale = scale.clone();
|
||||
|
||||
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
||||
let (tx, mut rx) = mpsc::channel(128);
|
||||
|
||||
spawn(async move {
|
||||
script
|
||||
.run(None, move |stream, _success| match stream {
|
||||
OutputStream::Stdout(out) => match out.parse() {
|
||||
Ok(value) => send!(tx, value),
|
||||
Ok(value) => try_send!(tx, value),
|
||||
Err(err) => error!("{err:?}"),
|
||||
},
|
||||
OutputStream::Stderr(err) => error!("{err:?}"),
|
||||
|
@ -119,10 +120,7 @@ impl CustomWidget for SliderWidget {
|
|||
.await;
|
||||
});
|
||||
|
||||
rx.attach(None, move |value| {
|
||||
scale.set_value(value);
|
||||
Continue(true)
|
||||
});
|
||||
glib_recv_mpsc!(rx, value => scale.set_value(value));
|
||||
}
|
||||
|
||||
scale
|
||||
|
|
|
@ -3,13 +3,11 @@ use crate::config::{CommonConfig, TruncateMode};
|
|||
use crate::gtk_helpers::IronbarGtkExt;
|
||||
use crate::image::ImageProvider;
|
||||
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
||||
use crate::{lock, send_async, try_send};
|
||||
use crate::{glib_recv, lock, send_async, spawn, try_send};
|
||||
use color_eyre::Result;
|
||||
use glib::Continue;
|
||||
use gtk::prelude::*;
|
||||
use gtk::Label;
|
||||
use serde::Deserialize;
|
||||
use tokio::spawn;
|
||||
use tokio::sync::mpsc::{Receiver, Sender};
|
||||
use tracing::debug;
|
||||
|
||||
|
@ -141,7 +139,7 @@ impl Module<gtk::Box> for FocusedModule {
|
|||
|
||||
{
|
||||
let icon_theme = icon_theme.clone();
|
||||
context.widget_rx.attach(None, move |data| {
|
||||
glib_recv!(context.subscribe(), data => {
|
||||
if let Some((name, id)) = data {
|
||||
if self.show_icon {
|
||||
match ImageProvider::parse(&id, &icon_theme, true, self.icon_size)
|
||||
|
@ -160,8 +158,6 @@ impl Module<gtk::Box> for FocusedModule {
|
|||
icon.hide();
|
||||
label.hide();
|
||||
}
|
||||
|
||||
Continue(true)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use crate::config::CommonConfig;
|
||||
use crate::dynamic_value::dynamic_string;
|
||||
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
||||
use crate::try_send;
|
||||
use crate::{glib_recv, try_send};
|
||||
use color_eyre::Result;
|
||||
use glib::Continue;
|
||||
use gtk::prelude::*;
|
||||
use gtk::Label;
|
||||
use serde::Deserialize;
|
||||
|
@ -42,7 +41,6 @@ impl Module<Label> for LabelModule {
|
|||
) -> Result<()> {
|
||||
dynamic_string(&self.label, move |string| {
|
||||
try_send!(tx, ModuleUpdateEvent::Update(string));
|
||||
Continue(true)
|
||||
});
|
||||
|
||||
Ok(())
|
||||
|
@ -58,10 +56,7 @@ impl Module<Label> for LabelModule {
|
|||
|
||||
{
|
||||
let label = label.clone();
|
||||
context.widget_rx.attach(None, move |string| {
|
||||
label.set_markup(&string);
|
||||
Continue(true)
|
||||
});
|
||||
glib_recv!(context.subscribe(), string => label.set_markup(&string));
|
||||
}
|
||||
|
||||
Ok(ModuleParts {
|
||||
|
|
|
@ -7,6 +7,7 @@ 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};
|
||||
use indexmap::IndexMap;
|
||||
|
@ -258,7 +259,7 @@ impl ItemButton {
|
|||
try_send!(tx, ModuleUpdateEvent::ClosePopup);
|
||||
}
|
||||
|
||||
Inhibit(false)
|
||||
Propagation::Proceed
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -283,7 +284,7 @@ impl ItemButton {
|
|||
try_send!(tx, ModuleUpdateEvent::ClosePopup);
|
||||
}
|
||||
|
||||
Inhibit(false)
|
||||
Propagation::Proceed
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -10,17 +10,15 @@ use crate::modules::launcher::item::AppearanceOptions;
|
|||
use crate::modules::{
|
||||
Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, WidgetContext,
|
||||
};
|
||||
use crate::{arc_mut, lock, send_async, try_send, write_lock};
|
||||
use crate::{arc_mut, glib_recv, lock, send_async, spawn, try_send, write_lock};
|
||||
use color_eyre::{Help, Report};
|
||||
use glib::Continue;
|
||||
use gtk::prelude::*;
|
||||
use gtk::{Button, Orientation};
|
||||
use indexmap::IndexMap;
|
||||
use serde::Deserialize;
|
||||
use std::process::{Command, Stdio};
|
||||
use std::sync::Arc;
|
||||
use tokio::spawn;
|
||||
use tokio::sync::mpsc::{Receiver, Sender};
|
||||
use tokio::sync::{broadcast, mpsc};
|
||||
use tracing::{debug, error, trace};
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
|
@ -92,8 +90,8 @@ impl Module<gtk::Box> for LauncherModule {
|
|||
fn spawn_controller(
|
||||
&self,
|
||||
_info: &ModuleInfo,
|
||||
tx: Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
||||
mut rx: Receiver<Self::ReceiveMessage>,
|
||||
tx: mpsc::Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
||||
mut rx: mpsc::Receiver<Self::ReceiveMessage>,
|
||||
) -> crate::Result<()> {
|
||||
let items = self
|
||||
.favorites
|
||||
|
@ -338,7 +336,9 @@ impl Module<gtk::Box> for LauncherModule {
|
|||
|
||||
let mut buttons = IndexMap::<String, ItemButton>::new();
|
||||
|
||||
context.widget_rx.attach(None, move |event| {
|
||||
let tx = context.tx.clone();
|
||||
let mut rx = context.subscribe();
|
||||
glib_recv!(rx, event => {
|
||||
match event {
|
||||
LauncherUpdate::AddItem(item) => {
|
||||
debug!("Adding item with id {}", item.app_id);
|
||||
|
@ -351,7 +351,7 @@ impl Module<gtk::Box> for LauncherModule {
|
|||
appearance_options,
|
||||
&icon_theme,
|
||||
bar_position,
|
||||
&context.tx,
|
||||
&tx,
|
||||
&controller_tx,
|
||||
);
|
||||
|
||||
|
@ -411,13 +411,12 @@ impl Module<gtk::Box> for LauncherModule {
|
|||
}
|
||||
LauncherUpdate::Hover(_) => {}
|
||||
};
|
||||
|
||||
Continue(true)
|
||||
});
|
||||
}
|
||||
|
||||
let rx = context.subscribe();
|
||||
let popup = self
|
||||
.into_popup(context.controller_tx, context.popup_rx, info)
|
||||
.into_popup(context.controller_tx, rx, info)
|
||||
.into_popup_parts(vec![]); // since item buttons are dynamic, they pass their geometry directly
|
||||
|
||||
Ok(ModuleParts {
|
||||
|
@ -428,8 +427,8 @@ impl Module<gtk::Box> for LauncherModule {
|
|||
|
||||
fn into_popup(
|
||||
self,
|
||||
controller_tx: Sender<Self::ReceiveMessage>,
|
||||
rx: glib::Receiver<Self::SendMessage>,
|
||||
controller_tx: mpsc::Sender<Self::ReceiveMessage>,
|
||||
mut rx: broadcast::Receiver<Self::SendMessage>,
|
||||
_info: &ModuleInfo,
|
||||
) -> Option<gtk::Box> {
|
||||
const MAX_WIDTH: i32 = 250;
|
||||
|
@ -445,7 +444,7 @@ impl Module<gtk::Box> for LauncherModule {
|
|||
|
||||
{
|
||||
let container = container.clone();
|
||||
rx.attach(None, move |event| {
|
||||
glib_recv!(rx, event => {
|
||||
match event {
|
||||
LauncherUpdate::AddItem(item) => {
|
||||
let app_id = item.app_id.clone();
|
||||
|
@ -532,8 +531,6 @@ impl Module<gtk::Box> for LauncherModule {
|
|||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Continue(true)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use std::cell::RefCell;
|
||||
use std::fmt::Debug;
|
||||
use std::rc::Rc;
|
||||
|
||||
use color_eyre::Result;
|
||||
|
@ -6,14 +7,13 @@ use glib::IsA;
|
|||
use gtk::gdk::{EventMask, Monitor};
|
||||
use gtk::prelude::*;
|
||||
use gtk::{Application, Button, EventBox, IconTheme, Orientation, Revealer, Widget};
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::sync::{broadcast, mpsc};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::bridge_channel::BridgeChannel;
|
||||
use crate::config::{BarPosition, CommonConfig, TransitionType};
|
||||
use crate::gtk_helpers::{IronbarGtkExt, WidgetGeometry};
|
||||
use crate::popup::Popup;
|
||||
use crate::send;
|
||||
use crate::{glib_recv_mpsc, send};
|
||||
|
||||
#[cfg(feature = "clipboard")]
|
||||
pub mod clipboard;
|
||||
|
@ -56,8 +56,8 @@ pub struct ModuleInfo<'a> {
|
|||
pub icon_theme: &'a IconTheme,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ModuleUpdateEvent<T> {
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ModuleUpdateEvent<T: Clone> {
|
||||
/// Sends an update to the module UI.
|
||||
Update(T),
|
||||
/// Toggles the open state of the popup.
|
||||
|
@ -71,12 +71,25 @@ pub enum ModuleUpdateEvent<T> {
|
|||
ClosePopup,
|
||||
}
|
||||
|
||||
pub struct WidgetContext<TSend, TReceive> {
|
||||
pub struct WidgetContext<TSend, TReceive>
|
||||
where
|
||||
TSend: Clone,
|
||||
{
|
||||
pub id: usize,
|
||||
pub tx: mpsc::Sender<ModuleUpdateEvent<TSend>>,
|
||||
pub update_tx: broadcast::Sender<TSend>,
|
||||
pub controller_tx: mpsc::Sender<TReceive>,
|
||||
pub widget_rx: glib::Receiver<TSend>,
|
||||
pub popup_rx: glib::Receiver<TSend>,
|
||||
|
||||
_update_rx: broadcast::Receiver<TSend>,
|
||||
}
|
||||
|
||||
impl<TSend, TReceive> WidgetContext<TSend, TReceive>
|
||||
where
|
||||
TSend: Clone,
|
||||
{
|
||||
pub fn subscribe(&self) -> broadcast::Receiver<TSend> {
|
||||
self.update_tx.subscribe()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ModuleParts<W: IsA<Widget>> {
|
||||
|
@ -151,18 +164,22 @@ where
|
|||
info: &ModuleInfo,
|
||||
tx: mpsc::Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
||||
rx: mpsc::Receiver<Self::ReceiveMessage>,
|
||||
) -> Result<()>;
|
||||
) -> Result<()>
|
||||
where
|
||||
<Self as Module<W>>::SendMessage: Clone;
|
||||
|
||||
fn into_widget(
|
||||
self,
|
||||
context: WidgetContext<Self::SendMessage, Self::ReceiveMessage>,
|
||||
info: &ModuleInfo,
|
||||
) -> Result<ModuleParts<W>>;
|
||||
) -> Result<ModuleParts<W>>
|
||||
where
|
||||
<Self as Module<W>>::SendMessage: Clone;
|
||||
|
||||
fn into_popup(
|
||||
self,
|
||||
_tx: mpsc::Sender<Self::ReceiveMessage>,
|
||||
_rx: glib::Receiver<Self::SendMessage>,
|
||||
_rx: broadcast::Receiver<Self::SendMessage>,
|
||||
_info: &ModuleInfo,
|
||||
) -> Option<gtk::Box>
|
||||
where
|
||||
|
@ -184,22 +201,21 @@ pub fn create_module<TModule, TWidget, TSend, TRec>(
|
|||
where
|
||||
TModule: Module<TWidget, SendMessage = TSend, ReceiveMessage = TRec>,
|
||||
TWidget: IsA<Widget>,
|
||||
TSend: Clone + Send + 'static,
|
||||
TSend: Debug + Clone + Send + 'static,
|
||||
{
|
||||
let (w_tx, w_rx) = glib::MainContext::channel::<TSend>(glib::PRIORITY_DEFAULT);
|
||||
let (p_tx, p_rx) = glib::MainContext::channel::<TSend>(glib::PRIORITY_DEFAULT);
|
||||
let (ui_tx, ui_rx) = mpsc::channel::<ModuleUpdateEvent<TSend>>(64);
|
||||
let (controller_tx, controller_rx) = mpsc::channel::<TRec>(64);
|
||||
|
||||
let channel = BridgeChannel::<ModuleUpdateEvent<TSend>>::new();
|
||||
let (ui_tx, ui_rx) = mpsc::channel::<TRec>(16);
|
||||
let (tx, rx) = broadcast::channel(64);
|
||||
|
||||
module.spawn_controller(info, channel.create_sender(), ui_rx)?;
|
||||
module.spawn_controller(info, ui_tx.clone(), controller_rx)?;
|
||||
|
||||
let context = WidgetContext {
|
||||
id,
|
||||
widget_rx: w_rx,
|
||||
popup_rx: p_rx,
|
||||
tx: channel.create_sender(),
|
||||
controller_tx: ui_tx,
|
||||
tx: ui_tx,
|
||||
update_tx: tx.clone(),
|
||||
controller_tx,
|
||||
_update_rx: rx,
|
||||
};
|
||||
|
||||
let module_name = TModule::name();
|
||||
|
@ -209,27 +225,16 @@ where
|
|||
module_parts.widget.add_class("widget");
|
||||
module_parts.widget.add_class(module_name);
|
||||
|
||||
let has_popup = if let Some(popup_content) = module_parts.popup.clone() {
|
||||
if let Some(popup_content) = module_parts.popup.clone() {
|
||||
popup_content
|
||||
.container
|
||||
.style_context()
|
||||
.add_class(&format!("popup-{module_name}"));
|
||||
|
||||
register_popup_content(popup, id, instance_name, popup_content);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
}
|
||||
|
||||
setup_receiver(
|
||||
channel,
|
||||
w_tx,
|
||||
p_tx,
|
||||
popup.clone(),
|
||||
module_name,
|
||||
id,
|
||||
has_popup,
|
||||
);
|
||||
setup_receiver(tx, ui_rx, popup.clone(), module_name, id);
|
||||
|
||||
Ok(module_parts)
|
||||
}
|
||||
|
@ -250,28 +255,22 @@ fn register_popup_content(
|
|||
/// Handles opening/closing popups
|
||||
/// and communicating update messages between controllers and widgets/popups.
|
||||
fn setup_receiver<TSend>(
|
||||
channel: BridgeChannel<ModuleUpdateEvent<TSend>>,
|
||||
w_tx: glib::Sender<TSend>,
|
||||
p_tx: glib::Sender<TSend>,
|
||||
tx: broadcast::Sender<TSend>,
|
||||
mut rx: mpsc::Receiver<ModuleUpdateEvent<TSend>>,
|
||||
popup: Rc<RefCell<Popup>>,
|
||||
name: &'static str,
|
||||
id: usize,
|
||||
has_popup: bool,
|
||||
) where
|
||||
TSend: Clone + Send + 'static,
|
||||
TSend: Debug + Clone + Send + 'static,
|
||||
{
|
||||
// some rare cases can cause the popup to incorrectly calculate its size on first open.
|
||||
// we can fix that by just force re-rendering it on its first open.
|
||||
let mut has_popup_opened = false;
|
||||
|
||||
channel.recv(move |ev| {
|
||||
glib_recv_mpsc!(rx, ev => {
|
||||
match ev {
|
||||
ModuleUpdateEvent::Update(update) => {
|
||||
if has_popup {
|
||||
send!(p_tx, update.clone());
|
||||
}
|
||||
|
||||
send!(w_tx, update);
|
||||
send!(tx, update);
|
||||
}
|
||||
ModuleUpdateEvent::TogglePopup(button_id) => {
|
||||
debug!("Toggling popup for {} [#{}]", name, id);
|
||||
|
@ -321,8 +320,6 @@ fn setup_receiver<TSend>(
|
|||
popup.hide();
|
||||
}
|
||||
}
|
||||
|
||||
Continue(true)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -4,12 +4,11 @@ use std::sync::Arc;
|
|||
use std::time::Duration;
|
||||
|
||||
use color_eyre::Result;
|
||||
use glib::{Continue, PropertySet};
|
||||
use glib::{Propagation, PropertySet};
|
||||
use gtk::prelude::*;
|
||||
use gtk::{Button, IconTheme, Label, Orientation, Scale};
|
||||
use regex::Regex;
|
||||
use tokio::spawn;
|
||||
use tokio::sync::mpsc::{Receiver, Sender};
|
||||
use tokio::sync::{broadcast, mpsc};
|
||||
use tracing::error;
|
||||
|
||||
use crate::clients::music::{
|
||||
|
@ -21,7 +20,7 @@ use crate::modules::PopupButton;
|
|||
use crate::modules::{
|
||||
Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, WidgetContext,
|
||||
};
|
||||
use crate::{send_async, try_send};
|
||||
use crate::{glib_recv, send_async, spawn, try_send};
|
||||
|
||||
pub use self::config::MusicModule;
|
||||
use self::config::PlayerType;
|
||||
|
@ -91,8 +90,8 @@ impl Module<Button> for MusicModule {
|
|||
fn spawn_controller(
|
||||
&self,
|
||||
_info: &ModuleInfo,
|
||||
tx: Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
||||
mut rx: Receiver<Self::ReceiveMessage>,
|
||||
tx: mpsc::Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
||||
mut rx: mpsc::Receiver<Self::ReceiveMessage>,
|
||||
) -> Result<()> {
|
||||
let format = self.format.clone();
|
||||
|
||||
|
@ -213,11 +212,13 @@ impl Module<Button> for MusicModule {
|
|||
|
||||
{
|
||||
let button = button.clone();
|
||||
let tx = context.tx.clone();
|
||||
|
||||
context.widget_rx.attach(None, move |event| {
|
||||
let tx = context.tx.clone();
|
||||
let mut rx = context.subscribe();
|
||||
|
||||
glib_recv!(rx, event => {
|
||||
let ControllerEvent::Update(mut event) = event else {
|
||||
return Continue(true);
|
||||
continue;
|
||||
};
|
||||
|
||||
if let Some(event) = event.take() {
|
||||
|
@ -248,13 +249,12 @@ impl Module<Button> for MusicModule {
|
|||
button.hide();
|
||||
try_send!(tx, ModuleUpdateEvent::ClosePopup);
|
||||
}
|
||||
|
||||
Continue(true)
|
||||
});
|
||||
};
|
||||
|
||||
let rx = context.subscribe();
|
||||
let popup = self
|
||||
.into_popup(context.controller_tx, context.popup_rx, info)
|
||||
.into_popup(context.controller_tx, rx, info)
|
||||
.into_popup_parts(vec![&button]);
|
||||
|
||||
Ok(ModuleParts::new(button, popup))
|
||||
|
@ -262,8 +262,8 @@ impl Module<Button> for MusicModule {
|
|||
|
||||
fn into_popup(
|
||||
self,
|
||||
tx: Sender<Self::ReceiveMessage>,
|
||||
rx: glib::Receiver<Self::SendMessage>,
|
||||
tx: mpsc::Sender<Self::ReceiveMessage>,
|
||||
mut rx: broadcast::Receiver<Self::SendMessage>,
|
||||
info: &ModuleInfo,
|
||||
) -> Option<gtk::Box> {
|
||||
let icon_theme = info.icon_theme;
|
||||
|
@ -355,7 +355,7 @@ impl Module<Button> for MusicModule {
|
|||
let tx_vol = tx.clone();
|
||||
volume_slider.connect_change_value(move |_, _, val| {
|
||||
try_send!(tx_vol, PlayerCommand::Volume(val as u8));
|
||||
Inhibit(false)
|
||||
Propagation::Proceed
|
||||
});
|
||||
|
||||
let progress_box = gtk::Box::new(Orientation::Horizontal, 5);
|
||||
|
@ -380,7 +380,7 @@ impl Module<Button> for MusicModule {
|
|||
let drag_lock = drag_lock.clone();
|
||||
progress.connect_button_press_event(move |_, _| {
|
||||
drag_lock.set(true);
|
||||
Inhibit(false)
|
||||
Propagation::Proceed
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -391,7 +391,7 @@ impl Module<Button> for MusicModule {
|
|||
try_send!(tx, PlayerCommand::Seek(Duration::from_secs_f64(value)));
|
||||
|
||||
drag_lock.set(false);
|
||||
Inhibit(false)
|
||||
Propagation::Proceed
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -402,7 +402,7 @@ impl Module<Button> for MusicModule {
|
|||
let image_size = self.cover_image_size;
|
||||
|
||||
let mut prev_cover = None;
|
||||
rx.attach(None, move |event| {
|
||||
glib_recv!(rx, event => {
|
||||
match event {
|
||||
ControllerEvent::Update(Some(update)) => {
|
||||
// only update art when album changes
|
||||
|
@ -487,8 +487,6 @@ impl Module<Button> for MusicModule {
|
|||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
Continue(true)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
use crate::config::CommonConfig;
|
||||
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
||||
use crate::script::{OutputStream, Script, ScriptMode};
|
||||
use crate::try_send;
|
||||
use crate::{glib_recv, spawn, try_send};
|
||||
use color_eyre::{Help, Report, Result};
|
||||
use gtk::prelude::*;
|
||||
use gtk::Label;
|
||||
use serde::Deserialize;
|
||||
use tokio::spawn;
|
||||
use tokio::sync::mpsc::{Receiver, Sender};
|
||||
use tracing::error;
|
||||
|
||||
|
@ -89,10 +88,7 @@ impl Module<Label> for ScriptModule {
|
|||
|
||||
{
|
||||
let label = label.clone();
|
||||
context.widget_rx.attach(None, move |s| {
|
||||
label.set_markup(s.as_str());
|
||||
Continue(true)
|
||||
});
|
||||
glib_recv!(context.subscribe(), s => label.set_markup(s.as_str()));
|
||||
}
|
||||
|
||||
Ok(ModuleParts {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::config::CommonConfig;
|
||||
use crate::gtk_helpers::IronbarGtkExt;
|
||||
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
||||
use crate::send_async;
|
||||
use crate::{glib_recv, send_async, spawn};
|
||||
use color_eyre::Result;
|
||||
use gtk::prelude::*;
|
||||
use gtk::Label;
|
||||
|
@ -10,7 +10,6 @@ use serde::Deserialize;
|
|||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
use sysinfo::{ComponentExt, CpuExt, DiskExt, NetworkExt, RefreshKind, System, SystemExt};
|
||||
use tokio::spawn;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::sync::mpsc::{Receiver, Sender};
|
||||
use tokio::time::sleep;
|
||||
|
@ -205,7 +204,7 @@ impl Module<gtk::Box> for SysInfoModule {
|
|||
|
||||
{
|
||||
let formats = self.format;
|
||||
context.widget_rx.attach(None, move |info| {
|
||||
glib_recv!(context.subscribe(), info => {
|
||||
for (format, label) in formats.iter().zip(labels.clone()) {
|
||||
let format_compiled = re.replace_all(format, |caps: &Captures| {
|
||||
info.get(&caps[1])
|
||||
|
@ -215,8 +214,6 @@ impl Module<gtk::Box> for SysInfoModule {
|
|||
|
||||
label.set_markup(format_compiled.as_ref());
|
||||
}
|
||||
|
||||
Continue(true)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::clients::system_tray::get_tray_event_client;
|
||||
use crate::config::CommonConfig;
|
||||
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
||||
use crate::{await_sync, try_send};
|
||||
use crate::{await_sync, glib_recv, spawn, try_send};
|
||||
use color_eyre::Result;
|
||||
use glib::ffi::g_strfreev;
|
||||
use glib::translate::ToGlibPtr;
|
||||
|
@ -20,7 +20,6 @@ use std::ptr;
|
|||
use system_tray::message::menu::{MenuItem as MenuItemInfo, MenuType};
|
||||
use system_tray::message::tray::StatusNotifierItem;
|
||||
use system_tray::message::{NotifierItemCommand, NotifierItemMessage};
|
||||
use tokio::spawn;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::sync::mpsc::{Receiver, Sender};
|
||||
|
||||
|
@ -58,9 +57,9 @@ fn get_icon_theme_search_paths(icon_theme: &IconTheme) -> HashSet<String> {
|
|||
|
||||
/// Attempts to get a GTK `Image` component
|
||||
/// for the status notifier item's icon.
|
||||
fn get_image_from_icon_name(item: &StatusNotifierItem, icon_theme: IconTheme) -> Option<Image> {
|
||||
fn get_image_from_icon_name(item: &StatusNotifierItem, icon_theme: &IconTheme) -> Option<Image> {
|
||||
if let Some(path) = item.icon_theme_path.as_ref() {
|
||||
if !path.is_empty() && !get_icon_theme_search_paths(&icon_theme).contains(path) {
|
||||
if !path.is_empty() && !get_icon_theme_search_paths(icon_theme).contains(path) {
|
||||
icon_theme.append_search_path(path);
|
||||
}
|
||||
}
|
||||
|
@ -209,7 +208,7 @@ impl Module<MenuBar> for TrayModule {
|
|||
let icon_theme = info.icon_theme.clone();
|
||||
|
||||
// listen for UI updates
|
||||
context.widget_rx.attach(None, move |update| {
|
||||
glib_recv!(context.subscribe(), update => {
|
||||
match update {
|
||||
NotifierItemMessage::Update {
|
||||
item,
|
||||
|
@ -221,7 +220,7 @@ impl Module<MenuBar> for TrayModule {
|
|||
let menu_item = MenuItem::new();
|
||||
menu_item.style_context().add_class("item");
|
||||
|
||||
get_image_from_icon_name(&item, icon_theme.clone())
|
||||
get_image_from_icon_name(&item, &icon_theme)
|
||||
.or_else(|| get_image_from_pixmap(&item))
|
||||
.map_or_else(
|
||||
|| {
|
||||
|
@ -262,8 +261,6 @@ impl Module<MenuBar> for TrayModule {
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
Continue(true)
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -3,8 +3,7 @@ use futures_lite::stream::StreamExt;
|
|||
use gtk::{prelude::*, Button};
|
||||
use gtk::{Label, Orientation};
|
||||
use serde::Deserialize;
|
||||
use tokio::spawn;
|
||||
use tokio::sync::mpsc::{Receiver, Sender};
|
||||
use tokio::sync::{broadcast, mpsc};
|
||||
use upower_dbus::BatteryState;
|
||||
use zbus;
|
||||
|
||||
|
@ -16,7 +15,7 @@ use crate::modules::PopupButton;
|
|||
use crate::modules::{
|
||||
Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, WidgetContext,
|
||||
};
|
||||
use crate::{await_sync, error, send_async, try_send};
|
||||
use crate::{await_sync, error, glib_recv, send_async, spawn, try_send};
|
||||
|
||||
const DAY: i64 = 24 * 60 * 60;
|
||||
const HOUR: i64 = 60 * 60;
|
||||
|
@ -62,8 +61,8 @@ impl Module<gtk::Button> for UpowerModule {
|
|||
fn spawn_controller(
|
||||
&self,
|
||||
_info: &ModuleInfo,
|
||||
tx: Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
||||
_rx: Receiver<Self::ReceiveMessage>,
|
||||
tx: mpsc::Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
||||
_rx: mpsc::Receiver<Self::ReceiveMessage>,
|
||||
) -> Result<()> {
|
||||
spawn(async move {
|
||||
// await_sync due to strange "higher-ranked lifetime error"
|
||||
|
@ -174,29 +173,28 @@ impl Module<gtk::Button> for UpowerModule {
|
|||
container.add(&label);
|
||||
button.add(&container);
|
||||
|
||||
let tx = context.tx.clone();
|
||||
button.connect_clicked(move |button| {
|
||||
try_send!(
|
||||
context.tx,
|
||||
ModuleUpdateEvent::TogglePopup(button.popup_id())
|
||||
);
|
||||
try_send!(tx, ModuleUpdateEvent::TogglePopup(button.popup_id()));
|
||||
});
|
||||
|
||||
label.set_angle(info.bar_position.get_angle());
|
||||
let format = self.format.clone();
|
||||
|
||||
context
|
||||
.widget_rx
|
||||
.attach(None, move |properties: UpowerProperties| {
|
||||
let format = format.replace("{percentage}", &properties.percentage.to_string());
|
||||
let icon_name = String::from("icon:") + &properties.icon_name;
|
||||
ImageProvider::parse(&icon_name, &icon_theme, false, self.icon_size)
|
||||
.map(|provider| provider.load_into_image(icon.clone()));
|
||||
label.set_markup(format.as_ref());
|
||||
Continue(true)
|
||||
});
|
||||
let mut rx = context.subscribe();
|
||||
glib_recv!(rx, properties => {
|
||||
let format = format.replace("{percentage}", &properties.percentage.to_string());
|
||||
let icon_name = String::from("icon:") + &properties.icon_name;
|
||||
|
||||
ImageProvider::parse(&icon_name, &icon_theme, false, self.icon_size)
|
||||
.map(|provider| provider.load_into_image(icon.clone()));
|
||||
|
||||
label.set_markup(format.as_ref());
|
||||
});
|
||||
|
||||
let rx = context.subscribe();
|
||||
let popup = self
|
||||
.into_popup(context.controller_tx, context.popup_rx, info)
|
||||
.into_popup(context.controller_tx, rx, info)
|
||||
.into_popup_parts(vec![&button]);
|
||||
|
||||
Ok(ModuleParts::new(button, popup))
|
||||
|
@ -204,8 +202,8 @@ impl Module<gtk::Button> for UpowerModule {
|
|||
|
||||
fn into_popup(
|
||||
self,
|
||||
_tx: Sender<Self::ReceiveMessage>,
|
||||
rx: glib::Receiver<Self::SendMessage>,
|
||||
_tx: mpsc::Sender<Self::ReceiveMessage>,
|
||||
mut rx: broadcast::Receiver<Self::SendMessage>,
|
||||
_info: &ModuleInfo,
|
||||
) -> Option<gtk::Box>
|
||||
where
|
||||
|
@ -219,7 +217,7 @@ impl Module<gtk::Button> for UpowerModule {
|
|||
label.add_class("upower-details");
|
||||
container.add(&label);
|
||||
|
||||
rx.attach(None, move |properties| {
|
||||
glib_recv!(rx, properties => {
|
||||
let state = u32_to_battery_state(properties.state);
|
||||
let format = match state {
|
||||
Ok(BatteryState::Charging | BatteryState::PendingCharge) => {
|
||||
|
@ -246,7 +244,6 @@ impl Module<gtk::Button> for UpowerModule {
|
|||
};
|
||||
|
||||
label.set_markup(&format);
|
||||
Continue(true)
|
||||
});
|
||||
|
||||
container.show_all();
|
||||
|
|
|
@ -2,14 +2,13 @@ use crate::clients::compositor::{Compositor, Visibility, Workspace, WorkspaceUpd
|
|||
use crate::config::CommonConfig;
|
||||
use crate::image::new_icon_button;
|
||||
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
||||
use crate::{send_async, try_send};
|
||||
use crate::{glib_recv, send_async, spawn, try_send};
|
||||
use color_eyre::{Report, Result};
|
||||
use gtk::prelude::*;
|
||||
use gtk::{Button, IconTheme};
|
||||
use serde::Deserialize;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use tokio::spawn;
|
||||
use tokio::sync::mpsc::{Receiver, Sender};
|
||||
use tracing::trace;
|
||||
|
||||
|
@ -205,7 +204,7 @@ impl Module<gtk::Box> for WorkspacesModule {
|
|||
// since it fires for every workspace subscriber
|
||||
let mut has_initialized = false;
|
||||
|
||||
context.widget_rx.attach(None, move |event| {
|
||||
glib_recv!(context.subscribe(), event => {
|
||||
match event {
|
||||
WorkspaceUpdate::Init(workspaces) => {
|
||||
if !has_initialized {
|
||||
|
@ -350,8 +349,6 @@ impl Module<gtk::Box> for WorkspacesModule {
|
|||
}
|
||||
WorkspaceUpdate::Update(_) => {}
|
||||
};
|
||||
|
||||
Continue(true)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue