aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKirill Chibisov <contact@kchibisov.com>2023-11-02 00:10:22 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2023-11-08 19:09:11 +0400
commit907e0a03efcce6ba35aa6405e130f316bc217c5a (patch)
treea7e7aa34c0fabdd055baf69df9f3f2dc17746123 /src
parenteb7d20c638e8912747ee21a4b8de95dd27bb7aba (diff)
downloadniri-907e0a03efcce6ba35aa6405e130f316bc217c5a.tar.gz
niri-907e0a03efcce6ba35aa6405e130f316bc217c5a.tar.bz2
niri-907e0a03efcce6ba35aa6405e130f316bc217c5a.zip
Add 'input.keyboard.track_layout' config option
Track layout for each window individually when user requested `Window` tracking mode, keeping the default as global.
Diffstat (limited to 'src')
-rw-r--r--src/config.rs13
-rw-r--r--src/niri.rs43
2 files changed, 52 insertions, 4 deletions
diff --git a/src/config.rs b/src/config.rs
index ac1917bc..b7510d8d 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -62,6 +62,8 @@ pub struct Keyboard {
pub repeat_delay: u16,
#[knuffel(child, unwrap(argument), default = 25)]
pub repeat_rate: u8,
+ #[knuffel(child, unwrap(argument), default)]
+ pub track_layout: TrackLayout,
}
#[derive(knuffel::Decode, Debug, Default, PartialEq, Eq)]
@@ -78,6 +80,15 @@ pub struct Xkb {
pub options: Option<String>,
}
+#[derive(knuffel::DecodeScalar, Debug, Default, PartialEq, Eq)]
+pub enum TrackLayout {
+ /// The layout change is global.
+ #[default]
+ Global,
+ /// The layout change is window local.
+ Window,
+}
+
// FIXME: Add the rest of the settings.
#[derive(knuffel::Decode, Debug, Default, PartialEq)]
pub struct Touchpad {
@@ -514,6 +525,7 @@ mod tests {
keyboard {
repeat-delay 600
repeat-rate 25
+ track-layout "window"
xkb {
layout "us,ru"
options "grp:win_space_toggle"
@@ -587,6 +599,7 @@ mod tests {
},
repeat_delay: 600,
repeat_rate: 25,
+ track_layout: TrackLayout::Window,
},
touchpad: Touchpad {
tap: true,
diff --git a/src/niri.rs b/src/niri.rs
index eb1cd243..275358b8 100644
--- a/src/niri.rs
+++ b/src/niri.rs
@@ -1,4 +1,4 @@
-use std::cell::RefCell;
+use std::cell::{Cell, RefCell};
use std::collections::{HashMap, HashSet};
use std::ffi::OsString;
use std::path::PathBuf;
@@ -29,7 +29,7 @@ use smithay::desktop::utils::{
under_from_surface_tree, update_surface_primary_scanout_output, OutputPresentationFeedback,
};
use smithay::desktop::{layer_map_for_output, PopupManager, Space, Window, WindowSurfaceType};
-use smithay::input::keyboard::XkbConfig;
+use smithay::input::keyboard::{Layout as KeyboardLayout, XkbConfig, XkbContextHandler};
use smithay::input::pointer::{CursorIcon, CursorImageAttributes, CursorImageStatus, MotionEvent};
use smithay::input::{Seat, SeatState};
use smithay::output::Output;
@@ -76,7 +76,7 @@ use smithay::wayland::text_input::TextInputManagerState;
use smithay::wayland::virtual_keyboard::VirtualKeyboardManagerState;
use crate::backend::{Backend, RenderResult, Tty, Winit};
-use crate::config::Config;
+use crate::config::{Config, TrackLayout};
use crate::cursor::{CursorManager, CursorTextureCache, RenderCursor, XCursor};
#[cfg(feature = "dbus")]
use crate::dbus::gnome_shell_screenshot::{NiriToScreenshot, ScreenshotToNiri};
@@ -382,8 +382,43 @@ impl State {
};
let keyboard = self.niri.seat.get_keyboard().unwrap();
- if keyboard.current_focus() != focus {
+ let current_focus = keyboard.current_focus();
+ if current_focus != focus {
+ if self.niri.config.borrow().input.keyboard.track_layout == TrackLayout::Window {
+ let current_layout =
+ keyboard.with_kkb_state(self, |context| context.active_layout());
+
+ let mut new_layout = current_layout;
+ // Store the currently active layout for the surface.
+ if let Some(current_focus) = current_focus.as_ref() {
+ with_states(current_focus, |data| {
+ let cell = data
+ .data_map
+ .get_or_insert::<Cell<KeyboardLayout>, _>(Cell::default);
+ cell.set(current_layout);
+ });
+ }
+
+ if let Some(focus) = focus.as_ref() {
+ new_layout = with_states(focus, |data| {
+ let cell = data.data_map.get_or_insert::<Cell<KeyboardLayout>, _>(|| {
+ // The default layout is effectively the first layout in the
+ // keymap, so use it for new windows.
+ Cell::new(KeyboardLayout::default())
+ });
+ cell.get()
+ });
+ }
+ if new_layout != current_layout && focus.is_some() {
+ keyboard.set_focus(self, None, SERIAL_COUNTER.next_serial());
+ keyboard.with_kkb_state(self, |mut context| {
+ context.set_layout(new_layout);
+ });
+ }
+ }
+
keyboard.set_focus(self, focus, SERIAL_COUNTER.next_serial());
+
// FIXME: can be more granular.
self.niri.queue_redraw_all();
}