Skip to content

Commit

Permalink
keyboard_layout: Add xkbswitch support (#1985)
Browse files Browse the repository at this point in the history
  • Loading branch information
IshanGrover2004 authored Jan 16, 2024
1 parent fb65e8d commit 5500fed
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 1 deletion.
17 changes: 16 additions & 1 deletion src/blocks/keyboard_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//!
//! Four drivers are available:
//! - `setxkbmap` which polls setxkbmap to get the current layout
//! - `xkbswitch` which utilizes [XkbSwitch](https://github.com/grwlf/xkb-switch) to monitor and retrieve the current layout and variant
//! - `localebus` which can read asynchronous updates from the systemd `org.freedesktop.locale1` D-Bus path
//! - `kbddbus` which uses [kbdd](https://github.com/qnikst/kbdd) to monitor per-window layout changes via DBus
//! - `sway` which can read asynchronous updates from the sway IPC
Expand All @@ -12,7 +13,7 @@
//!
//! Key | Values | Default
//! ----|--------|--------
//! `driver` | One of `"setxkbmap"`, `"localebus"`, `"kbddbus"` or `"sway"`, depending on your system. | `"setxkbmap"`
//! `driver` | One of `"setxkbmap"`, `"xkbswitch"`, "localebus"`, `"kbddbus"` or `"sway"`, depending on your system. | `"setxkbmap"`
//! `interval` | Update interval, in seconds. Only used by the `"setxkbmap"` driver. | `60`
//! `format` | A string to customise the output of this block. See below for available placeholders. | `" $layout "`
//! `sway_kb_identifier` | Identifier of the device you want to monitor, as found in the output of `swaymsg -t get_inputs`. | Defaults to first input found
Expand All @@ -34,6 +35,15 @@
//! interval = 15
//! ```
//!
//! Check `xkbswitch` every 15 seconds
//!
//! ```toml
//! [[block]]
//! block = "keyboard_layout"
//! driver = "xkbswitch"
//! interval = 15
//! ```
//!
//! Listen to D-Bus for changes:
//!
//! ```toml
Expand Down Expand Up @@ -82,6 +92,9 @@
mod set_xkb_map;
use set_xkb_map::SetXkbMap;

mod xkb_switch;
use xkb_switch::XkbSwitch;

mod locale_bus;
use locale_bus::LocaleBus;

Expand Down Expand Up @@ -109,6 +122,7 @@ pub struct Config {
pub enum KeyboardLayoutDriver {
#[default]
SetXkbMap,
XkbSwitch,
LocaleBus,
KbddBus,
Sway,
Expand All @@ -119,6 +133,7 @@ pub async fn run(config: &Config, api: &CommonApi) -> Result<()> {

let mut backend: Box<dyn Backend> = match config.driver {
KeyboardLayoutDriver::SetXkbMap => Box::new(SetXkbMap::new(config.interval)),
KeyboardLayoutDriver::XkbSwitch => Box::new(XkbSwitch::new(config.interval)),
KeyboardLayoutDriver::LocaleBus => Box::new(LocaleBus::new().await?),
KeyboardLayoutDriver::KbddBus => Box::new(KbddBus::new().await?),
KeyboardLayoutDriver::Sway => Box::new(Sway::new(config.sway_kb_identifier.clone()).await?),
Expand Down
44 changes: 44 additions & 0 deletions src/blocks/keyboard_layout/xkb_switch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use super::*;
use tokio::process::Command;

pub(super) struct XkbSwitch(Seconds);

impl XkbSwitch {
pub(super) fn new(update_interval: Seconds) -> Self {
Self(update_interval)
}
}

#[async_trait]
impl Backend for XkbSwitch {
async fn get_info(&mut self) -> Result<Info> {
// This command output is in the format of "layout(variant)" or "layout"
let output = Command::new("xkb-switch")
.arg("-p")
.output()
.await
.error("Failed to execute 'xkb-switch -p'")?;

let output =
String::from_utf8(output.stdout).error("xkb-switch produces a non-UTF8 output")?;

let mut components = output.trim_end().split('(');

let layout = components
.next()
.error("Could not find layout entry in xkb-switch")?
.to_string();

let variant = components
.last()
// Remove the trailing parenthesis ")"
.map(|variant_str| variant_str.split_at(variant_str.len() - 1).0.to_string());

Ok(Info { layout, variant })
}

async fn wait_for_change(&mut self) -> Result<()> {
sleep(self.0 .0).await;
Ok(())
}
}

0 comments on commit 5500fed

Please sign in to comment.