- Add optional modifier-only Super binding whose tap is cancelled by other input, focus changes, grabs, locks, and session teardown. - Ship the native ferese-rime user service, Rime defaults, installer inventory, package dependencies, session environment, and docs. - Vendor Smithay 8a27023 with the SHM texture-cache format fix and add GPU regressions for format changes and resize snapshots. - Release reused CRTC owners before staging output modes, then restore changed outputs before former owners when a transaction fails. - Wait for resize-capture GPU completion, expand filtered surface damage, and preserve IME popup origin under fractional scaling. - Mark weekends like holidays in both calendar layouts.
90 lines
3.9 KiB
Rust
90 lines
3.9 KiB
Rust
use smithay::backend::input::{Event, InputEvent, KeyboardKeyEvent};
|
|
use smithay::utils::SERIAL_COUNTER;
|
|
use smithay::wayland::input_method::InputMethodSeat;
|
|
use smithay::wayland::virtual_keyboard::{
|
|
VirtualKeyboardBackend, VirtualKeyboardHandler, VirtualKeyboardSpecialEvent,
|
|
};
|
|
|
|
use crate::Ferese;
|
|
|
|
impl VirtualKeyboardHandler for Ferese {
|
|
fn process_virtual_keyboard_event(&mut self, event: InputEvent<VirtualKeyboardBackend>) {
|
|
let keyboard = self.seat.get_keyboard().expect("seat has a keyboard");
|
|
if self.session_lock.active() {
|
|
// Synthetic input never enters a lock surface. Still reconcile
|
|
// keys from a departing/previously active auxiliary device.
|
|
let device = match &event {
|
|
InputEvent::Keyboard { event } => Some(event.device()),
|
|
InputEvent::DeviceRemoved { device } => Some(device.clone()),
|
|
_ => None,
|
|
};
|
|
if let Some(device) = device {
|
|
self.super_tap.cancel();
|
|
keyboard.release_source(self, device.source());
|
|
}
|
|
return;
|
|
}
|
|
match event {
|
|
InputEvent::DeviceAdded { device }
|
|
| InputEvent::Special(VirtualKeyboardSpecialEvent::KeymapChanged { device }) => {
|
|
if let Some(keymap) = device.keymap() {
|
|
let current = keyboard.with_xkb_state(self, |context| {
|
|
context.xkb().lock().unwrap().keymap_as_string()
|
|
});
|
|
if current != *keymap
|
|
&& let Err(error) =
|
|
keyboard.set_keymap_from_string(self, keymap.to_string())
|
|
{
|
|
tracing::warn!(%error, "invalid virtual keyboard keymap");
|
|
}
|
|
}
|
|
}
|
|
InputEvent::Keyboard { event } => {
|
|
let device = event.device();
|
|
let grab_client = self.seat.input_method().keyboard_grab_client();
|
|
if grab_client.is_some() && grab_client == device.client() {
|
|
// An IME forwards keys it did not consume. The physical path
|
|
// already updated XKB and compositor shortcuts: forwarding
|
|
// through that path again would recurse into the IME grab.
|
|
keyboard.input_forward_bypassing_grab(
|
|
self,
|
|
event.key_code(),
|
|
event.state(),
|
|
SERIAL_COUNTER.next_serial(),
|
|
event.time(),
|
|
true,
|
|
);
|
|
} else {
|
|
self.process_input_event_from_source::<VirtualKeyboardBackend>(
|
|
InputEvent::Keyboard { event },
|
|
device.source(),
|
|
);
|
|
}
|
|
}
|
|
InputEvent::Special(VirtualKeyboardSpecialEvent::Modifiers {
|
|
device,
|
|
mods_depressed,
|
|
mods_latched,
|
|
mods_locked,
|
|
group,
|
|
}) => {
|
|
let grab_client = self.seat.input_method().keyboard_grab_client();
|
|
if grab_client.is_some() && grab_client == device.client() {
|
|
// The physical path already owns these modifiers. An
|
|
// asynchronous IME echo must not restore an old mask after
|
|
// the physical release has arrived.
|
|
return;
|
|
}
|
|
keyboard.with_xkb_state(self, |mut context| {
|
|
context.set_modifier_mask(mods_depressed, mods_latched, mods_locked, group)
|
|
});
|
|
}
|
|
InputEvent::DeviceRemoved { device } => {
|
|
self.super_tap.cancel();
|
|
keyboard.release_source(self, device.source());
|
|
}
|
|
_ => (),
|
|
}
|
|
}
|
|
}
|