mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-22 02:01:55 +07:00
Add niri msg keyboard-layouts
This commit is contained in:
@@ -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.
|
||||
|
||||
+24
-1
@@ -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
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user