diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/cli.rs | 2 | ||||
| -rw-r--r-- | src/ipc/client.rs | 25 | ||||
| -rw-r--r-- | src/ipc/server.rs | 20 |
3 files changed, 45 insertions, 2 deletions
@@ -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) |
