mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-24 02:01:18 +07:00
Add niri msg keyboard-layouts
This commit is contained in:
@@ -36,6 +36,8 @@ pub enum Request {
|
|||||||
Workspaces,
|
Workspaces,
|
||||||
/// Request information about the focused output.
|
/// Request information about the focused output.
|
||||||
FocusedOutput,
|
FocusedOutput,
|
||||||
|
/// Request information about the keyboard layout.
|
||||||
|
KeyboardLayouts,
|
||||||
/// Respond with an error (for testing error handling).
|
/// Respond with an error (for testing error handling).
|
||||||
ReturnError,
|
ReturnError,
|
||||||
}
|
}
|
||||||
@@ -70,6 +72,8 @@ pub enum Response {
|
|||||||
Workspaces(Vec<Workspace>),
|
Workspaces(Vec<Workspace>),
|
||||||
/// Information about the focused output.
|
/// Information about the focused output.
|
||||||
FocusedOutput(Option<Output>),
|
FocusedOutput(Option<Output>),
|
||||||
|
/// Information about the keyboard layout.
|
||||||
|
KeyboardLayouts(KeyboardLayouts),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Actions that niri can perform.
|
/// Actions that niri can perform.
|
||||||
@@ -566,6 +570,16 @@ pub struct Workspace {
|
|||||||
pub is_active: bool,
|
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 {
|
impl FromStr for WorkspaceReferenceArg {
|
||||||
type Err = &'static str;
|
type Err = &'static str;
|
||||||
|
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ pub enum Msg {
|
|||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
action: OutputAction,
|
action: OutputAction,
|
||||||
},
|
},
|
||||||
|
/// Get the configured keyboard layouts.
|
||||||
|
KeyboardLayouts,
|
||||||
/// Print the version of the running niri instance.
|
/// Print the version of the running niri instance.
|
||||||
Version,
|
Version,
|
||||||
/// Request an error from the running niri instance.
|
/// Request an error from the running niri instance.
|
||||||
|
|||||||
+24
-1
@@ -1,6 +1,7 @@
|
|||||||
use anyhow::{anyhow, bail, Context};
|
use anyhow::{anyhow, bail, Context};
|
||||||
use niri_ipc::{
|
use niri_ipc::{
|
||||||
LogicalOutput, Mode, Output, OutputConfigChanged, Request, Response, Socket, Transform,
|
KeyboardLayouts, LogicalOutput, Mode, Output, OutputConfigChanged, Request, Response, Socket,
|
||||||
|
Transform,
|
||||||
};
|
};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> {
|
|||||||
action: action.clone(),
|
action: action.clone(),
|
||||||
},
|
},
|
||||||
Msg::Workspaces => Request::Workspaces,
|
Msg::Workspaces => Request::Workspaces,
|
||||||
|
Msg::KeyboardLayouts => Request::KeyboardLayouts,
|
||||||
Msg::RequestError => Request::ReturnError,
|
Msg::RequestError => Request::ReturnError,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -238,6 +240,27 @@ pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> {
|
|||||||
println!("{is_active}{idx}{name}");
|
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(())
|
Ok(())
|
||||||
|
|||||||
+19
-1
@@ -8,8 +8,9 @@ use calloop::io::Async;
|
|||||||
use directories::BaseDirs;
|
use directories::BaseDirs;
|
||||||
use futures_util::io::{AsyncReadExt, BufReader};
|
use futures_util::io::{AsyncReadExt, BufReader};
|
||||||
use futures_util::{AsyncBufReadExt, AsyncWriteExt};
|
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::desktop::Window;
|
||||||
|
use smithay::input::keyboard::XkbContextHandler;
|
||||||
use smithay::reexports::calloop::generic::Generic;
|
use smithay::reexports::calloop::generic::Generic;
|
||||||
use smithay::reexports::calloop::{Interest, LoopHandle, Mode, PostAction};
|
use smithay::reexports::calloop::{Interest, LoopHandle, Mode, PostAction};
|
||||||
use smithay::reexports::rustix::fs::unlink;
|
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"))?;
|
let output = result.map_err(|_| String::from("error getting active output info"))?;
|
||||||
Response::FocusedOutput(output)
|
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)
|
Ok(response)
|
||||||
|
|||||||
Reference in New Issue
Block a user