1
0
Fork 0
mirror of https://github.com/Zedfrigg/ironbar.git synced 2025-07-01 18:51:04 +02:00

Major module refactor (#19)

* refactor: major module restructuring

Modules now implement a "controller", which allows for separation of logic from UI code and enforces a tighter structure around how modules should be written. The introduction of this change required major refactoring or even rewriting of all modules.

This also better integrates the popup into modules, making it easier for data to be passed around without fetching the same thing twice

The refactor also improves some client code, switching from `ksway` to the much more stable `swayipc-async`. Partial multi-monitor for the tray module has been added.

BREAKING CHANGE: The `mpd` module config has changed, moving the icons to their own object.
This commit is contained in:
Jake Stanger 2022-09-25 22:49:00 +01:00 committed by GitHub
parent daafa0943e
commit 720ba7bfb0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 2381 additions and 1846 deletions

View file

@ -1,12 +1,16 @@
use crate::icon;
use crate::modules::{Module, ModuleInfo};
use crate::sway::get_client;
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
use crate::sway::node::{get_node_id, get_open_windows};
use crate::sway::{get_client, get_sub_client};
use crate::{await_sync, icon};
use color_eyre::Result;
use glib::Continue;
use gtk::prelude::*;
use gtk::{IconTheme, Image, Label, Orientation};
use serde::Deserialize;
use tokio::task::spawn_blocking;
use swayipc_async::WindowChange;
use tokio::spawn;
use tokio::sync::mpsc::{Receiver, Sender};
use tracing::trace;
#[derive(Debug, Deserialize, Clone)]
pub struct FocusedModule {
@ -29,7 +33,73 @@ const fn default_icon_size() -> i32 {
}
impl Module<gtk::Box> for FocusedModule {
fn into_widget(self, _info: &ModuleInfo) -> Result<gtk::Box> {
type SendMessage = (String, String);
type ReceiveMessage = ();
fn spawn_controller(
&self,
_info: &ModuleInfo,
tx: Sender<ModuleUpdateEvent<Self::SendMessage>>,
_rx: Receiver<Self::ReceiveMessage>,
) -> Result<()> {
let focused = await_sync(async {
let sway = get_client().await;
let mut sway = sway.lock().await;
get_open_windows(&mut sway)
.await
.expect("Failed to get open windows")
.into_iter()
.find(|node| node.focused)
});
if let Some(node) = focused {
let id = get_node_id(&node);
let name = node.name.as_deref().unwrap_or(id);
tx.try_send(ModuleUpdateEvent::Update((
name.to_string(),
id.to_string(),
)))?;
}
spawn(async move {
let mut srx = {
let sway = get_sub_client();
sway.subscribe_window()
};
trace!("Set up Sway window subscription");
while let Ok(payload) = srx.recv().await {
let update = match payload.change {
WindowChange::Focus => true,
WindowChange::Title => payload.container.focused,
_ => false,
};
if update {
let node = payload.container;
let id = get_node_id(&node);
let name = node.name.as_deref().unwrap_or(id);
tx.try_send(ModuleUpdateEvent::Update((
name.to_string(),
id.to_string(),
)))
.expect("Failed to send focus update");
}
}
});
Ok(())
}
fn into_widget(
self,
context: WidgetContext<Self::SendMessage, Self::ReceiveMessage>,
_info: &ModuleInfo,
) -> Result<ModuleWidget<gtk::Box>> {
let icon_theme = IconTheme::new();
if let Some(theme) = self.icon_theme {
@ -44,59 +114,25 @@ impl Module<gtk::Box> for FocusedModule {
container.add(&icon);
container.add(&label);
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
let focused = {
let sway = get_client();
let mut sway = sway.lock().expect("Failed to get lock on Sway IPC client");
sway.get_open_windows()?
.into_iter()
.find(|node| node.focused)
};
if let Some(focused) = focused {
tx.send(focused)?;
}
spawn_blocking(move || {
let srx = {
let sway = get_client();
let mut sway = sway.lock().expect("Failed to get lock on Sway IPC client");
sway.subscribe_window()
};
while let Ok(payload) = srx.recv() {
let update = match payload.change.as_str() {
"focus" => true,
"title" => payload.container.focused,
_ => false,
};
if update {
tx.send(payload.container)
.expect("Failed to sendf focus update");
}
}
});
{
rx.attach(None, move |node| {
let value = node.name.as_deref().unwrap_or_else(|| node.get_id());
let pixbuf = icon::get_icon(&icon_theme, node.get_id(), self.icon_size);
context.widget_rx.attach(None, move |(name, id)| {
let pixbuf = icon::get_icon(&icon_theme, &id, self.icon_size);
if self.show_icon {
icon.set_pixbuf(pixbuf.as_ref());
}
if self.show_title {
label.set_label(value);
label.set_label(&name);
}
Continue(true)
});
}
Ok(container)
Ok(ModuleWidget {
widget: container,
popup: None,
})
}
}