Keep modifier state in WLRoots input emulator

This commit is contained in:
VassiliDev
2024-11-25 19:36:14 -05:00
committed by Ferdinand Schober
parent 2e2046dc36
commit 345804355a
2 changed files with 63 additions and 2 deletions

View File

@@ -25,6 +25,7 @@ tokio = { version = "1.32.0", features = [
once_cell = "1.19.0"
[target.'cfg(all(unix, not(target_os="macos")))'.dependencies]
bitflags = "2.6.0"
wayland-client = { version = "0.31.1", optional = true }
wayland-protocols = { version = "0.32.1", features = [
"client",
@@ -42,6 +43,8 @@ ashpd = { version = "0.10", default-features = false, features = [
"tokio",
], optional = true }
reis = { version = "0.4", features = ["tokio"], optional = true }
keycode = "0.4.0"
[target.'cfg(target_os="macos")'.dependencies]
bitflags = "2.6.0"

View File

@@ -2,9 +2,11 @@ use crate::error::EmulationError;
use super::{error::WlrootsEmulationCreationError, Emulation};
use async_trait::async_trait;
use bitflags::bitflags;
use std::collections::HashMap;
use std::io;
use std::os::fd::{AsFd, OwnedFd};
use std::sync::{Arc, Mutex};
use std::time::{SystemTime, UNIX_EPOCH};
use wayland_client::backend::WaylandError;
use wayland_client::WEnum;
@@ -29,7 +31,7 @@ use wayland_client::{
Connection, Dispatch, EventQueue, QueueHandle,
};
use input_event::{Event, KeyboardEvent, PointerEvent};
use input_event::{scancode, Event, KeyboardEvent, PointerEvent};
use super::error::WaylandBindError;
use super::EmulationHandle;
@@ -103,7 +105,11 @@ impl State {
panic!("no keymap");
}
let vinput = VirtualInput { pointer, keyboard };
let vinput = VirtualInput {
pointer,
keyboard,
modifiers: Arc::new(Mutex::new(XMods::empty())),
};
self.input_for_client.insert(client, vinput);
}
@@ -174,6 +180,7 @@ impl Emulation for WlrootsEmulation {
struct VirtualInput {
pointer: Vp,
keyboard: Vk,
modifiers: Arc<Mutex<XMods>>,
}
impl VirtualInput {
@@ -212,6 +219,13 @@ impl VirtualInput {
Event::Keyboard(e) => match e {
KeyboardEvent::Key { time, key, state } => {
self.keyboard.key(time, key, state as u32);
if let Ok(mut mods) = self.modifiers.lock() {
if mods.from_key_event(key, state) {
log::trace!("Key triggers modifier change");
log::trace!("Modifiers: {:?}", mods);
self.keyboard.modifiers(mods.bits(), 0, 0, 0);
}
}
}
KeyboardEvent::Modifiers {
depressed: mods_depressed,
@@ -279,3 +293,47 @@ impl Dispatch<WlSeat, ()> for State {
}
}
}
// From X11/X.h
bitflags! {
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
struct XMods: u32 {
const ShiftMask = (1<<0);
const LockMask = (1<<1);
const ControlMask = (1<<2);
const Mod1Mask = (1<<3);
const Mod2Mask = (1<<4);
const Mod3Mask = (1<<5);
const Mod4Mask = (1<<6);
const Mod5Mask = (1<<7);
}
}
impl XMods {
fn from_key_event(&mut self, key: u32, state: u8) -> bool {
if let Ok(key) = scancode::Linux::try_from(key) {
log::trace!("Attempting to process modifier from: {:#?}", key);
let mask = match key {
scancode::Linux::KeyLeftShift | scancode::Linux::KeyRightShift => XMods::ShiftMask,
scancode::Linux::KeyCapsLock => XMods::LockMask,
scancode::Linux::KeyLeftCtrl | scancode::Linux::KeyRightCtrl => XMods::ControlMask,
scancode::Linux::KeyLeftAlt | scancode::Linux::KeyRightalt => XMods::Mod1Mask,
scancode::Linux::KeyLeftMeta | scancode::Linux::KeyRightmeta => XMods::Mod4Mask,
_ => XMods::empty(),
};
// unchanged
if mask.is_empty() {
log::trace!("{:#?} is not a modifier key", key);
return false;
}
match state {
1 => self.insert(mask),
_ => self.remove(mask),
}
true
} else {
false
}
}
}