1
0
Fork 0
mirror of https://github.com/Zedfrigg/ironbar.git synced 2025-08-17 23:01:04 +02:00
ironbar/src/modules/focused.rs

153 lines
4.2 KiB
Rust
Raw Normal View History

use crate::clients::wayland::{self, ToplevelEvent};
use crate::config::{CommonConfig, TruncateMode};
use crate::gtk_helpers::IronbarGtkExt;
use crate::image::ImageProvider;
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
2023-06-29 16:57:47 +01:00
use crate::{lock, send_async, try_send};
use color_eyre::Result;
2022-08-14 20:40:11 +01:00
use glib::Continue;
use gtk::prelude::*;
use gtk::Label;
2022-08-14 20:40:11 +01:00
use serde::Deserialize;
use tokio::spawn;
use tokio::sync::mpsc::{Receiver, Sender};
use tracing::debug;
2022-08-14 20:40:11 +01:00
#[derive(Debug, Deserialize, Clone)]
pub struct FocusedModule {
/// Whether to show icon on the bar.
2022-08-14 20:40:11 +01:00
#[serde(default = "crate::config::default_true")]
show_icon: bool,
/// Whether to show app name on the bar.
2022-08-14 20:40:11 +01:00
#[serde(default = "crate::config::default_true")]
show_title: bool,
/// Icon size in pixels.
2022-08-14 20:40:11 +01:00
#[serde(default = "default_icon_size")]
icon_size: i32,
truncate: Option<TruncateMode>,
#[serde(flatten)]
pub common: Option<CommonConfig>,
2022-08-14 20:40:11 +01:00
}
impl Default for FocusedModule {
fn default() -> Self {
Self {
show_icon: crate::config::default_true(),
show_title: crate::config::default_true(),
icon_size: default_icon_size(),
truncate: None,
common: Some(CommonConfig::default()),
}
}
}
2022-08-14 20:40:11 +01:00
const fn default_icon_size() -> i32 {
32
}
impl Module<gtk::Box> for FocusedModule {
type SendMessage = (String, String);
type ReceiveMessage = ();
fn name() -> &'static str {
"focused"
}
fn spawn_controller(
&self,
_info: &ModuleInfo,
tx: Sender<ModuleUpdateEvent<Self::SendMessage>>,
_rx: Receiver<Self::ReceiveMessage>,
) -> Result<()> {
spawn(async move {
let (mut wlrx, handles) = {
2023-06-29 16:57:47 +01:00
let wl = wayland::get_client();
let wl = lock!(wl);
wl.subscribe_toplevels()
};
let focused = handles.values().find_map(|handle| {
handle
.info()
.and_then(|info| if info.focused { Some(info) } else { None })
});
if let Some(focused) = focused {
try_send!(
tx,
ModuleUpdateEvent::Update((focused.title.clone(), focused.app_id))
);
};
while let Ok(event) = wlrx.recv().await {
if let ToplevelEvent::Update(handle) = event {
let info = handle.info().unwrap_or_default();
if info.focused {
debug!("Changing focus");
send_async!(
tx,
ModuleUpdateEvent::Update((info.title.clone(), info.app_id.clone()))
);
}
2022-08-14 20:40:11 +01:00
}
}
});
Ok(())
}
fn into_widget(
self,
context: WidgetContext<Self::SendMessage, Self::ReceiveMessage>,
info: &ModuleInfo,
) -> Result<ModuleParts<gtk::Box>> {
let icon_theme = info.icon_theme;
2022-08-14 20:40:11 +01:00
let container = gtk::Box::new(info.bar_position.get_orientation(), 5);
let icon = gtk::Image::new();
if self.show_icon {
icon.add_class("icon");
container.add(&icon);
}
let label = Label::new(None);
label.add_class("label");
if let Some(truncate) = self.truncate {
truncate.truncate_label(&label);
}
container.add(&label);
{
let icon_theme = icon_theme.clone();
context.widget_rx.attach(None, move |(name, id)| {
2022-08-14 20:40:11 +01:00
if self.show_icon {
match ImageProvider::parse(&id, &icon_theme, true, self.icon_size)
.map(|image| image.load_into_image(icon.clone()))
{
Some(Ok(_)) => icon.show(),
_ => icon.hide(),
}
2022-08-14 20:40:11 +01:00
}
if self.show_title {
label.set_label(&name);
2022-08-14 20:40:11 +01:00
}
Continue(true)
});
}
Ok(ModuleParts {
widget: container,
popup: None,
})
2022-08-14 20:40:11 +01:00
}
}