Add niri msg keyboard-layouts

This commit is contained in:
Ivan Molodetskikh
2024-08-25 09:38:45 +03:00
parent 20cd4f5d04
commit f19e1711a7
4 changed files with 59 additions and 2 deletions
+14
View File
@@ -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;
+2
View File
@@ -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.
+24 -1
View File
@@ -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(())
+19 -1
View File
@@ -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)