diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-08-25 09:38:45 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-08-25 09:38:45 +0300 |
| commit | f19e1711a7999f9b4d97cf1a1b2e03f273b2f120 (patch) | |
| tree | aa9832280c4e604f1ed0d962e39c096449e90214 | |
| parent | 20cd4f5d0470d1755f351c53eb2c0f63c27529cf (diff) | |
| download | niri-f19e1711a7999f9b4d97cf1a1b2e03f273b2f120.tar.gz niri-f19e1711a7999f9b4d97cf1a1b2e03f273b2f120.tar.bz2 niri-f19e1711a7999f9b4d97cf1a1b2e03f273b2f120.zip | |
Add niri msg keyboard-layouts
| -rw-r--r-- | niri-ipc/src/lib.rs | 14 | ||||
| -rw-r--r-- | src/cli.rs | 2 | ||||
| -rw-r--r-- | src/ipc/client.rs | 25 | ||||
| -rw-r--r-- | src/ipc/server.rs | 20 |
4 files changed, 59 insertions, 2 deletions
diff --git a/niri-ipc/src/lib.rs b/niri-ipc/src/lib.rs index 713db8af..ecf202f2 100644 --- a/niri-ipc/src/lib.rs +++ b/niri-ipc/src/lib.rs @@ -36,6 +36,8 @@ pub enum Request { Workspaces, /// Request information about the focused output. FocusedOutput, + /// Request information about the keyboard layout. + KeyboardLayouts, /// Respond with an error (for testing error handling). ReturnError, } @@ -70,6 +72,8 @@ pub enum Response { Workspaces(Vec<Workspace>), /// Information about the focused output. FocusedOutput(Option<Output>), + /// Information about the keyboard layout. + KeyboardLayouts(KeyboardLayouts), } /// Actions that niri can perform. @@ -566,6 +570,16 @@ pub struct Workspace { pub is_active: bool, } +/// Configured keyboard layouts. +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] +pub struct KeyboardLayouts { + /// XKB names of the configured layouts. + pub names: Vec<String>, + /// Index of the currently active layout in `names`. + pub current_idx: u8, +} + impl FromStr for WorkspaceReferenceArg { type Err = &'static str; @@ -86,6 +86,8 @@ pub enum Msg { #[command(subcommand)] action: OutputAction, }, + /// Get the configured keyboard layouts. + KeyboardLayouts, /// Print the version of the running niri instance. Version, /// Request an error from the running niri instance. diff --git a/src/ipc/client.rs b/src/ipc/client.rs index 3192925f..e9312933 100644 --- a/src/ipc/client.rs +++ b/src/ipc/client.rs @@ -1,6 +1,7 @@ use anyhow::{anyhow, bail, Context}; use niri_ipc::{ - LogicalOutput, Mode, Output, OutputConfigChanged, Request, Response, Socket, Transform, + KeyboardLayouts, LogicalOutput, Mode, Output, OutputConfigChanged, Request, Response, Socket, + Transform, }; use serde_json::json; @@ -19,6 +20,7 @@ pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> { action: action.clone(), }, Msg::Workspaces => Request::Workspaces, + Msg::KeyboardLayouts => Request::KeyboardLayouts, Msg::RequestError => Request::ReturnError, }; @@ -238,6 +240,27 @@ pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> { println!("{is_active}{idx}{name}"); } } + Msg::KeyboardLayouts => { + let Response::KeyboardLayouts(response) = response else { + bail!("unexpected response: expected KeyboardLayouts, got {response:?}"); + }; + + if json { + let response = + serde_json::to_string(&response).context("error formatting response")?; + println!("{response}"); + return Ok(()); + } + + let KeyboardLayouts { names, current_idx } = response; + let current_idx = usize::from(current_idx); + + println!("Keyboard layouts:"); + for (idx, name) in names.iter().enumerate() { + let is_active = if idx == current_idx { " * " } else { " " }; + println!("{is_active}{idx} {name}"); + } + } } Ok(()) diff --git a/src/ipc/server.rs b/src/ipc/server.rs index d05131a3..5b614a83 100644 --- a/src/ipc/server.rs +++ b/src/ipc/server.rs @@ -8,8 +8,9 @@ use calloop::io::Async; use directories::BaseDirs; use futures_util::io::{AsyncReadExt, BufReader}; use futures_util::{AsyncBufReadExt, AsyncWriteExt}; -use niri_ipc::{OutputConfigChanged, Reply, Request, Response}; +use niri_ipc::{KeyboardLayouts, OutputConfigChanged, Reply, Request, Response}; use smithay::desktop::Window; +use smithay::input::keyboard::XkbContextHandler; use smithay::reexports::calloop::generic::Generic; use smithay::reexports::calloop::{Interest, LoopHandle, Mode, PostAction}; use smithay::reexports::rustix::fs::unlink; @@ -235,6 +236,23 @@ async fn process(ctx: &ClientCtx, request: Request) -> Reply { let output = result.map_err(|_| String::from("error getting active output info"))?; Response::FocusedOutput(output) } + Request::KeyboardLayouts => { + let (tx, rx) = async_channel::bounded(1); + ctx.event_loop.insert_idle(move |state| { + let keyboard = state.niri.seat.get_keyboard().unwrap(); + let layout = keyboard.with_xkb_state(state, |context| { + let layouts = context.keymap().layouts(); + KeyboardLayouts { + names: layouts.map(str::to_owned).collect(), + current_idx: context.active_layout().0 as u8, + } + }); + let _ = tx.send_blocking(layout); + }); + let result = rx.recv().await; + let layout = result.map_err(|_| String::from("error getting layout info"))?; + Response::KeyboardLayouts(layout) + } }; Ok(response) |
