diff options
| author | may <63159454+m4rch3n1ng@users.noreply.github.com> | 2025-01-30 14:50:05 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-01-30 13:50:05 +0000 |
| commit | e412a0fc6bc0e04b4238b3d6de4962c2e19ea4ec (patch) | |
| tree | 290eb88c9d7c86e4f579e05f5181cda53bbf680a | |
| parent | fb5fedbf24aa66909bb9d112856f27ceb04766a8 (diff) | |
| download | niri-e412a0fc6bc0e04b4238b3d6de4962c2e19ea4ec.tar.gz niri-e412a0fc6bc0e04b4238b3d6de4962c2e19ea4ec.tar.bz2 niri-e412a0fc6bc0e04b4238b3d6de4962c2e19ea4ec.zip | |
add option to set xkb config from file (#1062)
* add option to set xkb config from file
* Apply suggestions from code review
---------
Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
| -rw-r--r-- | niri-config/src/lib.rs | 2 | ||||
| -rw-r--r-- | src/niri.rs | 52 | ||||
| -rw-r--r-- | wiki/Configuration:-Input.md | 16 |
3 files changed, 65 insertions, 5 deletions
diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs index b70499d1..dbf3756d 100644 --- a/niri-config/src/lib.rs +++ b/niri-config/src/lib.rs @@ -136,6 +136,8 @@ pub struct Xkb { pub variant: String, #[knuffel(child, unwrap(argument))] pub options: Option<String>, + #[knuffel(child, unwrap(argument))] + pub file: Option<String>, } impl Xkb { diff --git a/src/niri.rs b/src/niri.rs index 73488c41..36c56f30 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -155,7 +155,7 @@ use crate::ui::screenshot_ui::{OutputScreenshot, ScreenshotUi, ScreenshotUiRende use crate::utils::scale::{closest_representable_scale, guess_monitor_scale}; use crate::utils::spawning::CHILD_ENV; use crate::utils::{ - center, center_f64, get_monotonic_time, ipc_transform_to_smithay, logical_output, + center, center_f64, expand_home, get_monotonic_time, ipc_transform_to_smithay, logical_output, make_screenshot_path, output_matches_name, output_size, send_scale_transform, write_png_rgba8, }; use crate::window::{InitialConfigureState, Mapped, ResolvedWindowRules, Unmapped, WindowRef}; @@ -588,6 +588,8 @@ impl State { let mut state = Self { backend, niri }; + // Load the xkb_file config option if set by the user. + state.load_xkb_file(); // Initialize some IPC server state. state.ipc_keyboard_layouts_changed(); @@ -1083,6 +1085,31 @@ impl State { } } + /// Loads the xkb keymap from a file config setting. + fn set_xkb_file(&mut self, xkb_file: String) -> anyhow::Result<()> { + let xkb_file = PathBuf::from(xkb_file); + let xkb_file = expand_home(&xkb_file) + .context("failed to expand ~")? + .unwrap_or(xkb_file); + + let keymap = std::fs::read_to_string(xkb_file).context("failed to read xkb_file")?; + + let xkb = self.niri.seat.get_keyboard().unwrap(); + xkb.set_keymap_from_string(self, keymap) + .context("failed to set keymap")?; + + Ok(()) + } + + fn load_xkb_file(&mut self) { + let xkb_file = self.niri.config.borrow().input.keyboard.xkb.file.clone(); + if let Some(xkb_file) = xkb_file { + if let Err(err) = self.set_xkb_file(xkb_file) { + warn!("error loading xkb_file: {err:?}"); + } + } + } + pub fn reload_config(&mut self, path: PathBuf) { let _span = tracy_client::span!("State::reload_config"); @@ -1247,10 +1274,25 @@ impl State { drop(old_config); // Now with a &mut self we can reload the xkb config. - if let Some(xkb) = reload_xkb { - let keyboard = self.niri.seat.get_keyboard().unwrap(); - if let Err(err) = keyboard.set_xkb_config(self, xkb.to_xkb_config()) { - warn!("error updating xkb config: {err:?}"); + if let Some(mut xkb) = reload_xkb { + let mut set_xkb_config = true; + + // It's fine to .take() the xkb file, as this is a + // clone and the file field is not used in the XkbConfig. + if let Some(xkb_file) = xkb.file.take() { + if let Err(err) = self.set_xkb_file(xkb_file) { + warn!("error reloading xkb_file: {err:?}"); + } else { + // We successfully set xkb file so we don't need to fallback to XkbConfig. + set_xkb_config = false; + } + } + + if set_xkb_config { + let keyboard = self.niri.seat.get_keyboard().unwrap(); + if let Err(err) = keyboard.set_xkb_config(self, xkb.to_xkb_config()) { + warn!("error updating xkb config: {err:?}"); + } } self.ipc_keyboard_layouts_changed(); diff --git a/wiki/Configuration:-Input.md b/wiki/Configuration:-Input.md index 899d1beb..cbb8c2d2 100644 --- a/wiki/Configuration:-Input.md +++ b/wiki/Configuration:-Input.md @@ -17,6 +17,7 @@ input { // options "compose:ralt,ctrl:nocaps" // model "" // rules "" + // file "~/.config/keymap.xkb" } // repeat-delay 600 @@ -112,6 +113,21 @@ input { } ``` +> [!TIP] +> +> Alternatively you can directly set a path to a .xkb file containing an xkb keymap. +> This overrides all other xkb settings +> +> ```kdl +> input { +> keyboard { +> xkb { +> file "~/.config/keymap.xkb" +> } +> } +> } +> ``` + When using multiple layouts, niri can remember the current layout globally (the default) or per-window. You can control this with the `track-layout` option. |
