From 8ec1ffb740dfbd02ccc6cdaa431dd3438ec51f68 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Wed, 2 Sep 2026 12:49:01 -0700 Subject: [PATCH] protocols/keyboard-layout: Send ei `modifiers` on group change This makes `cosmic-osk` show a group change on `super+space`. Previously a change like that wouldn't be sent until a keyboard input changed the modifier state, for instance releasing the shift key. --- src/config/mod.rs | 4 +++- src/input/mod.rs | 11 +++-------- src/libei.rs | 4 +++- src/wayland/handlers/keyboard_layout.rs | 6 ++++++ src/wayland/protocols/keyboard_layout.rs | 5 ++++- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/config/mod.rs b/src/config/mod.rs index 9db9a9bb..d3d2919b 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -842,7 +842,9 @@ fn config_changed(config: cosmic_config::Config, keys: Vec, state: &mut } if !state.common.ei_seats.is_empty() { let seat = state.common.shell.read().seats.last_active().clone(); - state.broadcast_ei_keyboard_modifiers(&seat); + if let Some(keyboard) = seat.get_keyboard() { + state.broadcast_ei_keyboard_modifiers(&keyboard); + } } state.common.config.cosmic_conf.xkb_config = value; } diff --git a/src/input/mod.rs b/src/input/mod.rs index 6055ad33..0228d3cb 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -49,6 +49,7 @@ use smithay::{ desktop::{PopupKeyboardGrab, WindowSurfaceType, utils::under_from_surface_tree}, input::{ Seat, + keyboard::KeyboardHandle, keyboard::{FilterResult, KeyboardSource, KeysymHandle, ModifiersState}, pointer::{ AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, @@ -1907,13 +1908,7 @@ impl State { /// Mirror the seat's current modifier state to every libei sender with a keyboard via /// `ei_keyboard.modifiers` - pub(crate) fn broadcast_ei_keyboard_modifiers(&self, seat: &Seat) { - if self.common.ei_seats.is_empty() { - return; - } - let Some(keyboard) = seat.get_keyboard() else { - return; - }; + pub(crate) fn broadcast_ei_keyboard_modifiers(&self, keyboard: &KeyboardHandle) { let s = keyboard.modifier_state().serialized; for ei_seat in self.common.ei_seats.values() { ei_seat.keyboard_modifiers(s.depressed, s.locked, s.latched, s.layout_effective); @@ -1958,7 +1953,7 @@ impl State { ) -> FilterResult> { if previous_modifiers != *modifiers { seat.set_last_modifier_change(backend_id, serial); - self.broadcast_ei_keyboard_modifiers(seat); + self.broadcast_ei_keyboard_modifiers(&seat.get_keyboard().unwrap()); } let current_focus = seat.get_keyboard().unwrap().current_focus(); diff --git a/src/libei.rs b/src/libei.rs index ad3a674d..487f0387 100644 --- a/src/libei.rs +++ b/src/libei.rs @@ -124,7 +124,9 @@ pub fn setup_ei( data.update_ei_input_method(); // Notify the remaining libei clients of the now-cleared modifier state let seat = data.common.shell.read().seats.last_active().clone(); - data.broadcast_ei_keyboard_modifiers(&seat); + if let Some(keyboard) = seat.get_keyboard() { + data.broadcast_ei_keyboard_modifiers(&keyboard); + } } EiInputEvent::Event(event) => { use smithay::backend::input::{InputEvent, KeyboardKeyEvent}; diff --git a/src/wayland/handlers/keyboard_layout.rs b/src/wayland/handlers/keyboard_layout.rs index ac1fda87..2477f93b 100644 --- a/src/wayland/handlers/keyboard_layout.rs +++ b/src/wayland/handlers/keyboard_layout.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only +use smithay::input::keyboard::KeyboardHandle; + use crate::state::State; use crate::wayland::protocols::keyboard_layout::{KeyboardLayoutHandler, KeyboardLayoutState}; @@ -7,4 +9,8 @@ impl KeyboardLayoutHandler for State { fn keyboard_layout_state(&mut self) -> &mut KeyboardLayoutState { &mut self.common.keyboard_layout_state } + + fn group_changed(&mut self, keyboard: &KeyboardHandle) { + self.broadcast_ei_keyboard_modifiers(keyboard); + } } diff --git a/src/wayland/protocols/keyboard_layout.rs b/src/wayland/protocols/keyboard_layout.rs index f3a44f0a..8a8840b6 100644 --- a/src/wayland/protocols/keyboard_layout.rs +++ b/src/wayland/protocols/keyboard_layout.rs @@ -17,8 +17,10 @@ use smithay::{ use std::mem; use wayland_backend::server::{ClientId, GlobalId}; -pub trait KeyboardLayoutHandler { +pub trait KeyboardLayoutHandler: SeatHandler { fn keyboard_layout_state(&mut self) -> &mut KeyboardLayoutState; + /// Group has been changed through the protocol + fn group_changed(&mut self, keyboard: &KeyboardHandle); } #[derive(Debug)] @@ -57,6 +59,7 @@ impl KeyboardLayoutState { let active_layout = handle.with_xkb_state(state, |context| { context.xkb().lock().unwrap().active_layout() }); + state.group_changed(handle); if *last_layout != Some(active_layout) { keyboard_layout.group(active_layout.0); *last_layout = Some(active_layout);