aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cli.rs2
-rw-r--r--src/ipc/client.rs25
-rw-r--r--src/ipc/server.rs20
3 files changed, 45 insertions, 2 deletions
diff --git a/src/cli.rs b/src/cli.rs
index 4004a331..4d0d3559 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -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)