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

View File

@@ -2,9 +2,11 @@ use crate::error::EmulationError;
use super::{error::WlrootsEmulationCreationError, Emulation}; use super::{error::WlrootsEmulationCreationError, Emulation};
use async_trait::async_trait; use async_trait::async_trait;
use bitflags::bitflags;
use std::collections::HashMap; use std::collections::HashMap;
use std::io; use std::io;
use std::os::fd::{AsFd, OwnedFd}; use std::os::fd::{AsFd, OwnedFd};
use std::sync::{Arc, Mutex};
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use wayland_client::backend::WaylandError; use wayland_client::backend::WaylandError;
use wayland_client::WEnum; use wayland_client::WEnum;
@@ -29,7 +31,7 @@ use wayland_client::{
Connection, Dispatch, EventQueue, QueueHandle, Connection, Dispatch, EventQueue, QueueHandle,
}; };
use input_event::{Event, KeyboardEvent, PointerEvent}; use input_event::{scancode, Event, KeyboardEvent, PointerEvent};
use super::error::WaylandBindError; use super::error::WaylandBindError;
use super::EmulationHandle; use super::EmulationHandle;
@@ -103,7 +105,11 @@ impl State {
panic!("no keymap"); 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); self.input_for_client.insert(client, vinput);
} }
@@ -174,6 +180,7 @@ impl Emulation for WlrootsEmulation {
struct VirtualInput { struct VirtualInput {
pointer: Vp, pointer: Vp,
keyboard: Vk, keyboard: Vk,
modifiers: Arc<Mutex<XMods>>,
} }
impl VirtualInput { impl VirtualInput {
@@ -212,6 +219,13 @@ impl VirtualInput {
Event::Keyboard(e) => match e { Event::Keyboard(e) => match e {
KeyboardEvent::Key { time, key, state } => { KeyboardEvent::Key { time, key, state } => {
self.keyboard.key(time, key, state as u32); 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 { KeyboardEvent::Modifiers {
depressed: mods_depressed, 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
}
}
}