From b08bd94353235218ebb43ac50e4a009d2a66b0d8 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Sun, 9 Jan 2022 16:13:56 +0100 Subject: [PATCH] autocommit 2022-01-09 16:13:56 CET --- build.rs | 6 ++++ src/backends/xorg/mod.rs | 2 +- src/client/objects.rs | 2 +- src/ifs/wl_seat/mod.rs | 42 ++++++++++++++++++++------ src/ifs/wl_shm_pool/mod.rs | 5 ++-- src/ifs/wl_surface/mod.rs | 2 +- src/macros.rs | 10 +++++++ src/tasks.rs | 2 +- src/tree.rs | 2 +- src/utils/clonecell.rs | 21 +++++++------ src/utils/mod.rs | 2 +- src/xkbcommon/consts.rs | 23 +++++++++++++++ src/xkbcommon/mod.rs | 60 ++++++++++++++++++++++++++++++++++++++ 13 files changed, 151 insertions(+), 28 deletions(-) diff --git a/build.rs b/build.rs index 5ec33e93..1035b01d 100644 --- a/build.rs +++ b/build.rs @@ -71,6 +71,12 @@ fn main() -> anyhow::Result<()> { "xkb_keymap_compile_flags", )?; write_ty(&mut f, xkbcommon::XKB_KEYMAP_FORMAT, "xkb_keymap_format")?; + write_ty( + &mut f, + xkbcommon::XKB_STATE_COMPONENT, + "xkb_state_component", + )?; + write_ty(&mut f, xkbcommon::XKB_KEY_DIRECTION, "xkb_key_direction")?; println!("cargo:rerun-if-changed=build.rs"); Ok(()) diff --git a/src/backends/xorg/mod.rs b/src/backends/xorg/mod.rs index 8a760519..6fec6ce0 100644 --- a/src/backends/xorg/mod.rs +++ b/src/backends/xorg/mod.rs @@ -8,6 +8,7 @@ use crate::ifs::wl_surface::WlSurface; use crate::pixman::{Image, PixmanError}; use crate::servermem::{ServerMem, ServerMemError}; use crate::tree::{Node, NodeKind, ToplevelNode}; +use crate::utils::clonecell::CloneCell; use crate::utils::copyhashmap::CopyHashMap; use crate::utils::ptr_ext::PtrExt; use crate::wheel::{WheelDispatcher, WheelId}; @@ -24,7 +25,6 @@ use uapi::c; use xcb_dl::{ffi, Xcb, XcbShm, XcbXinput, XcbXkb}; use xcb_dl_util::error::{XcbError, XcbErrorParser}; use xcb_dl_util::xcb_box::XcbBox; -use crate::utils::clonecell::CloneCell; #[derive(Debug, Error)] pub enum XorgBackendError { diff --git a/src/client/objects.rs b/src/client/objects.rs index da4640dc..3eb0bc5a 100644 --- a/src/client/objects.rs +++ b/src/client/objects.rs @@ -8,12 +8,12 @@ use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceId}; use crate::ifs::wl_surface::{WlSurface, WlSurfaceId}; use crate::ifs::xdg_wm_base::{XdgWmBaseId, XdgWmBaseObj}; use crate::object::{Object, ObjectId}; +use crate::utils::clonecell::CloneCell; use crate::utils::copyhashmap::CopyHashMap; use ahash::AHashMap; use std::cell::{RefCell, RefMut}; use std::mem; use std::rc::Rc; -use crate::utils::clonecell::CloneCell; pub struct Objects { pub display: CloneCell>>, diff --git a/src/ifs/wl_seat/mod.rs b/src/ifs/wl_seat/mod.rs index 0e07c653..68a9b51f 100644 --- a/src/ifs/wl_seat/mod.rs +++ b/src/ifs/wl_seat/mod.rs @@ -13,8 +13,9 @@ use crate::ifs::wl_seat::wl_touch::WlTouch; use crate::object::{Interface, Object, ObjectId}; use crate::tree::{Node, NodeBase, NodeKind, ToplevelNode}; use crate::utils::buffd::MsgParser; +use crate::utils::clonecell::CloneCell; use crate::utils::copyhashmap::CopyHashMap; -use crate::xkbcommon::XkbContext; +use crate::xkbcommon::{ModifierState, XkbContext, XkbState, XKB_KEY_DOWN, XKB_KEY_UP}; use crate::State; use ahash::{AHashMap, AHashSet}; use bstr::ByteSlice; @@ -23,7 +24,6 @@ use std::io::Write; use std::rc::Rc; pub use types::*; use uapi::{c, OwnedFd}; -use crate::utils::clonecell::CloneCell; id!(WlSeatId); @@ -57,15 +57,17 @@ pub struct WlSeatGlobal { keyboard_node: CloneCell>, pressed_keys: RefCell>, bindings: RefCell>>>, + kb_state: RefCell, layout: Rc, layout_size: u32, } impl WlSeatGlobal { pub fn new(name: GlobalName, state: &Rc, seat: &Rc) -> Self { - let (layout, layout_size) = { + let (kb_state, layout, layout_size) = { let ctx = XkbContext::new().unwrap(); let keymap = ctx.default_keymap().unwrap(); + let state = keymap.state().unwrap(); let string = keymap.as_str().unwrap(); let mut memfd = uapi::memfd_create("keymap", c::MFD_CLOEXEC | c::MFD_ALLOW_SEALING).unwrap(); @@ -77,7 +79,7 @@ impl WlSeatGlobal { c::F_SEAL_SEAL | c::F_SEAL_GROW | c::F_SEAL_SHRINK | c::F_SEAL_WRITE, ) .unwrap(); - (Rc::new(memfd), (string.len() + 1) as _) + (state, Rc::new(memfd), (string.len() + 1) as _) }; Self { name, @@ -91,6 +93,7 @@ impl WlSeatGlobal { keyboard_node: CloneCell::new(state.root.clone()), pressed_keys: RefCell::new(Default::default()), bindings: Default::default(), + kb_state: RefCell::new(kb_state), layout, layout_size, } @@ -244,6 +247,16 @@ impl WlSeatGlobal { if let NodeKind::Toplevel(tl) = kb_node.clone().into_kind() { self.tl_kb_event(&tl, |k| k.leave(0, tl.surface.surface.surface.id)) .await; + let ModifierState { + mods_depressed, + mods_latched, + mods_locked, + group, + } = self.kb_state.borrow().mods(); + self.tl_kb_event(&tl, |k| { + k.modifiers(0, mods_depressed, mods_latched, mods_locked, group) + }) + .await; } self.keyboard_node.set(node.clone()); } @@ -281,28 +294,39 @@ impl WlSeatGlobal { } async fn key_event(&self, key: u32, state: KeyState) { - let state = { + let (state, xkb_dir) = { let mut pk = self.pressed_keys.borrow_mut(); match state { KeyState::Released => { if !pk.remove(&key) { return; } - log::info!("release"); - wl_keyboard::RELEASED + (wl_keyboard::RELEASED, XKB_KEY_UP) } KeyState::Pressed => { if !pk.insert(key) { return; } - log::info!("press"); - wl_keyboard::PRESSED + (wl_keyboard::PRESSED, XKB_KEY_DOWN) } } }; + let mods = self.kb_state.borrow_mut().update(key, xkb_dir); let node = self.keyboard_node.get().into_kind(); if let NodeKind::Toplevel(node) = node { self.tl_kb_event(&node, |k| k.key(0, 0, key, state)).await; + if let Some(mods) = mods { + self.tl_kb_event(&node, |k| { + k.modifiers( + 0, + mods.mods_depressed, + mods.mods_latched, + mods.mods_locked, + mods.group, + ) + }) + .await; + } } } diff --git a/src/ifs/wl_shm_pool/mod.rs b/src/ifs/wl_shm_pool/mod.rs index 4153697a..83d33b80 100644 --- a/src/ifs/wl_shm_pool/mod.rs +++ b/src/ifs/wl_shm_pool/mod.rs @@ -5,10 +5,10 @@ use crate::clientmem::ClientMem; use crate::ifs::wl_buffer::WlBuffer; use crate::object::{Interface, Object, ObjectId}; use crate::utils::buffd::MsgParser; +use crate::utils::clonecell::CloneCell; use std::rc::Rc; pub use types::*; use uapi::OwnedFd; -use crate::utils::clonecell::CloneCell; const CREATE_BUFFER: u32 = 0; const DESTROY: u32 = 1; @@ -75,7 +75,8 @@ impl WlShmPool { if (req.size as usize) < self.mem.get().len() { return Err(ResizeError::CannotShrink); } - self.mem.set(Rc::new(ClientMem::new(self.fd.raw(), req.size as usize)?)); + self.mem + .set(Rc::new(ClientMem::new(self.fd.raw(), req.size as usize)?)); Ok(()) } diff --git a/src/ifs/wl_surface/mod.rs b/src/ifs/wl_surface/mod.rs index e87f1a65..9d07cb8a 100644 --- a/src/ifs/wl_surface/mod.rs +++ b/src/ifs/wl_surface/mod.rs @@ -13,6 +13,7 @@ use crate::object::{Interface, Object, ObjectId}; use crate::pixman::Region; use crate::tree::{NodeBase, NodeCommon, ToplevelNode}; use crate::utils::buffd::{MsgParser, MsgParserError}; +use crate::utils::clonecell::CloneCell; use crate::utils::copyhashmap::CopyHashMap; use crate::utils::linkedlist::{LinkedList, Node as LinkNode}; use ahash::AHashMap; @@ -21,7 +22,6 @@ use std::mem; use std::ops::{Deref, DerefMut}; use std::rc::Rc; pub use types::*; -use crate::utils::clonecell::CloneCell; const DESTROY: u32 = 0; const ATTACH: u32 = 1; diff --git a/src/macros.rs b/src/macros.rs index d165afd0..f4031d47 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -159,5 +159,15 @@ macro_rules! bitor { Self(self.0 | rhs.0) } } + + impl $name { + pub fn contains(self, rhs: Self) -> bool { + self.0 & rhs.0 == rhs.0 + } + + pub fn is_some(self) -> bool { + self.0 != 0 + } + } }; } diff --git a/src/tasks.rs b/src/tasks.rs index aa8ceceb..284259d5 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -3,10 +3,10 @@ use crate::ifs::wl_output::WlOutputGlobal; use crate::ifs::wl_seat::WlSeatGlobal; use crate::tree::{NodeCommon, NodeExtents, OutputNode}; use crate::utils::asyncevent::AsyncEvent; +use crate::utils::clonecell::CloneCell; use crate::State; use std::cell::{Cell, RefCell}; use std::rc::Rc; -use crate::utils::clonecell::CloneCell; pub async fn handle_backend_events(state: Rc) { let mut beh = BackendEventHandler { state }; diff --git a/src/tree.rs b/src/tree.rs index 8648292c..30f0ee55 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -1,12 +1,12 @@ use crate::backend::{Output, OutputId}; use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevel; +use crate::utils::clonecell::CloneCell; use crate::utils::copyhashmap::CopyHashMap; use crate::utils::linkedlist::{LinkedList, Node as LinkedNode}; use ahash::AHashMap; use std::cell::{Cell, RefCell}; use std::mem; use std::rc::Rc; -use crate::utils::clonecell::CloneCell; linear_ids!(NodeIds, NodeId); diff --git a/src/utils/clonecell.rs b/src/utils/clonecell.rs index 74b2d404..4960265b 100644 --- a/src/utils/clonecell.rs +++ b/src/utils/clonecell.rs @@ -1,7 +1,7 @@ +use crate::utils::ptr_ext::{MutPtrExt, PtrExt}; use std::cell::UnsafeCell; use std::mem; use std::rc::Rc; -use crate::utils::ptr_ext::{MutPtrExt, PtrExt}; pub struct CloneCell { data: UnsafeCell, @@ -16,9 +16,7 @@ impl CloneCell { #[inline(always)] pub fn get(&self) -> T { - unsafe { - self.data.get().deref().clone() - } + unsafe { self.data.get().deref().clone() } } #[inline(always)] @@ -29,10 +27,11 @@ impl CloneCell { } #[inline(always)] - pub fn take(&self) -> T where T: Default { - unsafe { - mem::take(self.data.get().deref_mut()) - } + pub fn take(&self) -> T + where + T: Default, + { + unsafe { mem::take(self.data.get().deref_mut()) } } } @@ -42,8 +41,8 @@ impl Default for CloneCell { } } -pub unsafe trait UnsafeCellCloneSafe: Clone { } +pub unsafe trait UnsafeCellCloneSafe: Clone {} -unsafe impl UnsafeCellCloneSafe for Option { } +unsafe impl UnsafeCellCloneSafe for Option {} -unsafe impl UnsafeCellCloneSafe for Rc { } +unsafe impl UnsafeCellCloneSafe for Rc {} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 98f15a2e..3bc23e08 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,5 +1,6 @@ pub mod asyncevent; pub mod buffd; +pub mod clonecell; pub mod copyhashmap; pub mod errorfmt; pub mod linkedlist; @@ -8,4 +9,3 @@ pub mod oneshot; pub mod ptr_ext; pub mod queue; pub mod vec_ext; -pub mod clonecell; diff --git a/src/xkbcommon/consts.rs b/src/xkbcommon/consts.rs index 9b4d7b11..559b3bef 100644 --- a/src/xkbcommon/consts.rs +++ b/src/xkbcommon/consts.rs @@ -33,3 +33,26 @@ cenum! { XKB_KEYMAP_FORMAT_TEXT_V1 = 1, } + +cenum! { + XkbStateComponent, XKB_STATE_COMPONENT; + + XKB_STATE_MODS_DEPRESSED = 1 << 0, + XKB_STATE_MODS_LATCHED = 1 << 1, + XKB_STATE_MODS_LOCKED = 1 << 2, + XKB_STATE_MODS_EFFECTIVE = 1 << 3, + XKB_STATE_LAYOUT_DEPRESSED = 1 << 4, + XKB_STATE_LAYOUT_LATCHED = 1 << 5, + XKB_STATE_LAYOUT_LOCKED = 1 << 6, + XKB_STATE_LAYOUT_EFFECTIVE = 1 << 7, + XKB_STATE_LEDS = 1 << 8, +} + +bitor!(XkbStateComponent); + +cenum! { + XkbKeyDirection, XKB_KEY_DIRECTION; + + XKB_KEY_UP = 0, + XKB_KEY_DOWN = 1, +} diff --git a/src/xkbcommon/mod.rs b/src/xkbcommon/mod.rs index 8dcad0c5..04ae223b 100644 --- a/src/xkbcommon/mod.rs +++ b/src/xkbcommon/mod.rs @@ -18,6 +18,8 @@ use uapi::c; pub enum XkbCommonError { #[error("Could not create an xkbcommon context")] CreateContext, + #[error("Could not create an xkbcommon state")] + CreateState, #[error("Could not create keymap from names")] KeymapFromNames, #[error("Could not convert the keymap to a string")] @@ -73,6 +75,14 @@ extern "C" { ) -> *mut c::c_char; fn xkb_keymap_unref(keymap: *mut xkb_keymap); fn xkb_state_unref(state: *mut xkb_state); + fn xkb_state_new(keymap: *mut xkb_keymap) -> *mut xkb_state; + fn xkb_state_update_key( + state: *mut xkb_state, + key: u32, + direction: xkb_key_direction, + ) -> xkb_state_component; + fn xkb_state_serialize_mods(state: *mut xkb_state, components: xkb_state_component) -> u32; + fn xkb_state_serialize_layout(state: *mut xkb_state, components: xkb_state_component) -> u32; } pub struct XkbContext { @@ -126,6 +136,22 @@ impl XkbKeymap { s: unsafe { CStr::from_ptr(res).to_bytes().as_bstr() }, }) } + + pub fn state(&self) -> Result { + let res = unsafe { xkb_state_new(self.keymap) }; + if res.is_null() { + return Err(XkbCommonError::CreateState); + } + Ok(XkbState { + state: res, + mods: ModifierState { + mods_depressed: 0, + mods_latched: 0, + mods_locked: 0, + group: 0, + }, + }) + } } impl Drop for XkbKeymap { @@ -154,8 +180,42 @@ impl Drop for XkbKeymapStr { } } +#[derive(Copy, Clone, Debug)] +pub struct ModifierState { + pub mods_depressed: u32, + pub mods_latched: u32, + pub mods_locked: u32, + pub group: u32, +} + pub struct XkbState { state: *mut xkb_state, + mods: ModifierState, +} + +impl XkbState { + pub fn mods(&self) -> ModifierState { + self.mods + } + + pub fn update(&mut self, key: u32, direction: XkbKeyDirection) -> Option { + unsafe { + let changes = xkb_state_update_key(self.state, key + 8, direction.raw() as _); + if changes != 0 { + self.mods.mods_depressed = + xkb_state_serialize_mods(self.state, XKB_STATE_MODS_DEPRESSED.raw() as _); + self.mods.mods_latched = + xkb_state_serialize_mods(self.state, XKB_STATE_MODS_LATCHED.raw() as _); + self.mods.mods_locked = + xkb_state_serialize_mods(self.state, XKB_STATE_MODS_LOCKED.raw() as _); + self.mods.group = + xkb_state_serialize_layout(self.state, XKB_STATE_LAYOUT_EFFECTIVE.raw() as _); + Some(self.mods) + } else { + None + } + } + } } impl Drop for XkbState {