mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-08-17 23:01:04 +02:00
feat: rename sway_mode to bindmode and add Hyprland support
Signed-off-by: Rodrigodd <rodrigobatsmoraes@hotmail.com>
This commit is contained in:
parent
1e501d99d2
commit
5a5b110c7a
12 changed files with 206 additions and 76 deletions
|
@ -10,11 +10,22 @@ use hyprland::shared::{HyprDataVec, WorkspaceType};
|
|||
use tokio::sync::broadcast::{Receiver, Sender, channel};
|
||||
use tracing::{debug, error, info};
|
||||
|
||||
#[cfg(feature = "bindmode+hyprland")]
|
||||
use super::{BindModeClient, BindModeUpdate};
|
||||
#[cfg(feature = "keyboard+hyprland")]
|
||||
use super::{KeyboardLayoutClient, KeyboardLayoutUpdate};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TxRx<T> {
|
||||
tx: Sender<T>,
|
||||
_rx: Receiver<T>,
|
||||
}
|
||||
impl<T: Clone> TxRx<T> {
|
||||
fn new() -> Self {
|
||||
let (tx, rx) = channel(16);
|
||||
Self { tx, _rx: rx }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Client {
|
||||
|
@ -23,27 +34,20 @@ pub struct Client {
|
|||
|
||||
#[cfg(feature = "keyboard+hyprland")]
|
||||
keyboard_layout: TxRx<KeyboardLayoutUpdate>,
|
||||
|
||||
#[cfg(feature = "bindmode+hyprland")]
|
||||
bindmode: TxRx<BindModeUpdate>,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub(crate) fn new() -> Self {
|
||||
#[cfg(feature = "workspaces+hyprland")]
|
||||
let (workspace_tx, workspace_rx) = channel(16);
|
||||
|
||||
#[cfg(feature = "keyboard+hyprland")]
|
||||
let (keyboard_layout_tx, keyboard_layout_rx) = channel(16);
|
||||
|
||||
let instance = Self {
|
||||
#[cfg(feature = "workspaces+hyprland")]
|
||||
workspace: TxRx {
|
||||
tx: workspace_tx,
|
||||
_rx: workspace_rx,
|
||||
},
|
||||
workspace: TxRx::new(),
|
||||
#[cfg(feature = "keyboard+hyprland")]
|
||||
keyboard_layout: TxRx {
|
||||
tx: keyboard_layout_tx,
|
||||
_rx: keyboard_layout_rx,
|
||||
},
|
||||
keyboard_layout: TxRx::new(),
|
||||
#[cfg(feature = "bindmode+hyprland")]
|
||||
bindmode: TxRx::new(),
|
||||
};
|
||||
|
||||
instance.listen_events();
|
||||
|
@ -54,11 +58,14 @@ impl Client {
|
|||
info!("Starting Hyprland event listener");
|
||||
|
||||
#[cfg(feature = "workspaces+hyprland")]
|
||||
let tx = self.workspace.tx.clone();
|
||||
let workspace_tx = self.workspace.tx.clone();
|
||||
|
||||
#[cfg(feature = "keyboard+hyprland")]
|
||||
let keyboard_layout_tx = self.keyboard_layout.tx.clone();
|
||||
|
||||
#[cfg(feature = "bindmode+hyprland")]
|
||||
let bindmode_tx = self.bindmode.tx.clone();
|
||||
|
||||
spawn_blocking(move || {
|
||||
let mut event_listener = EventListener::new();
|
||||
|
||||
|
@ -67,10 +74,13 @@ impl Client {
|
|||
|
||||
// cache the active workspace since Hyprland doesn't give us the prev active
|
||||
#[cfg(feature = "workspaces+hyprland")]
|
||||
Self::listen_workspace_events(tx, &mut event_listener, &lock);
|
||||
Self::listen_workspace_events(workspace_tx, &mut event_listener, &lock);
|
||||
|
||||
#[cfg(feature = "keyboard+hyprland")]
|
||||
Self::listen_keyboard_events(keyboard_layout_tx, &mut event_listener, lock);
|
||||
Self::listen_keyboard_events(keyboard_layout_tx, &mut event_listener, &lock);
|
||||
|
||||
#[cfg(feature = "bindmode+hyprland")]
|
||||
Self::listen_bindmode_events(bindmode_tx, &mut event_listener, &lock);
|
||||
|
||||
event_listener
|
||||
.start_listener()
|
||||
|
@ -257,7 +267,7 @@ impl Client {
|
|||
fn listen_keyboard_events(
|
||||
keyboard_layout_tx: Sender<KeyboardLayoutUpdate>,
|
||||
event_listener: &mut EventListener,
|
||||
lock: std::sync::Arc<std::sync::Mutex<()>>,
|
||||
lock: &std::sync::Arc<std::sync::Mutex<()>>,
|
||||
) {
|
||||
let tx = keyboard_layout_tx.clone();
|
||||
let lock = lock.clone();
|
||||
|
@ -307,6 +317,29 @@ impl Client {
|
|||
});
|
||||
}
|
||||
|
||||
#[cfg(feature = "bindmode+hyprland")]
|
||||
fn listen_bindmode_events(
|
||||
bindmode_tx: Sender<BindModeUpdate>,
|
||||
event_listener: &mut EventListener,
|
||||
lock: &std::sync::Arc<std::sync::Mutex<()>>,
|
||||
) {
|
||||
let tx = bindmode_tx.clone();
|
||||
let lock = lock.clone();
|
||||
|
||||
event_listener.add_sub_map_change_handler(move |bind_mode| {
|
||||
let _lock = lock!(lock);
|
||||
debug!("Received bind mode: {bind_mode:?}");
|
||||
|
||||
send!(
|
||||
tx,
|
||||
BindModeUpdate {
|
||||
name: bind_mode,
|
||||
pango_markup: false,
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Sends a `WorkspaceUpdate::Focus` event
|
||||
/// and updates the active workspace cache.
|
||||
#[cfg(feature = "workspaces+hyprland")]
|
||||
|
@ -392,9 +425,6 @@ impl super::WorkspaceClient for Client {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "keyboard+hyprland")]
|
||||
use super::{KeyboardLayoutClient, KeyboardLayoutUpdate};
|
||||
|
||||
#[cfg(feature = "keyboard+hyprland")]
|
||||
impl KeyboardLayoutClient for Client {
|
||||
fn set_next_active(&self) {
|
||||
|
@ -436,6 +466,13 @@ impl KeyboardLayoutClient for Client {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "bindmode+hyprland")]
|
||||
impl BindModeClient for Client {
|
||||
fn subscribe(&self) -> Result<Receiver<BindModeUpdate>> {
|
||||
Ok(self.bindmode.tx.subscribe())
|
||||
}
|
||||
}
|
||||
|
||||
fn get_workspace_name(name: WorkspaceType) -> String {
|
||||
match name {
|
||||
WorkspaceType::Regular(name) => name,
|
||||
|
|
|
@ -66,6 +66,30 @@ impl Compositor {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "bindmode")]
|
||||
pub fn create_bindmode_client(
|
||||
clients: &mut super::Clients,
|
||||
) -> ClientResult<dyn BindModeClient + Send + Sync> {
|
||||
let current = Self::get_current();
|
||||
debug!("Getting keyboard_layout client for: {current}");
|
||||
match current {
|
||||
#[cfg(feature = "bindmode+sway")]
|
||||
Self::Sway => clients
|
||||
.sway()
|
||||
.map(|client| client as Arc<dyn BindModeClient + Send + Sync>),
|
||||
#[cfg(feature = "bindmode+hyprland")]
|
||||
Self::Hyprland => Ok(clients.hyprland()),
|
||||
#[cfg(feature = "niri")]
|
||||
Self::Niri => Err(Report::msg("Unsupported compositor")
|
||||
.note("Currently bindmode is only supported by Sway and Hyprland")),
|
||||
Self::Unsupported => Err(Report::msg("Unsupported compositor")
|
||||
.note("Currently bindmode is only supported by Sway and Hyprland")),
|
||||
#[allow(unreachable_patterns)]
|
||||
_ => Err(Report::msg("Unsupported compositor")
|
||||
.note("Bindmode feature is disabled for this compositor")),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "keyboard")]
|
||||
pub fn create_keyboard_layout_client(
|
||||
clients: &mut super::Clients,
|
||||
|
@ -195,6 +219,14 @@ pub enum WorkspaceUpdate {
|
|||
Unknown,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BindModeUpdate {
|
||||
/// The binding mode that became active.
|
||||
pub name: String,
|
||||
/// Whether the mode should be parsed as pango markup.
|
||||
pub pango_markup: bool,
|
||||
}
|
||||
|
||||
#[cfg(feature = "workspaces")]
|
||||
pub trait WorkspaceClient: Debug + Send + Sync {
|
||||
/// Requests the workspace with this id is focused.
|
||||
|
@ -218,3 +250,12 @@ pub trait KeyboardLayoutClient: Debug + Send + Sync {
|
|||
|
||||
#[cfg(feature = "keyboard")]
|
||||
register_fallible_client!(dyn KeyboardLayoutClient, keyboard_layout);
|
||||
|
||||
#[cfg(feature = "bindmode")]
|
||||
pub trait BindModeClient: Debug + Send + Sync {
|
||||
/// Add a callback for bindmode updates.
|
||||
fn subscribe(&self) -> Result<broadcast::Receiver<BindModeUpdate>>;
|
||||
}
|
||||
|
||||
#[cfg(feature = "bindmode")]
|
||||
register_fallible_client!(dyn BindModeClient, bindmode);
|
||||
|
|
|
@ -231,3 +231,36 @@ impl TryFrom<InputEvent> for KeyboardLayoutUpdate {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "bindmode+sway")]
|
||||
use super::{BindModeClient, BindModeUpdate};
|
||||
|
||||
#[cfg(feature = "bindmode+sway")]
|
||||
impl BindModeClient for Client {
|
||||
fn subscribe(&self) -> Result<Receiver<BindModeUpdate>, Report> {
|
||||
let (tx, rx) = channel(16);
|
||||
await_sync(async {
|
||||
self.add_listener::<swayipc_async::ModeEvent>(move |mode| {
|
||||
tracing::trace!("mode: {:?}", mode);
|
||||
|
||||
// when no bindind is active the bindmode is named "default", but we must display
|
||||
// nothing in this case.
|
||||
let name = if mode.change == "default" {
|
||||
String::new()
|
||||
} else {
|
||||
mode.change.clone()
|
||||
};
|
||||
|
||||
send!(
|
||||
tx,
|
||||
BindModeUpdate {
|
||||
name,
|
||||
pango_markup: mode.pango_markup,
|
||||
}
|
||||
);
|
||||
})
|
||||
.await
|
||||
})?;
|
||||
Ok(rx)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,12 @@ use std::sync::Arc;
|
|||
|
||||
#[cfg(feature = "clipboard")]
|
||||
pub mod clipboard;
|
||||
#[cfg(any(feature = "keyboard", feature = "workspaces", feature = "hyprland"))]
|
||||
#[cfg(any(
|
||||
feature = "bindmode",
|
||||
feature = "hyprland",
|
||||
feature = "keyboard",
|
||||
feature = "workspaces",
|
||||
))]
|
||||
pub mod compositor;
|
||||
#[cfg(feature = "keyboard")]
|
||||
pub mod libinput;
|
||||
|
@ -42,6 +47,8 @@ pub struct Clients {
|
|||
sway: Option<Arc<sway::Client>>,
|
||||
#[cfg(feature = "hyprland")]
|
||||
hyprland: Option<Arc<compositor::hyprland::Client>>,
|
||||
#[cfg(feature = "bindmode")]
|
||||
bindmode: Option<Arc<dyn compositor::BindModeClient>>,
|
||||
#[cfg(feature = "clipboard")]
|
||||
clipboard: Option<Arc<clipboard::Client>>,
|
||||
#[cfg(feature = "keyboard")]
|
||||
|
@ -114,6 +121,19 @@ impl Clients {
|
|||
Ok(client)
|
||||
}
|
||||
|
||||
#[cfg(feature = "bindmode")]
|
||||
pub fn bindmode(&mut self) -> ClientResult<dyn compositor::BindModeClient> {
|
||||
let client = if let Some(client) = &self.bindmode {
|
||||
client.clone()
|
||||
} else {
|
||||
let client = compositor::Compositor::create_bindmode_client(self)?;
|
||||
self.bindmode.replace(client.clone());
|
||||
client
|
||||
};
|
||||
|
||||
Ok(client)
|
||||
}
|
||||
|
||||
#[cfg(feature = "sway")]
|
||||
pub fn sway(&mut self) -> ClientResult<sway::Client> {
|
||||
let client = if let Some(client) = &self.sway {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue