mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-22 02:01:55 +07:00
Add 'input.keyboard.track_layout' config option
Track layout for each window individually when user requested `Window` tracking mode, keeping the default as global.
This commit is contained in:
committed by
Ivan Molodetskikh
parent
eb7d20c638
commit
907e0a03ef
@@ -16,6 +16,11 @@ input {
|
|||||||
// Delay is in milliseconds before the repeat starts. Rate is in characters per second.
|
// Delay is in milliseconds before the repeat starts. Rate is in characters per second.
|
||||||
// repeat-delay 600
|
// repeat-delay 600
|
||||||
// repeat-rate 25
|
// repeat-rate 25
|
||||||
|
|
||||||
|
// Niri can remember the keyboard layout globally (the default) or per-window.
|
||||||
|
// - "global" - layout change is global for all windows.
|
||||||
|
// - "window" - layout is tracked for each window individually.
|
||||||
|
// track-layout "global"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next sections include libinput settings.
|
// Next sections include libinput settings.
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ pub struct Keyboard {
|
|||||||
pub repeat_delay: u16,
|
pub repeat_delay: u16,
|
||||||
#[knuffel(child, unwrap(argument), default = 25)]
|
#[knuffel(child, unwrap(argument), default = 25)]
|
||||||
pub repeat_rate: u8,
|
pub repeat_rate: u8,
|
||||||
|
#[knuffel(child, unwrap(argument), default)]
|
||||||
|
pub track_layout: TrackLayout,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(knuffel::Decode, Debug, Default, PartialEq, Eq)]
|
#[derive(knuffel::Decode, Debug, Default, PartialEq, Eq)]
|
||||||
@@ -78,6 +80,15 @@ pub struct Xkb {
|
|||||||
pub options: Option<String>,
|
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.
|
// FIXME: Add the rest of the settings.
|
||||||
#[derive(knuffel::Decode, Debug, Default, PartialEq)]
|
#[derive(knuffel::Decode, Debug, Default, PartialEq)]
|
||||||
pub struct Touchpad {
|
pub struct Touchpad {
|
||||||
@@ -514,6 +525,7 @@ mod tests {
|
|||||||
keyboard {
|
keyboard {
|
||||||
repeat-delay 600
|
repeat-delay 600
|
||||||
repeat-rate 25
|
repeat-rate 25
|
||||||
|
track-layout "window"
|
||||||
xkb {
|
xkb {
|
||||||
layout "us,ru"
|
layout "us,ru"
|
||||||
options "grp:win_space_toggle"
|
options "grp:win_space_toggle"
|
||||||
@@ -587,6 +599,7 @@ mod tests {
|
|||||||
},
|
},
|
||||||
repeat_delay: 600,
|
repeat_delay: 600,
|
||||||
repeat_rate: 25,
|
repeat_rate: 25,
|
||||||
|
track_layout: TrackLayout::Window,
|
||||||
},
|
},
|
||||||
touchpad: Touchpad {
|
touchpad: Touchpad {
|
||||||
tap: true,
|
tap: true,
|
||||||
|
|||||||
+39
-4
@@ -1,4 +1,4 @@
|
|||||||
use std::cell::RefCell;
|
use std::cell::{Cell, RefCell};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -29,7 +29,7 @@ use smithay::desktop::utils::{
|
|||||||
under_from_surface_tree, update_surface_primary_scanout_output, OutputPresentationFeedback,
|
under_from_surface_tree, update_surface_primary_scanout_output, OutputPresentationFeedback,
|
||||||
};
|
};
|
||||||
use smithay::desktop::{layer_map_for_output, PopupManager, Space, Window, WindowSurfaceType};
|
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::pointer::{CursorIcon, CursorImageAttributes, CursorImageStatus, MotionEvent};
|
||||||
use smithay::input::{Seat, SeatState};
|
use smithay::input::{Seat, SeatState};
|
||||||
use smithay::output::Output;
|
use smithay::output::Output;
|
||||||
@@ -76,7 +76,7 @@ use smithay::wayland::text_input::TextInputManagerState;
|
|||||||
use smithay::wayland::virtual_keyboard::VirtualKeyboardManagerState;
|
use smithay::wayland::virtual_keyboard::VirtualKeyboardManagerState;
|
||||||
|
|
||||||
use crate::backend::{Backend, RenderResult, Tty, Winit};
|
use crate::backend::{Backend, RenderResult, Tty, Winit};
|
||||||
use crate::config::Config;
|
use crate::config::{Config, TrackLayout};
|
||||||
use crate::cursor::{CursorManager, CursorTextureCache, RenderCursor, XCursor};
|
use crate::cursor::{CursorManager, CursorTextureCache, RenderCursor, XCursor};
|
||||||
#[cfg(feature = "dbus")]
|
#[cfg(feature = "dbus")]
|
||||||
use crate::dbus::gnome_shell_screenshot::{NiriToScreenshot, ScreenshotToNiri};
|
use crate::dbus::gnome_shell_screenshot::{NiriToScreenshot, ScreenshotToNiri};
|
||||||
@@ -382,8 +382,43 @@ impl State {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let keyboard = self.niri.seat.get_keyboard().unwrap();
|
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());
|
keyboard.set_focus(self, focus, SERIAL_COUNTER.next_serial());
|
||||||
|
|
||||||
// FIXME: can be more granular.
|
// FIXME: can be more granular.
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user