mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-08-17 14:51:04 +02:00
build: fix compilation for many feature combinations (#932)
* Fix compilation for many feature combinations * fix: keep Mpris as the default music player type * fix: update futures-lite comment * fix: remove redundant "clap" feature dependency from "cli" * fix: don't make IPC a dependency of sysinfo module * refactor: move serde_json feature to "shared" section * refactor: avoid cfgs inside listen_workspace_events by splitting list_keyboards_events out of it, which manages its own connection to the Hyprland IPC socket. * refactor: sort multiline cfg any's * Revert "refactor: avoid cfgs inside listen_workspace_events" This reverts commit 1b4202ed80c9483c609ada8c4436e0fec26a9eef. * refactor: split listen_workspace_events in more functions * style: fix broken identation Not sure why rustfmt didn't catch this.
This commit is contained in:
parent
5744929931
commit
cff6b1fc83
11 changed files with 363 additions and 265 deletions
|
@ -1,4 +1,4 @@
|
|||
use super::{KeyboardLayoutClient, KeyboardLayoutUpdate, Visibility, Workspace, WorkspaceUpdate};
|
||||
use super::{Visibility, Workspace, WorkspaceUpdate};
|
||||
use crate::{arc_mut, lock, send, spawn_blocking};
|
||||
use color_eyre::Result;
|
||||
use hyprland::ctl::switch_xkb_layout;
|
||||
|
@ -11,35 +11,53 @@ use tokio::sync::broadcast::{Receiver, Sender, channel};
|
|||
use tracing::{debug, error, info};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Client {
|
||||
workspace_tx: Sender<WorkspaceUpdate>,
|
||||
_workspace_rx: Receiver<WorkspaceUpdate>,
|
||||
struct TxRx<T> {
|
||||
tx: Sender<T>,
|
||||
_rx: Receiver<T>,
|
||||
}
|
||||
|
||||
keyboard_layout_tx: Sender<KeyboardLayoutUpdate>,
|
||||
_keyboard_layout_rx: Receiver<KeyboardLayoutUpdate>,
|
||||
#[derive(Debug)]
|
||||
pub struct Client {
|
||||
#[cfg(feature = "workspaces+hyprland")]
|
||||
workspace: TxRx<WorkspaceUpdate>,
|
||||
|
||||
#[cfg(feature = "keyboard+hyprland")]
|
||||
keyboard_layout: TxRx<KeyboardLayoutUpdate>,
|
||||
}
|
||||
|
||||
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 {
|
||||
workspace_tx,
|
||||
_workspace_rx: workspace_rx,
|
||||
keyboard_layout_tx,
|
||||
_keyboard_layout_rx: keyboard_layout_rx,
|
||||
#[cfg(feature = "workspaces+hyprland")]
|
||||
workspace: TxRx {
|
||||
tx: workspace_tx,
|
||||
_rx: workspace_rx,
|
||||
},
|
||||
#[cfg(feature = "keyboard+hyprland")]
|
||||
keyboard_layout: TxRx {
|
||||
tx: keyboard_layout_tx,
|
||||
_rx: keyboard_layout_rx,
|
||||
},
|
||||
};
|
||||
|
||||
instance.listen_workspace_events();
|
||||
instance.listen_events();
|
||||
instance
|
||||
}
|
||||
|
||||
fn listen_workspace_events(&self) {
|
||||
fn listen_events(&self) {
|
||||
info!("Starting Hyprland event listener");
|
||||
|
||||
let tx = self.workspace_tx.clone();
|
||||
let keyboard_layout_tx = self.keyboard_layout_tx.clone();
|
||||
#[cfg(feature = "workspaces+hyprland")]
|
||||
let tx = self.workspace.tx.clone();
|
||||
|
||||
#[cfg(feature = "keyboard+hyprland")]
|
||||
let keyboard_layout_tx = self.keyboard_layout.tx.clone();
|
||||
|
||||
spawn_blocking(move || {
|
||||
let mut event_listener = EventListener::new();
|
||||
|
@ -48,223 +66,11 @@ impl Client {
|
|||
let lock = arc_mut!(());
|
||||
|
||||
// cache the active workspace since Hyprland doesn't give us the prev active
|
||||
let active = Self::get_active_workspace().expect("Failed to get active workspace");
|
||||
let active = arc_mut!(Some(active));
|
||||
#[cfg(feature = "workspaces+hyprland")]
|
||||
Self::listen_workspace_events(tx, &mut event_listener, &lock);
|
||||
|
||||
{
|
||||
let tx = tx.clone();
|
||||
let lock = lock.clone();
|
||||
let active = active.clone();
|
||||
|
||||
event_listener.add_workspace_added_handler(move |workspace_type| {
|
||||
let _lock = lock!(lock);
|
||||
debug!("Added workspace: {workspace_type:?}");
|
||||
|
||||
let workspace_name = get_workspace_name(workspace_type);
|
||||
let prev_workspace = lock!(active);
|
||||
|
||||
let workspace = Self::get_workspace(&workspace_name, prev_workspace.as_ref());
|
||||
|
||||
if let Some(workspace) = workspace {
|
||||
send!(tx, WorkspaceUpdate::Add(workspace));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let tx = tx.clone();
|
||||
let lock = lock.clone();
|
||||
let active = active.clone();
|
||||
|
||||
event_listener.add_workspace_change_handler(move |workspace_type| {
|
||||
let _lock = lock!(lock);
|
||||
|
||||
let mut prev_workspace = lock!(active);
|
||||
|
||||
debug!(
|
||||
"Received workspace change: {:?} -> {workspace_type:?}",
|
||||
prev_workspace.as_ref().map(|w| &w.id)
|
||||
);
|
||||
|
||||
let workspace_name = get_workspace_name(workspace_type);
|
||||
let workspace = Self::get_workspace(&workspace_name, prev_workspace.as_ref());
|
||||
|
||||
workspace.map_or_else(
|
||||
|| {
|
||||
error!("Unable to locate workspace");
|
||||
},
|
||||
|workspace| {
|
||||
// there may be another type of update so dispatch that regardless of focus change
|
||||
if !workspace.visibility.is_focused() {
|
||||
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let tx = tx.clone();
|
||||
let lock = lock.clone();
|
||||
let active = active.clone();
|
||||
|
||||
event_listener.add_active_monitor_change_handler(move |event_data| {
|
||||
let _lock = lock!(lock);
|
||||
let workspace_type = event_data.workspace;
|
||||
|
||||
let mut prev_workspace = lock!(active);
|
||||
|
||||
debug!(
|
||||
"Received active monitor change: {:?} -> {workspace_type:?}",
|
||||
prev_workspace.as_ref().map(|w| &w.name)
|
||||
);
|
||||
|
||||
let workspace_name = get_workspace_name(workspace_type);
|
||||
let workspace = Self::get_workspace(&workspace_name, prev_workspace.as_ref());
|
||||
|
||||
if let Some((false, workspace)) =
|
||||
workspace.map(|w| (w.visibility.is_focused(), w))
|
||||
{
|
||||
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
|
||||
} else {
|
||||
error!("unable to locate workspace: {workspace_name}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let tx = tx.clone();
|
||||
let lock = lock.clone();
|
||||
|
||||
event_listener.add_workspace_moved_handler(move |event_data| {
|
||||
let _lock = lock!(lock);
|
||||
let workspace_type = event_data.workspace;
|
||||
debug!("Received workspace move: {workspace_type:?}");
|
||||
|
||||
let mut prev_workspace = lock!(active);
|
||||
|
||||
let workspace_name = get_workspace_name(workspace_type);
|
||||
let workspace = Self::get_workspace(&workspace_name, prev_workspace.as_ref());
|
||||
|
||||
if let Some(workspace) = workspace {
|
||||
send!(tx, WorkspaceUpdate::Move(workspace.clone()));
|
||||
|
||||
if !workspace.visibility.is_focused() {
|
||||
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let tx = tx.clone();
|
||||
let lock = lock.clone();
|
||||
|
||||
event_listener.add_workspace_rename_handler(move |data| {
|
||||
let _lock = lock!(lock);
|
||||
debug!("Received workspace rename: {data:?}");
|
||||
|
||||
send!(
|
||||
tx,
|
||||
WorkspaceUpdate::Rename {
|
||||
id: data.workspace_id as i64,
|
||||
name: data.workspace_name
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let tx = tx.clone();
|
||||
let lock = lock.clone();
|
||||
|
||||
event_listener.add_workspace_destroy_handler(move |data| {
|
||||
let _lock = lock!(lock);
|
||||
debug!("Received workspace destroy: {data:?}");
|
||||
send!(tx, WorkspaceUpdate::Remove(data.workspace_id as i64));
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let tx = tx.clone();
|
||||
let lock = lock.clone();
|
||||
|
||||
event_listener.add_urgent_state_handler(move |address| {
|
||||
let _lock = lock!(lock);
|
||||
debug!("Received urgent state: {address:?}");
|
||||
|
||||
let clients = match hyprland::data::Clients::get() {
|
||||
Ok(clients) => clients,
|
||||
Err(err) => {
|
||||
error!("Failed to get clients: {err}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
clients.iter().find(|c| c.address == address).map_or_else(
|
||||
|| {
|
||||
error!("Unable to locate client");
|
||||
},
|
||||
|c| {
|
||||
send!(
|
||||
tx,
|
||||
WorkspaceUpdate::Urgent {
|
||||
id: c.workspace.id as i64,
|
||||
urgent: true,
|
||||
}
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let tx = keyboard_layout_tx.clone();
|
||||
let lock = lock.clone();
|
||||
|
||||
event_listener.add_keyboard_layout_change_handler(move |layout_event| {
|
||||
let _lock = lock!(lock);
|
||||
|
||||
let layout = if layout_event.layout_name.is_empty() {
|
||||
// FIXME: This field is empty due to bug in `hyprland-rs_0.4.0-alpha.3`. Which is already fixed in last betas
|
||||
|
||||
// The layout may be empty due to a bug in `hyprland-rs`, because of which the `layout_event` is incorrect.
|
||||
//
|
||||
// Instead of:
|
||||
// ```
|
||||
// LayoutEvent {
|
||||
// keyboard_name: "keychron-keychron-c2",
|
||||
// layout_name: "English (US)",
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// We get:
|
||||
// ```
|
||||
// LayoutEvent {
|
||||
// keyboard_name: "keychron-keychron-c2,English (US)",
|
||||
// layout_name: "",
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Here we are trying to recover `layout_name` from `keyboard_name`
|
||||
|
||||
let layout = layout_event.keyboard_name.as_str().split(',').nth(1);
|
||||
let Some(layout) = layout else {
|
||||
error!(
|
||||
"Failed to get layout from string: {}. The failed logic is a workaround for a bug in `hyprland 0.4.0-alpha.3`", layout_event.keyboard_name);
|
||||
return;
|
||||
};
|
||||
|
||||
layout.into()
|
||||
}
|
||||
else {
|
||||
layout_event.layout_name
|
||||
};
|
||||
|
||||
debug!("Received layout: {layout:?}");
|
||||
|
||||
send!(tx, KeyboardLayoutUpdate(layout));
|
||||
});
|
||||
}
|
||||
#[cfg(feature = "keyboard+hyprland")]
|
||||
Self::listen_keyboard_events(keyboard_layout_tx, &mut event_listener, lock);
|
||||
|
||||
event_listener
|
||||
.start_listener()
|
||||
|
@ -272,8 +78,238 @@ impl Client {
|
|||
});
|
||||
}
|
||||
|
||||
#[cfg(feature = "workspaces+hyprland")]
|
||||
fn listen_workspace_events(
|
||||
tx: Sender<WorkspaceUpdate>,
|
||||
event_listener: &mut EventListener,
|
||||
lock: &std::sync::Arc<std::sync::Mutex<()>>,
|
||||
) {
|
||||
let active = Self::get_active_workspace().expect("Failed to get active workspace");
|
||||
let active = arc_mut!(Some(active));
|
||||
|
||||
{
|
||||
let tx = tx.clone();
|
||||
let lock = lock.clone();
|
||||
let active = active.clone();
|
||||
|
||||
event_listener.add_workspace_added_handler(move |workspace_type| {
|
||||
let _lock = lock!(lock);
|
||||
debug!("Added workspace: {workspace_type:?}");
|
||||
|
||||
let workspace_name = get_workspace_name(workspace_type);
|
||||
let prev_workspace = lock!(active);
|
||||
|
||||
let workspace = Self::get_workspace(&workspace_name, prev_workspace.as_ref());
|
||||
|
||||
if let Some(workspace) = workspace {
|
||||
send!(tx, WorkspaceUpdate::Add(workspace));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let tx = tx.clone();
|
||||
let lock = lock.clone();
|
||||
let active = active.clone();
|
||||
|
||||
event_listener.add_workspace_change_handler(move |workspace_type| {
|
||||
let _lock = lock!(lock);
|
||||
|
||||
let mut prev_workspace = lock!(active);
|
||||
|
||||
debug!(
|
||||
"Received workspace change: {:?} -> {workspace_type:?}",
|
||||
prev_workspace.as_ref().map(|w| &w.id)
|
||||
);
|
||||
|
||||
let workspace_name = get_workspace_name(workspace_type);
|
||||
let workspace = Self::get_workspace(&workspace_name, prev_workspace.as_ref());
|
||||
|
||||
workspace.map_or_else(
|
||||
|| {
|
||||
error!("Unable to locate workspace");
|
||||
},
|
||||
|workspace| {
|
||||
// there may be another type of update so dispatch that regardless of focus change
|
||||
if !workspace.visibility.is_focused() {
|
||||
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let tx = tx.clone();
|
||||
let lock = lock.clone();
|
||||
let active = active.clone();
|
||||
|
||||
event_listener.add_active_monitor_change_handler(move |event_data| {
|
||||
let _lock = lock!(lock);
|
||||
let workspace_type = event_data.workspace;
|
||||
|
||||
let mut prev_workspace = lock!(active);
|
||||
|
||||
debug!(
|
||||
"Received active monitor change: {:?} -> {workspace_type:?}",
|
||||
prev_workspace.as_ref().map(|w| &w.name)
|
||||
);
|
||||
|
||||
let workspace_name = get_workspace_name(workspace_type);
|
||||
let workspace = Self::get_workspace(&workspace_name, prev_workspace.as_ref());
|
||||
|
||||
if let Some((false, workspace)) = workspace.map(|w| (w.visibility.is_focused(), w))
|
||||
{
|
||||
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
|
||||
} else {
|
||||
error!("unable to locate workspace: {workspace_name}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let tx = tx.clone();
|
||||
let lock = lock.clone();
|
||||
|
||||
event_listener.add_workspace_moved_handler(move |event_data| {
|
||||
let _lock = lock!(lock);
|
||||
let workspace_type = event_data.workspace;
|
||||
debug!("Received workspace move: {workspace_type:?}");
|
||||
|
||||
let mut prev_workspace = lock!(active);
|
||||
|
||||
let workspace_name = get_workspace_name(workspace_type);
|
||||
let workspace = Self::get_workspace(&workspace_name, prev_workspace.as_ref());
|
||||
|
||||
if let Some(workspace) = workspace {
|
||||
send!(tx, WorkspaceUpdate::Move(workspace.clone()));
|
||||
|
||||
if !workspace.visibility.is_focused() {
|
||||
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let tx = tx.clone();
|
||||
let lock = lock.clone();
|
||||
|
||||
event_listener.add_workspace_rename_handler(move |data| {
|
||||
let _lock = lock!(lock);
|
||||
debug!("Received workspace rename: {data:?}");
|
||||
|
||||
send!(
|
||||
tx,
|
||||
WorkspaceUpdate::Rename {
|
||||
id: data.workspace_id as i64,
|
||||
name: data.workspace_name
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let tx = tx.clone();
|
||||
let lock = lock.clone();
|
||||
|
||||
event_listener.add_workspace_destroy_handler(move |data| {
|
||||
let _lock = lock!(lock);
|
||||
debug!("Received workspace destroy: {data:?}");
|
||||
send!(tx, WorkspaceUpdate::Remove(data.workspace_id as i64));
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let tx = tx.clone();
|
||||
let lock = lock.clone();
|
||||
|
||||
event_listener.add_urgent_state_handler(move |address| {
|
||||
let _lock = lock!(lock);
|
||||
debug!("Received urgent state: {address:?}");
|
||||
|
||||
let clients = match hyprland::data::Clients::get() {
|
||||
Ok(clients) => clients,
|
||||
Err(err) => {
|
||||
error!("Failed to get clients: {err}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
clients.iter().find(|c| c.address == address).map_or_else(
|
||||
|| {
|
||||
error!("Unable to locate client");
|
||||
},
|
||||
|c| {
|
||||
send!(
|
||||
tx,
|
||||
WorkspaceUpdate::Urgent {
|
||||
id: c.workspace.id as i64,
|
||||
urgent: true,
|
||||
}
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "keyboard+hyprland")]
|
||||
fn listen_keyboard_events(
|
||||
keyboard_layout_tx: Sender<KeyboardLayoutUpdate>,
|
||||
event_listener: &mut EventListener,
|
||||
lock: std::sync::Arc<std::sync::Mutex<()>>,
|
||||
) {
|
||||
let tx = keyboard_layout_tx.clone();
|
||||
let lock = lock.clone();
|
||||
|
||||
event_listener.add_keyboard_layout_change_handler(move |layout_event| {
|
||||
let _lock = lock!(lock);
|
||||
|
||||
let layout = if layout_event.layout_name.is_empty() {
|
||||
// FIXME: This field is empty due to bug in `hyprland-rs_0.4.0-alpha.3`. Which is already fixed in last betas
|
||||
|
||||
// The layout may be empty due to a bug in `hyprland-rs`, because of which the `layout_event` is incorrect.
|
||||
//
|
||||
// Instead of:
|
||||
// ```
|
||||
// LayoutEvent {
|
||||
// keyboard_name: "keychron-keychron-c2",
|
||||
// layout_name: "English (US)",
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// We get:
|
||||
// ```
|
||||
// LayoutEvent {
|
||||
// keyboard_name: "keychron-keychron-c2,English (US)",
|
||||
// layout_name: "",
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Here we are trying to recover `layout_name` from `keyboard_name`
|
||||
|
||||
let layout = layout_event.keyboard_name.as_str().split(',').nth(1);
|
||||
let Some(layout) = layout else {
|
||||
error!(
|
||||
"Failed to get layout from string: {}. The failed logic is a workaround for a bug in `hyprland 0.4.0-alpha.3`", layout_event.keyboard_name);
|
||||
return;
|
||||
};
|
||||
|
||||
layout.into()
|
||||
}
|
||||
else {
|
||||
layout_event.layout_name
|
||||
};
|
||||
|
||||
debug!("Received layout: {layout:?}");
|
||||
|
||||
send!(tx, KeyboardLayoutUpdate(layout));
|
||||
});
|
||||
}
|
||||
|
||||
/// Sends a `WorkspaceUpdate::Focus` event
|
||||
/// and updates the active workspace cache.
|
||||
#[cfg(feature = "workspaces+hyprland")]
|
||||
fn send_focus_change(
|
||||
prev_workspace: &mut Option<Workspace>,
|
||||
workspace: Workspace,
|
||||
|
@ -299,6 +335,7 @@ impl Client {
|
|||
}
|
||||
|
||||
/// Gets a workspace by name from the server, given the active workspace if known.
|
||||
#[cfg(feature = "workspaces+hyprland")]
|
||||
fn get_workspace(name: &str, active: Option<&Workspace>) -> Option<Workspace> {
|
||||
Workspaces::get()
|
||||
.expect("Failed to get workspaces")
|
||||
|
@ -323,7 +360,7 @@ impl Client {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "workspaces")]
|
||||
#[cfg(feature = "workspaces+hyprland")]
|
||||
impl super::WorkspaceClient for Client {
|
||||
fn focus(&self, id: i64) {
|
||||
let identifier = WorkspaceIdentifierWithSpecial::Id(id as i32);
|
||||
|
@ -334,7 +371,7 @@ impl super::WorkspaceClient for Client {
|
|||
}
|
||||
|
||||
fn subscribe(&self) -> Receiver<WorkspaceUpdate> {
|
||||
let rx = self.workspace_tx.subscribe();
|
||||
let rx = self.workspace.tx.subscribe();
|
||||
|
||||
let active_id = HWorkspace::get_active().ok().map(|active| active.name);
|
||||
let is_visible = create_is_visible();
|
||||
|
@ -349,12 +386,16 @@ impl super::WorkspaceClient for Client {
|
|||
})
|
||||
.collect();
|
||||
|
||||
send!(self.workspace_tx, WorkspaceUpdate::Init(workspaces));
|
||||
send!(self.workspace.tx, WorkspaceUpdate::Init(workspaces));
|
||||
|
||||
rx
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "keyboard+hyprland")]
|
||||
use super::{KeyboardLayoutClient, KeyboardLayoutUpdate};
|
||||
|
||||
#[cfg(feature = "keyboard+hyprland")]
|
||||
impl KeyboardLayoutClient for Client {
|
||||
fn set_next_active(&self) {
|
||||
let device = Devices::get()
|
||||
|
@ -376,7 +417,7 @@ impl KeyboardLayoutClient for Client {
|
|||
}
|
||||
|
||||
fn subscribe(&self) -> Receiver<KeyboardLayoutUpdate> {
|
||||
let rx = self.keyboard_layout_tx.subscribe();
|
||||
let rx = self.keyboard_layout.tx.subscribe();
|
||||
|
||||
let layout = Devices::get()
|
||||
.expect("Failed to get devices")
|
||||
|
@ -386,7 +427,7 @@ impl KeyboardLayoutClient for Client {
|
|||
.map(|k| k.active_keymap.clone());
|
||||
|
||||
if let Some(layout) = layout {
|
||||
send!(self.keyboard_layout_tx, KeyboardLayoutUpdate(layout));
|
||||
send!(self.keyboard_layout.tx, KeyboardLayoutUpdate(layout));
|
||||
} else {
|
||||
error!("Failed to get current keyboard layout hyprland");
|
||||
}
|
||||
|
|
|
@ -7,19 +7,19 @@ use std::sync::Arc;
|
|||
use tokio::sync::broadcast;
|
||||
use tracing::debug;
|
||||
|
||||
#[cfg(any(feature = "keyboard+hyprland", feature = "workspaces+hyprland"))]
|
||||
#[cfg(feature = "hyprland")]
|
||||
pub mod hyprland;
|
||||
#[cfg(feature = "workspaces+niri")]
|
||||
#[cfg(feature = "niri")]
|
||||
pub mod niri;
|
||||
#[cfg(any(feature = "keyboard+sway", feature = "workspaces+sway"))]
|
||||
#[cfg(feature = "sway")]
|
||||
pub mod sway;
|
||||
|
||||
pub enum Compositor {
|
||||
#[cfg(any(feature = "keyboard+sway", feature = "workspaces+sway"))]
|
||||
#[cfg(feature = "sway")]
|
||||
Sway,
|
||||
#[cfg(any(feature = "keyboard+hyprland", feature = "workspaces+hyprland"))]
|
||||
#[cfg(feature = "hyprland")]
|
||||
Hyprland,
|
||||
#[cfg(feature = "workspaces+niri")]
|
||||
#[cfg(feature = "niri")]
|
||||
Niri,
|
||||
Unsupported,
|
||||
}
|
||||
|
@ -30,9 +30,9 @@ impl Display for Compositor {
|
|||
f,
|
||||
"{}",
|
||||
match self {
|
||||
#[cfg(any(feature = "keyboard+sway", feature = "workspaces+sway"))]
|
||||
#[cfg(any(feature = "sway"))]
|
||||
Self::Sway => "Sway",
|
||||
#[cfg(any(feature = "keyboard+hyprland", feature = "workspaces+hyprland"))]
|
||||
#[cfg(any(feature = "hyprland"))]
|
||||
Self::Hyprland => "Hyprland",
|
||||
#[cfg(feature = "workspaces+niri")]
|
||||
Self::Niri => "Niri",
|
||||
|
@ -48,17 +48,17 @@ impl Compositor {
|
|||
fn get_current() -> Self {
|
||||
if std::env::var("SWAYSOCK").is_ok() {
|
||||
cfg_if! {
|
||||
if #[cfg(any(feature = "keyboard+sway", feature = "workspaces+sway"))] { Self::Sway }
|
||||
if #[cfg(feature = "sway")] { Self::Sway }
|
||||
else { tracing::error!("Not compiled with Sway support"); Self::Unsupported }
|
||||
}
|
||||
} else if std::env::var("HYPRLAND_INSTANCE_SIGNATURE").is_ok() {
|
||||
cfg_if! {
|
||||
if #[cfg(any(feature = "keyboard+hyprland", feature = "workspaces+hyprland"))] { Self::Hyprland }
|
||||
if #[cfg(feature = "hyprland")] { Self::Hyprland }
|
||||
else { tracing::error!("Not compiled with Hyprland support"); Self::Unsupported }
|
||||
}
|
||||
} else if std::env::var("NIRI_SOCKET").is_ok() {
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "workspaces+niri")] { Self::Niri }
|
||||
if #[cfg(feature = "niri")] { Self::Niri }
|
||||
else {tracing::error!("Not compiled with Niri support"); Self::Unsupported }
|
||||
}
|
||||
} else {
|
||||
|
@ -79,13 +79,16 @@ impl Compositor {
|
|||
.map(|client| client as Arc<dyn KeyboardLayoutClient + Send + Sync>),
|
||||
#[cfg(feature = "keyboard+hyprland")]
|
||||
Self::Hyprland => Ok(clients.hyprland()),
|
||||
#[cfg(feature = "workspaces")]
|
||||
#[cfg(feature = "niri")]
|
||||
Self::Niri => Err(Report::msg("Unsupported compositor").note(
|
||||
"Currently keyboard layout functionality are only supported by Sway and Hyprland",
|
||||
)),
|
||||
Self::Unsupported => Err(Report::msg("Unsupported compositor").note(
|
||||
"Currently keyboard layout functionality are only supported by Sway and Hyprland",
|
||||
)),
|
||||
#[allow(unreachable_patterns)]
|
||||
_ => Err(Report::msg("Unsupported compositor")
|
||||
.note("Keyboard layout feature is disabled for this compositor")),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,6 +111,9 @@ impl Compositor {
|
|||
Self::Niri => Ok(Arc::new(niri::Client::new())),
|
||||
Self::Unsupported => Err(Report::msg("Unsupported compositor")
|
||||
.note("Currently workspaces are only supported by Sway, Niri and Hyprland")),
|
||||
#[allow(unreachable_patterns)]
|
||||
_ => Err(Report::msg("Unsupported compositor")
|
||||
.note("Workspaces feature is disabled for this compositor")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use super::{KeyboardLayoutClient, KeyboardLayoutUpdate, Visibility, Workspace, WorkspaceUpdate};
|
||||
use super::{Visibility, Workspace, WorkspaceUpdate};
|
||||
use crate::clients::sway::Client;
|
||||
use crate::{await_sync, error, send, spawn};
|
||||
use color_eyre::Report;
|
||||
use swayipc_async::{InputChange, InputEvent, Node, WorkspaceChange, WorkspaceEvent};
|
||||
use tokio::sync::broadcast::{Receiver, channel};
|
||||
|
||||
#[cfg(feature = "workspaces")]
|
||||
#[cfg(feature = "workspaces+sway")]
|
||||
impl super::WorkspaceClient for Client {
|
||||
fn focus(&self, id: i64) {
|
||||
let client = self.connection().clone();
|
||||
|
@ -153,6 +153,10 @@ impl From<WorkspaceEvent> for WorkspaceUpdate {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "keyboard+sway")]
|
||||
use super::{KeyboardLayoutClient, KeyboardLayoutUpdate};
|
||||
|
||||
#[cfg(feature = "keyboard+sway")]
|
||||
impl KeyboardLayoutClient for Client {
|
||||
fn set_next_active(&self) {
|
||||
let client = self.connection().clone();
|
||||
|
@ -210,6 +214,7 @@ impl KeyboardLayoutClient for Client {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "keyboard+sway")]
|
||||
impl TryFrom<InputEvent> for KeyboardLayoutUpdate {
|
||||
type Error = ();
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::sync::Arc;
|
|||
|
||||
#[cfg(feature = "clipboard")]
|
||||
pub mod clipboard;
|
||||
#[cfg(any(feature = "keyboard", feature = "workspaces"))]
|
||||
#[cfg(any(feature = "keyboard", feature = "workspaces", feature = "hyprland"))]
|
||||
pub mod compositor;
|
||||
#[cfg(feature = "keyboard")]
|
||||
pub mod libinput;
|
||||
|
@ -195,7 +195,10 @@ impl Clients {
|
|||
self.sys_info
|
||||
.get_or_insert_with(|| {
|
||||
let client = Arc::new(sysinfo::Client::new());
|
||||
|
||||
#[cfg(feature = "ipc")]
|
||||
Ironbar::variable_manager().register_namespace("sysinfo", client.clone());
|
||||
|
||||
client
|
||||
})
|
||||
.clone()
|
||||
|
|
|
@ -70,13 +70,17 @@ pub trait MusicClient: Debug + Send + Sync {
|
|||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum ClientType {
|
||||
#[cfg(feature = "music+mpd")]
|
||||
Mpd { host: String, music_dir: PathBuf },
|
||||
#[cfg(feature = "music+mpris")]
|
||||
Mpris,
|
||||
}
|
||||
|
||||
pub fn create_client(client_type: ClientType) -> Arc<dyn MusicClient> {
|
||||
match client_type {
|
||||
#[cfg(feature = "music+mpd")]
|
||||
ClientType::Mpd { host, music_dir } => Arc::new(mpd::Client::new(host, music_dir)),
|
||||
#[cfg(feature = "music+mpris")]
|
||||
ClientType::Mpris => Arc::new(mpris::Client::new()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use crate::ironvar::Namespace;
|
||||
use crate::modules::sysinfo::Interval;
|
||||
use crate::{lock, register_client};
|
||||
use color_eyre::{Report, Result};
|
||||
|
@ -483,6 +482,10 @@ impl FromStr for TokenType {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ipc")]
|
||||
use crate::ironvar::Namespace;
|
||||
|
||||
#[cfg(feature = "ipc")]
|
||||
impl Namespace for Client {
|
||||
fn get(&self, key: &str) -> Option<String> {
|
||||
let get = |value: Value| Some(value.get(Prefix::None).to_string());
|
||||
|
@ -591,6 +594,7 @@ impl Namespace for Client {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ipc")]
|
||||
impl Namespace for ValueSet {
|
||||
fn get(&self, key: &str) -> Option<String> {
|
||||
let function = Function::from_str(key).ok()?;
|
||||
|
|
|
@ -6,10 +6,13 @@ use std::ops::Deref;
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg(any(
|
||||
feature = "cairo",
|
||||
feature = "clipboard",
|
||||
feature = "clipboard",
|
||||
feature = "keyboard",
|
||||
feature = "launcher",
|
||||
feature = "music",
|
||||
feature = "workspaces"
|
||||
feature = "workspaces",
|
||||
))]
|
||||
pub struct IconButton {
|
||||
button: Button,
|
||||
|
@ -17,10 +20,13 @@ pub struct IconButton {
|
|||
}
|
||||
|
||||
#[cfg(any(
|
||||
feature = "cairo",
|
||||
feature = "clipboard",
|
||||
feature = "clipboard",
|
||||
feature = "keyboard",
|
||||
feature = "launcher",
|
||||
feature = "music",
|
||||
feature = "workspaces"
|
||||
feature = "workspaces",
|
||||
))]
|
||||
impl IconButton {
|
||||
pub fn new(input: &str, icon_theme: &IconTheme, size: i32) -> Self {
|
||||
|
@ -57,6 +63,15 @@ impl IconButton {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
feature = "clipboard",
|
||||
feature = "keyboard",
|
||||
feature = "music",
|
||||
feature = "workspaces",
|
||||
feature = "cairo",
|
||||
feature = "clipboard",
|
||||
feature = "launcher",
|
||||
))]
|
||||
impl Deref for IconButton {
|
||||
type Target = Button;
|
||||
|
||||
|
@ -138,6 +153,7 @@ impl IconLabel {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "keyboard", feature = "music", feature = "workspaces"))]
|
||||
impl Deref for IconLabel {
|
||||
type Target = gtk::Box;
|
||||
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
#[cfg(any(
|
||||
feature = "clipboard",
|
||||
feature = "keyboard",
|
||||
feature = "launcher",
|
||||
feature = "music",
|
||||
feature = "workspaces"
|
||||
feature = "workspaces",
|
||||
))]
|
||||
mod gtk;
|
||||
mod provider;
|
||||
|
||||
#[cfg(any(feature = "keyboard", feature = "music", feature = "workspaces"))]
|
||||
#[cfg(any(
|
||||
feature = "clipboard",
|
||||
feature = "keyboard",
|
||||
feature = "launcher",
|
||||
feature = "music",
|
||||
feature = "workspaces",
|
||||
))]
|
||||
pub use self::gtk::*;
|
||||
pub use provider::ImageProvider;
|
||||
|
|
|
@ -74,13 +74,23 @@ impl Default for Icons {
|
|||
#[serde(rename_all = "snake_case")]
|
||||
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
|
||||
pub enum PlayerType {
|
||||
#[cfg(feature = "music+mpd")]
|
||||
Mpd,
|
||||
#[cfg(feature = "music+mpris")]
|
||||
Mpris,
|
||||
}
|
||||
|
||||
impl Default for PlayerType {
|
||||
fn default() -> Self {
|
||||
Self::Mpris
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(feature = "music+mpris")] {
|
||||
Self::Mpris
|
||||
} else if #[cfg(feature = "music+mpd")] {
|
||||
Self::Mpd
|
||||
} else {
|
||||
compile_error!("No player type feature enabled")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,9 @@ fn get_client(
|
|||
music_dir: PathBuf,
|
||||
) -> Arc<dyn MusicClient> {
|
||||
let client_type = match player_type {
|
||||
#[cfg(feature = "music+mpd")]
|
||||
PlayerType::Mpd => music::ClientType::Mpd { host, music_dir },
|
||||
#[cfg(feature = "music+mpris")]
|
||||
PlayerType::Mpris => music::ClientType::Mpris,
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue