Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 46 additions & 20 deletions src/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ use std::any::Any;
use std::cmp::min;
use std::collections::hash_map::Entry;
use std::collections::HashSet;
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;

use calloop::timer::{TimeoutAction, Timer};
use input::event::gesture::GestureEventCoordinates as _;
use niri_config::{
Action, Bind, Binds, Config, Key, ModKey, Modifiers, MruDirection, SwitchBinds, Trigger,
Action, Bind, Binds, Config, Key, ModKey, Modifiers, MruDirection, SwitchBinds, Trigger, Xkb
};
use niri_ipc::LayoutSwitchTarget;
use smithay::backend::input::{
Expand All @@ -19,6 +20,7 @@ use smithay::backend::input::{
TabletToolTipState, TouchEvent,
};
use smithay::backend::libinput::LibinputInputBackend;
use smithay::input::keyboard::KeyboardHandle;
use smithay::input::keyboard::{keysyms, FilterResult, Keysym, Layout, ModifiersState};
use smithay::input::pointer::{
AxisFrame, ButtonEvent, CursorIcon, CursorImageStatus, Focus, GestureHoldBeginEvent,
Expand Down Expand Up @@ -67,6 +69,8 @@ use backend_ext::{NiriInputBackend as InputBackend, NiriInputDevice as _};

pub const DOUBLE_CLICK_TIME: Duration = Duration::from_millis(400);

static RESETKEYMAP: AtomicBool = AtomicBool::new(false);

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct TabletData {
pub aspect_ratio: f64,
Expand Down Expand Up @@ -336,16 +340,20 @@ impl State {
.is_some_and(KeyboardShortcutsInhibitor::is_active)
}

fn on_keyboard<I: InputBackend>(
pub fn on_keyboard_real(
&mut self,
event: I::KeyboardKeyEvent,
key: Keycode,
state: KeyState,
time: u32,
keyboard: KeyboardHandle<Self>,
consumed_by_a11y: &mut bool,
) {
RESETKEYMAP.store(true, Ordering::SeqCst);

let mod_key = self.backend.mod_key(&self.niri.config.borrow());

let serial = SERIAL_COUNTER.next_serial();
let time = Event::time_msec(&event);
let pressed = event.state() == KeyState::Pressed;
let pressed = state == KeyState::Pressed;

// Stop bind key repeat on any release. This won't work 100% correctly in cases like:
// 1. Press Mod
Expand All @@ -369,23 +377,14 @@ impl State {
// Accessibility modifier grabs should override XKB state changes (e.g. Caps Lock), so we
// need to process them before keyboard.input() below.
#[cfg(feature = "dbus")]
if self.a11y_process_key(
Duration::from_millis(u64::from(time)),
event.key_code(),
event.state(),
) {
if self.a11y_process_key(Duration::from_millis(u64::from(time)), key, state) {
*consumed_by_a11y = true;
return;
}

let Some(Some(bind)) = self.niri.seat.get_keyboard().unwrap().input(
self,
event.key_code(),
event.state(),
serial,
time,
|this, mods, keysym| {
let key_code = event.key_code();
let Some(Some(bind)) =
keyboard.input(self, key, state, serial, time, |this, mods, keysym| {
let key_code = key;
let modified = keysym.modified_sym();
let raw = keysym.raw_latin_sym_or_raw_current_sym();
let modifiers = modifiers_from_state(*mods);
Expand Down Expand Up @@ -468,8 +467,8 @@ impl State {
}

res
},
) else {
})
else {
return;
};

Expand All @@ -481,6 +480,33 @@ impl State {

self.start_key_repeat(bind);
}
fn on_keyboard<I: InputBackend>(
&mut self,
event: I::KeyboardKeyEvent,
consumed_by_a11y: &mut bool,
) {
{
let config = self.niri.config.borrow();
let xkb_config = config.input.keyboard.xkb.clone();
std::mem::drop(config);
if RESETKEYMAP.load(Ordering::Relaxed) {
if xkb_config != Xkb::default() {
self.set_xkb_config(xkb_config.to_xkb_config());
} else {
let xkb = self.niri.xkb_from_locale1.clone().unwrap_or_default();
self.set_xkb_config(xkb.to_xkb_config());
}
}
}
self.on_keyboard_real(
event.key_code(),
event.state(),
Event::time_msec(&event),
self.niri.seat.get_keyboard().unwrap(),
consumed_by_a11y,
);
RESETKEYMAP.store(false, Ordering::SeqCst);
}

fn start_key_repeat(&mut self, bind: Bind) {
if !bind.repeat {
Expand Down
62 changes: 59 additions & 3 deletions src/niri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use niri_config::{
WorkspaceReference, Xkb, DEFAULT_MRU_COMMIT_MS,
};
use smithay::backend::allocator::Fourcc;
use smithay::backend::input::Keycode;
use smithay::backend::input::{KeyState, Keycode};
use smithay::backend::renderer::damage::OutputDamageTracker;
use smithay::backend::renderer::element::memory::MemoryRenderBufferRenderElement;
use smithay::backend::renderer::element::surface::{
Expand All @@ -46,6 +46,8 @@ use smithay::desktop::{
find_popup_root_surface, layer_map_for_output, LayerMap, LayerSurface, PopupGrab, PopupManager,
PopupUngrabStrategy, Space, Window, WindowSurfaceType,
};
use smithay::input::keyboard::xkb::ModMask;
use smithay::input::keyboard::KeyboardHandle;
use smithay::input::keyboard::{Layout as KeyboardLayout, XkbConfig};
use smithay::input::pointer::{
CursorIcon, CursorImageStatus, CursorImageSurfaceData, Focus,
Expand Down Expand Up @@ -107,7 +109,7 @@ use smithay::wayland::socket::ListeningSocketSource;
use smithay::wayland::tablet_manager::TabletManagerState;
use smithay::wayland::text_input::TextInputManagerState;
use smithay::wayland::viewporter::ViewporterState;
use smithay::wayland::virtual_keyboard::VirtualKeyboardManagerState;
use smithay::wayland::virtual_keyboard::{VirtualKeyboardHandler, VirtualKeyboardManagerState};
use smithay::wayland::xdg_activation::XdgActivationState;
use smithay::wayland::xdg_foreign::XdgForeignState;

Expand Down Expand Up @@ -1367,7 +1369,7 @@ impl State {
}
}

fn set_xkb_config(&mut self, xkb: XkbConfig) {
pub fn set_xkb_config(&mut self, xkb: XkbConfig) {
let keyboard = self.niri.seat.get_keyboard().unwrap();
let num_lock = keyboard.modifier_state().num_lock;
if let Err(err) = keyboard.set_xkb_config(self, xkb) {
Expand Down Expand Up @@ -6566,6 +6568,60 @@ fn scale_relocate_crop<E: Element>(
CropRenderElement::from_element(elem, output_scale, ws_geo)
}

impl VirtualKeyboardHandler for State {
fn on_keyboard_event(
&mut self,
keycode: Keycode,
state: KeyState,
time: u32,
keyboard: KeyboardHandle<Self>,
) {
// Make sure some logic like workspace clean-up has a chance to run before doing actions.
self.niri.advance_animations();

if self.niri.monitors_active {
// Notify the idle-notifier of activity.
self.niri.notify_activity();
} else {
// Power on monitors if they were off.
self.niri.activate_monitors(&mut self.backend);

// Notify the idle-notifier of activity only if we're also powering on the
// monitors.
self.niri.notify_activity();
}
let mut consumed_by_a11y = false;

self.on_keyboard_real(keycode, state, time, keyboard, &mut consumed_by_a11y);

let hide_hotkey_overlay = self.niri.hotkey_overlay.is_open();

let hide_exit_confirm_dialog = self.niri.exit_confirm_dialog.is_open();
if consumed_by_a11y {
return;
}

// Do this last so that screenshot still gets it.
if hide_hotkey_overlay && self.niri.hotkey_overlay.hide() {
self.niri.queue_redraw_all();
}

if hide_exit_confirm_dialog && self.niri.exit_confirm_dialog.hide() {
self.niri.queue_redraw_all();
}
}

/// We handle modifiers when the key event is sent
fn on_keyboard_modifiers(
&mut self,
_depressed_mods: ModMask,
_latched_mods: ModMask,
_locked_mods: ModMask,
_keyboard: KeyboardHandle<Self>,
) {
}
}

niri_render_elements! {
OutputRenderElements<R> => {
Monitor = MonitorRenderElement<R>,
Expand Down