keyboard: replace xkbcommon by kbvm
This commit is contained in:
parent
51ceba72b0
commit
541a7b5ebc
23 changed files with 532 additions and 738 deletions
|
|
@ -4,6 +4,7 @@ use {
|
|||
client::{Client, ClientError},
|
||||
clientmem::{ClientMem, ClientMemError},
|
||||
ifs::wl_seat::WlSeatGlobal,
|
||||
kbvm::{KbvmError, KbvmMap},
|
||||
leaks::Tracker,
|
||||
libinput::consts::{
|
||||
AccelProfile, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
|
||||
|
|
@ -13,7 +14,6 @@ use {
|
|||
state::{DeviceHandlerData, InputDeviceData},
|
||||
utils::errorfmt::ErrorFmt,
|
||||
wire::{jay_input::*, JayInputId},
|
||||
xkbcommon::{XkbCommonError, XkbKeymap},
|
||||
},
|
||||
std::rc::Rc,
|
||||
thiserror::Error,
|
||||
|
|
@ -72,7 +72,7 @@ impl JayInput {
|
|||
});
|
||||
}
|
||||
|
||||
fn send_keymap(&self, map: &XkbKeymap) {
|
||||
fn send_keymap(&self, map: &KbvmMap) {
|
||||
self.client.event(Keymap {
|
||||
self_id: self.id,
|
||||
keymap: map.map.clone(),
|
||||
|
|
@ -167,7 +167,7 @@ impl JayInput {
|
|||
|
||||
fn set_keymap_impl<F>(&self, keymap: &Rc<OwnedFd>, len: u32, f: F) -> Result<(), JayInputError>
|
||||
where
|
||||
F: FnOnce(&Rc<XkbKeymap>) -> Result<(), JayInputError>,
|
||||
F: FnOnce(&Rc<KbvmMap>) -> Result<(), JayInputError>,
|
||||
{
|
||||
let cm = Rc::new(ClientMem::new_private(
|
||||
keymap,
|
||||
|
|
@ -180,7 +180,7 @@ impl JayInput {
|
|||
let mut map = vec![];
|
||||
cm.read(&mut map)?;
|
||||
self.or_error(|| {
|
||||
let map = self.client.state.xkb_ctx.keymap_from_str(&map)?;
|
||||
let map = self.client.state.kb_ctx.parse_keymap(&map)?;
|
||||
f(&map)?;
|
||||
Ok(())
|
||||
})
|
||||
|
|
@ -489,7 +489,7 @@ pub enum JayInputError {
|
|||
#[error("Could not access client memory")]
|
||||
ClientMemError(#[from] ClientMemError),
|
||||
#[error("Could not parse keymap")]
|
||||
XkbCommonError(#[from] XkbCommonError),
|
||||
ParseKeymap(#[from] KbvmError),
|
||||
#[error("Output is not connected")]
|
||||
OutputNotConnected,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,8 @@ use {
|
|||
},
|
||||
xdg_toplevel_drag_v1::XdgToplevelDragV1,
|
||||
},
|
||||
keyboard::{DynKeyboardState, KeyboardState},
|
||||
kbvm::{KbvmMap, KbvmMapId, KbvmState, PhysicalKeyboardState},
|
||||
keyboard::{DynKeyboardState, KeyboardState, KeyboardStateId},
|
||||
leaks::Tracker,
|
||||
object::{Object, Version},
|
||||
rect::Rect,
|
||||
|
|
@ -83,8 +84,8 @@ use {
|
|||
},
|
||||
utils::{
|
||||
asyncevent::AsyncEvent, bindings::PerClientBindings, clonecell::CloneCell,
|
||||
copyhashmap::CopyHashMap, errorfmt::ErrorFmt, linkedlist::LinkedNode, numcell::NumCell,
|
||||
rc_eq::rc_eq, smallmap::SmallMap,
|
||||
copyhashmap::CopyHashMap, linkedlist::LinkedNode, numcell::NumCell, rc_eq::rc_eq,
|
||||
smallmap::SmallMap,
|
||||
},
|
||||
wire::{
|
||||
wl_seat::*, ExtIdleNotificationV1Id, WlDataDeviceId, WlKeyboardId, WlPointerId,
|
||||
|
|
@ -92,7 +93,6 @@ use {
|
|||
ZwpTextInputV3Id,
|
||||
},
|
||||
wire_ei::EiSeatId,
|
||||
xkbcommon::{KeymapId, XkbKeymap, XkbState},
|
||||
},
|
||||
ahash::AHashMap,
|
||||
smallvec::SmallVec,
|
||||
|
|
@ -144,6 +144,13 @@ impl Drop for DroppedDnd {
|
|||
}
|
||||
}
|
||||
|
||||
linear_ids!(PhysicalKeyboardIds, PhysicalKeyboardId, u64);
|
||||
|
||||
pub struct PhysicalKeyboard {
|
||||
has_custom_map: Cell<bool>,
|
||||
pub phy_state: PhysicalKeyboardState,
|
||||
}
|
||||
|
||||
linear_ids!(SeatIds, SeatId);
|
||||
|
||||
pub struct WlSeatGlobal {
|
||||
|
|
@ -169,10 +176,12 @@ pub struct WlSeatGlobal {
|
|||
>,
|
||||
data_control_devices: CopyHashMap<DataControlDeviceId, Rc<dyn DynDataControlDevice>>,
|
||||
repeat_rate: Cell<(i32, i32)>,
|
||||
seat_kb_map: CloneCell<Rc<XkbKeymap>>,
|
||||
seat_xkb_state: CloneCell<Rc<RefCell<XkbState>>>,
|
||||
seat_kb_map: CloneCell<Rc<KbvmMap>>,
|
||||
seat_kb_state: CloneCell<Rc<RefCell<KbvmState>>>,
|
||||
latest_kb_state: CloneCell<Rc<dyn DynKeyboardState>>,
|
||||
xkb_states: CopyHashMap<KeymapId, Weak<RefCell<XkbState>>>,
|
||||
latest_kb_state_id: Cell<KeyboardStateId>,
|
||||
kb_states: CopyHashMap<KbvmMapId, Weak<RefCell<KbvmState>>>,
|
||||
kb_devices: CopyHashMap<PhysicalKeyboardId, Rc<PhysicalKeyboard>>,
|
||||
cursor_user_group: Rc<CursorUserGroup>,
|
||||
pointer_cursor: Rc<CursorUser>,
|
||||
tree_changed: Rc<AsyncEvent>,
|
||||
|
|
@ -214,13 +223,11 @@ const CHANGE_TREE: u32 = 1 << 1;
|
|||
|
||||
impl WlSeatGlobal {
|
||||
pub fn new(name: GlobalName, seat_name: &str, state: &Rc<State>) -> Rc<Self> {
|
||||
let seat_xkb_state = state
|
||||
.default_keymap
|
||||
.state(state.keyboard_state_ids.next())
|
||||
.map(|s| Rc::new(RefCell::new(s)))
|
||||
.unwrap();
|
||||
let xkb_states = CopyHashMap::new();
|
||||
xkb_states.set(state.default_keymap.id, Rc::downgrade(&seat_xkb_state));
|
||||
let seat_kb_state = state.default_keymap.state(state.keyboard_state_ids.next());
|
||||
let latest_kb_state_id = seat_kb_state.kb_state.id;
|
||||
let seat_kb_state = Rc::new(RefCell::new(seat_kb_state));
|
||||
let kb_states = CopyHashMap::new();
|
||||
kb_states.set(state.default_keymap.id, Rc::downgrade(&seat_kb_state));
|
||||
let cursor_user_group = CursorUserGroup::create(state);
|
||||
let cursor_user = cursor_user_group.create_user();
|
||||
cursor_user.activate();
|
||||
|
|
@ -243,9 +250,11 @@ impl WlSeatGlobal {
|
|||
primary_selection_devices: RefCell::new(Default::default()),
|
||||
repeat_rate: Cell::new((25, 250)),
|
||||
seat_kb_map: CloneCell::new(state.default_keymap.clone()),
|
||||
seat_xkb_state: CloneCell::new(seat_xkb_state.clone()),
|
||||
latest_kb_state: CloneCell::new(seat_xkb_state.clone()),
|
||||
xkb_states,
|
||||
seat_kb_state: CloneCell::new(seat_kb_state.clone()),
|
||||
latest_kb_state: CloneCell::new(seat_kb_state.clone()),
|
||||
latest_kb_state_id: Cell::new(latest_kb_state_id),
|
||||
kb_states,
|
||||
kb_devices: Default::default(),
|
||||
cursor_user_group,
|
||||
pointer_cursor: cursor_user,
|
||||
tree_changed: Default::default(),
|
||||
|
|
@ -318,7 +327,7 @@ impl WlSeatGlobal {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn keymap(&self) -> Rc<XkbKeymap> {
|
||||
pub fn keymap(&self) -> Rc<KbvmMap> {
|
||||
self.seat_kb_map.get()
|
||||
}
|
||||
|
||||
|
|
@ -496,53 +505,46 @@ impl WlSeatGlobal {
|
|||
false
|
||||
}
|
||||
|
||||
pub fn set_seat_keymap(&self, keymap: &Rc<XkbKeymap>) {
|
||||
let Some(xkb_state) = self.get_xkb_state(keymap) else {
|
||||
return;
|
||||
};
|
||||
pub fn set_seat_keymap(&self, keymap: &Rc<KbvmMap>) {
|
||||
self.seat_kb_map.set(keymap.clone());
|
||||
let old = self.seat_xkb_state.set(xkb_state.clone());
|
||||
if !rc_eq(&old, &xkb_state) {
|
||||
self.handle_xkb_state_change(&old.borrow(), &xkb_state.borrow());
|
||||
let new = self.get_kb_state(keymap);
|
||||
let old = self.seat_kb_state.set(new.clone());
|
||||
if rc_eq(&old, &new) {
|
||||
return;
|
||||
}
|
||||
self.kb_devices.lock().retain(|_, p| p.has_custom_map.get());
|
||||
self.handle_keyboard_state_change(&old.borrow().kb_state, &new.borrow().kb_state);
|
||||
}
|
||||
|
||||
fn handle_xkb_state_change(&self, old: &XkbState, new: &XkbState) {
|
||||
fn handle_keyboard_state_change(&self, old: &KeyboardState, new: &KeyboardState) {
|
||||
self.for_each_ei_seat(|ei_seat| {
|
||||
ei_seat.handle_xkb_state_change(old.kb_state.id, &new.kb_state);
|
||||
ei_seat.handle_keyboard_state_change(old.id, new);
|
||||
});
|
||||
let Some(surface) = self.keyboard_node.get().node_into_surface() else {
|
||||
return;
|
||||
};
|
||||
let serial = surface.client.next_serial();
|
||||
self.surface_kb_event(Version::ALL, &surface, |kb| {
|
||||
if kb.kb_state_id() == old.kb_state.id {
|
||||
if kb.kb_state_id() == old.id {
|
||||
kb.send_leave(serial, surface.id);
|
||||
kb.enter(serial, surface.id, &new.kb_state);
|
||||
kb.enter(serial, surface.id, new);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn get_xkb_state(&self, keymap: &Rc<XkbKeymap>) -> Option<Rc<RefCell<XkbState>>> {
|
||||
if let Some(weak) = self.xkb_states.get(&keymap.id) {
|
||||
pub fn get_kb_state(&self, keymap: &Rc<KbvmMap>) -> Rc<RefCell<KbvmState>> {
|
||||
if let Some(weak) = self.kb_states.get(&keymap.id) {
|
||||
if let Some(state) = weak.upgrade() {
|
||||
return Some(state);
|
||||
return state;
|
||||
}
|
||||
}
|
||||
self.xkb_states
|
||||
self.kb_states
|
||||
.lock()
|
||||
.retain(|_, state| state.strong_count() > 0);
|
||||
match keymap.state(self.state.keyboard_state_ids.next()) {
|
||||
Ok(s) => {
|
||||
let s = Rc::new(RefCell::new(s));
|
||||
self.xkb_states.set(keymap.id, Rc::downgrade(&s));
|
||||
Some(s)
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Could not create xkb state: {}", ErrorFmt(e));
|
||||
None
|
||||
}
|
||||
}
|
||||
let s = keymap.state(self.state.keyboard_state_ids.next());
|
||||
let s = Rc::new(RefCell::new(s));
|
||||
self.kb_states.set(keymap.id, Rc::downgrade(&s));
|
||||
s
|
||||
}
|
||||
|
||||
pub fn prepare_for_lock(self: &Rc<Self>) {
|
||||
|
|
@ -1031,16 +1033,17 @@ impl WlSeatGlobal {
|
|||
self.update_capabilities();
|
||||
}
|
||||
|
||||
pub fn remove_ei_seat(&self, ei: &EiSeat) {
|
||||
pub fn remove_ei_seat(self: &Rc<Self>, ei: &EiSeat) {
|
||||
self.ei_seats.remove(&(ei.client.id, ei.id));
|
||||
self.destroy_physical_keyboard(ei.keyboard_id);
|
||||
self.update_capabilities();
|
||||
}
|
||||
|
||||
pub fn seat_xkb_state(&self) -> Rc<dyn DynKeyboardState> {
|
||||
self.seat_xkb_state.get()
|
||||
pub fn seat_kb_state(&self) -> Rc<dyn DynKeyboardState> {
|
||||
self.seat_kb_state.get()
|
||||
}
|
||||
|
||||
pub fn latest_xkb_state(&self) -> Rc<dyn DynKeyboardState> {
|
||||
pub fn latest_kb_state(&self) -> Rc<dyn DynKeyboardState> {
|
||||
self.latest_kb_state.get()
|
||||
}
|
||||
|
||||
|
|
@ -1091,6 +1094,33 @@ impl WlSeatGlobal {
|
|||
}
|
||||
self.focus_node_with_serial(node, serial);
|
||||
}
|
||||
|
||||
pub fn get_physical_keyboard(
|
||||
&self,
|
||||
id: PhysicalKeyboardId,
|
||||
map: Option<&Rc<KbvmMap>>,
|
||||
) -> Rc<PhysicalKeyboard> {
|
||||
if let Some(d) = self.kb_devices.get(&id) {
|
||||
return d;
|
||||
}
|
||||
let state = match map {
|
||||
Some(m) => self.get_kb_state(m),
|
||||
_ => self.get_kb_state(&self.seat_kb_map.get()),
|
||||
};
|
||||
let d = Rc::new(PhysicalKeyboard {
|
||||
has_custom_map: Cell::new(map.is_some()),
|
||||
phy_state: PhysicalKeyboardState::new(&state),
|
||||
});
|
||||
self.kb_devices.set(id, d.clone());
|
||||
d
|
||||
}
|
||||
|
||||
pub fn destroy_physical_keyboard(self: &Rc<Self>, id: PhysicalKeyboardId) {
|
||||
let Some(kb) = self.kb_devices.remove(&id) else {
|
||||
return;
|
||||
};
|
||||
kb.phy_state.destroy(self.state.now_usec(), self);
|
||||
}
|
||||
}
|
||||
|
||||
impl CursorUserOwner for WlSeatGlobal {
|
||||
|
|
@ -1178,7 +1208,7 @@ impl WlSeatRequestHandler for WlSeat {
|
|||
p.enter(
|
||||
self.client.next_serial(),
|
||||
surface.id,
|
||||
&self.global.seat_xkb_state.get().borrow().kb_state,
|
||||
&self.global.seat_kb_state.get().borrow().kb_state,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1265,17 +1295,20 @@ pub fn collect_kb_foci(node: Rc<dyn Node>) -> SmallVec<[Rc<WlSeatGlobal>; 3]> {
|
|||
|
||||
impl DeviceHandlerData {
|
||||
pub fn set_seat(&self, seat: Option<Rc<WlSeatGlobal>>) {
|
||||
let old = self.seat.set(seat.clone());
|
||||
if let Some(old) = old {
|
||||
if let Some(new) = &seat {
|
||||
if let Some(new) = &seat {
|
||||
if let Some(old) = self.seat.get() {
|
||||
if old.id() == new.id() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
let xkb_state = self.get_effective_xkb_state(&old);
|
||||
let xkb_state = &mut *xkb_state.borrow_mut();
|
||||
xkb_state.reset();
|
||||
old.handle_xkb_state_change(xkb_state, xkb_state);
|
||||
} else {
|
||||
if self.seat.is_none() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
self.destroy_physical_keyboard_state();
|
||||
let old = self.seat.set(seat.clone());
|
||||
if let Some(old) = old {
|
||||
if let Some(info) = &self.tablet_init {
|
||||
old.tablet_remove_tablet(info.id);
|
||||
}
|
||||
|
|
@ -1287,7 +1320,6 @@ impl DeviceHandlerData {
|
|||
old.update_capabilities();
|
||||
}
|
||||
}
|
||||
self.update_xkb_state();
|
||||
if let Some(seat) = &seat {
|
||||
if let Some(info) = &self.tablet_init {
|
||||
seat.tablet_add_tablet(self.device.id(), info);
|
||||
|
|
@ -1302,34 +1334,15 @@ impl DeviceHandlerData {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn set_keymap(&self, keymap: Option<Rc<XkbKeymap>>) {
|
||||
self.keymap.set(keymap);
|
||||
self.update_xkb_state();
|
||||
}
|
||||
|
||||
fn get_effective_xkb_state(&self, seat: &WlSeatGlobal) -> Rc<RefCell<XkbState>> {
|
||||
match self.xkb_state.get() {
|
||||
Some(s) => s,
|
||||
_ => seat.seat_xkb_state.get(),
|
||||
}
|
||||
}
|
||||
|
||||
fn update_xkb_state(&self) {
|
||||
let Some(seat) = self.seat.get() else {
|
||||
self.xkb_state.take();
|
||||
return;
|
||||
fn destroy_physical_keyboard_state(&self) {
|
||||
if let Some(seat) = self.seat.get() {
|
||||
seat.destroy_physical_keyboard(self.keyboard_id);
|
||||
};
|
||||
let old = self.get_effective_xkb_state(&seat);
|
||||
self.xkb_state.take();
|
||||
if let Some(keymap) = self.keymap.get() {
|
||||
if let Some(state) = seat.get_xkb_state(&keymap) {
|
||||
self.xkb_state.set(Some(state));
|
||||
}
|
||||
}
|
||||
let new = self.get_effective_xkb_state(&seat);
|
||||
if !rc_eq(&old, &new) {
|
||||
seat.handle_xkb_state_change(&old.borrow(), &new.borrow());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_keymap(&self, keymap: Option<Rc<KbvmMap>>) {
|
||||
self.destroy_physical_keyboard_state();
|
||||
self.keymap.set(keymap);
|
||||
}
|
||||
|
||||
pub fn set_output(&self, output: Option<&WlOutputGlobal>) {
|
||||
|
|
|
|||
|
|
@ -33,16 +33,19 @@ use {
|
|||
},
|
||||
wl_surface::{xdg_surface::xdg_popup::XdgPopup, WlSurface},
|
||||
},
|
||||
kbvm::KbvmState,
|
||||
keyboard::KeyboardState,
|
||||
object::Version,
|
||||
rect::Rect,
|
||||
state::DeviceHandlerData,
|
||||
tree::{Direction, Node, ToplevelNode},
|
||||
utils::{bitflags::BitflagsExt, hash_map_ext::HashMapExt, smallmap::SmallMap},
|
||||
utils::{
|
||||
bitflags::BitflagsExt, hash_map_ext::HashMapExt, smallmap::SmallMap,
|
||||
syncqueue::SyncQueue,
|
||||
},
|
||||
wire::WlDataOfferId,
|
||||
xkbcommon::{XkbState, XKB_KEY_DOWN, XKB_KEY_UP},
|
||||
},
|
||||
isnt::std_1::primitive::{IsntSlice2Ext, IsntSliceExt},
|
||||
isnt::std_1::primitive::IsntSliceExt,
|
||||
jay_config::{
|
||||
input::SwitchEvent,
|
||||
keyboard::{
|
||||
|
|
@ -50,8 +53,9 @@ use {
|
|||
syms::{KeySym, SYM_Escape},
|
||||
},
|
||||
},
|
||||
kbvm::{state_machine::Event, ModifierMask},
|
||||
smallvec::SmallVec,
|
||||
std::{cell::RefCell, collections::hash_map::Entry, rc::Rc},
|
||||
std::{cell::RefCell, collections::hash_map::Entry, mem, rc::Rc},
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -320,7 +324,11 @@ impl WlSeatGlobal {
|
|||
time_usec,
|
||||
key,
|
||||
state,
|
||||
} => self.key_event(time_usec, key, state, || dev.get_effective_xkb_state(self)),
|
||||
} => {
|
||||
self.get_physical_keyboard(dev.keyboard_id, dev.keymap.get().as_ref())
|
||||
.phy_state
|
||||
.update(time_usec, self, key, state);
|
||||
}
|
||||
InputEvent::ConnectorPosition {
|
||||
time_usec,
|
||||
connector,
|
||||
|
|
@ -779,130 +787,129 @@ impl WlSeatGlobal {
|
|||
self.touch_owner.frame(self);
|
||||
}
|
||||
|
||||
pub fn key_event_with_seat_state(
|
||||
pub fn key_events(
|
||||
self: &Rc<Self>,
|
||||
time_usec: u64,
|
||||
key: u32,
|
||||
key_state: KeyState,
|
||||
events: &SyncQueue<Event>,
|
||||
kbvm_state_rc: &Rc<RefCell<KbvmState>>,
|
||||
) {
|
||||
self.key_event(time_usec, key, key_state, || self.seat_xkb_state.get());
|
||||
}
|
||||
|
||||
pub(super) fn key_event<F>(
|
||||
self: &Rc<Self>,
|
||||
time_usec: u64,
|
||||
key: u32,
|
||||
key_state: KeyState,
|
||||
mut get_state: F,
|
||||
) where
|
||||
F: FnMut() -> Rc<RefCell<XkbState>>,
|
||||
{
|
||||
let mut xkb_state_rc = get_state();
|
||||
let mut xkb_state = xkb_state_rc.borrow_mut();
|
||||
let (state, xkb_dir) = {
|
||||
match key_state {
|
||||
KeyState::Released => {
|
||||
if xkb_state.kb_state.pressed_keys.not_contains(&key) {
|
||||
return;
|
||||
}
|
||||
(wl_keyboard::RELEASED, XKB_KEY_UP)
|
||||
}
|
||||
KeyState::Pressed => {
|
||||
if xkb_state.kb_state.pressed_keys.contains(&key) {
|
||||
return;
|
||||
}
|
||||
(wl_keyboard::PRESSED, XKB_KEY_DOWN)
|
||||
}
|
||||
}
|
||||
};
|
||||
let mut kbvm_state = kbvm_state_rc.borrow_mut();
|
||||
self.latest_kb_state.set(kbvm_state_rc.clone());
|
||||
self.latest_kb_state_id.set(kbvm_state.kb_state.id);
|
||||
let mut shortcuts = SmallVec::<[_; 1]>::new();
|
||||
let new_mods;
|
||||
{
|
||||
let mut mods = xkb_state.mods().mods.0 & !(CAPS.0 | NUM.0);
|
||||
if state == wl_keyboard::RELEASED {
|
||||
mods |= RELEASE.0;
|
||||
}
|
||||
let scs = &*self.shortcuts.borrow();
|
||||
let keysyms = xkb_state.unmodified_keysyms(key);
|
||||
let mut revert_pointer_to_default = false;
|
||||
for &sym in keysyms {
|
||||
if sym == SYM_Escape.0 && mods == 0 {
|
||||
revert_pointer_to_default = true;
|
||||
let mut components_changed = false;
|
||||
while let Some(event) = events.pop() {
|
||||
components_changed |= kbvm_state.kb_state.mods.apply_event(event);
|
||||
let (key_state, kc) = match event {
|
||||
Event::KeyDown(kc) => (KeyState::Pressed, kc),
|
||||
Event::KeyUp(kc) => (KeyState::Released, kc),
|
||||
_ => continue,
|
||||
};
|
||||
let update_pressed_keys = |kbvm_state: &mut KbvmState| {
|
||||
let pk = &mut kbvm_state.kb_state.pressed_keys;
|
||||
match key_state {
|
||||
KeyState::Released => pk.remove(&kc.to_evdev()),
|
||||
KeyState::Pressed => pk.insert(kc.to_evdev()),
|
||||
}
|
||||
if !self.state.lock.locked.get() {
|
||||
if let Some(key_mods) = scs.get(&sym) {
|
||||
for (key_mods, mask) in key_mods {
|
||||
if mods & mask == key_mods {
|
||||
shortcuts.push(InvokedShortcut {
|
||||
unmasked_mods: Modifiers(mods),
|
||||
effective_mods: Modifiers(key_mods),
|
||||
sym: KeySym(sym),
|
||||
});
|
||||
};
|
||||
shortcuts.clear();
|
||||
{
|
||||
let mut mods = kbvm_state.kb_state.mods.mods.0 & !(CAPS.0 | NUM.0);
|
||||
if key_state == KeyState::Released {
|
||||
mods |= RELEASE.0;
|
||||
}
|
||||
let scs = &*self.shortcuts.borrow();
|
||||
let keysyms = kbvm_state.map.lookup_table.lookup(
|
||||
kbvm_state.kb_state.mods.group,
|
||||
ModifierMask::default(),
|
||||
kc,
|
||||
);
|
||||
let mut revert_pointer_to_default = false;
|
||||
for props in keysyms {
|
||||
let sym = props.keysym().0;
|
||||
if sym == SYM_Escape.0 && mods == 0 {
|
||||
revert_pointer_to_default = true;
|
||||
}
|
||||
if !self.state.lock.locked.get() {
|
||||
if let Some(key_mods) = scs.get(&sym) {
|
||||
for (key_mods, mask) in key_mods {
|
||||
if mods & mask == key_mods {
|
||||
shortcuts.push(InvokedShortcut {
|
||||
unmasked_mods: Modifiers(mods),
|
||||
effective_mods: Modifiers(key_mods),
|
||||
sym: KeySym(sym),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if revert_pointer_to_default {
|
||||
drop(xkb_state);
|
||||
self.pointer_owner.revert_to_default(self);
|
||||
xkb_state = xkb_state_rc.borrow_mut();
|
||||
}
|
||||
new_mods = xkb_state.update(key, xkb_dir);
|
||||
}
|
||||
self.state.for_each_seat_tester(|t| {
|
||||
t.send_key(self.id, time_usec, key, key_state);
|
||||
});
|
||||
let node = self.keyboard_node.get();
|
||||
let input_method_grab = self.input_method_grab.get();
|
||||
let mut forward = true;
|
||||
if shortcuts.is_not_empty() {
|
||||
self.forward.set(state == wl_keyboard::RELEASED);
|
||||
if let Some(config) = self.state.config.get() {
|
||||
let id = xkb_state.kb_state.id;
|
||||
drop(xkb_state);
|
||||
for shortcut in shortcuts {
|
||||
config.invoke_shortcut(self.id(), &shortcut);
|
||||
}
|
||||
xkb_state_rc = get_state();
|
||||
xkb_state = xkb_state_rc.borrow_mut();
|
||||
if id != xkb_state.kb_state.id {
|
||||
return;
|
||||
if revert_pointer_to_default {
|
||||
drop(kbvm_state);
|
||||
self.pointer_owner.revert_to_default(self);
|
||||
kbvm_state = kbvm_state_rc.borrow_mut();
|
||||
}
|
||||
}
|
||||
forward = self.forward.get();
|
||||
}
|
||||
if forward {
|
||||
match &input_method_grab {
|
||||
Some(g) => g.on_key(time_usec, key, state, &xkb_state.kb_state),
|
||||
_ => node.node_on_key(self, time_usec, key, state, &xkb_state.kb_state),
|
||||
}
|
||||
self.for_each_ei_seat(|ei_seat| {
|
||||
ei_seat.handle_key(time_usec, key, state, &xkb_state.kb_state);
|
||||
});
|
||||
}
|
||||
if new_mods {
|
||||
self.for_each_ei_seat(|ei_seat| {
|
||||
ei_seat.handle_modifiers_changed(&xkb_state.kb_state);
|
||||
});
|
||||
self.state.for_each_seat_tester(|t| {
|
||||
t.send_modifiers(self.id, &xkb_state.kb_state.mods);
|
||||
t.send_key(self.id, time_usec, kc.to_evdev(), key_state);
|
||||
});
|
||||
match &input_method_grab {
|
||||
Some(g) => g.on_modifiers(&xkb_state.kb_state),
|
||||
_ => node.node_on_mods(self, &xkb_state.kb_state),
|
||||
if shortcuts.is_not_empty() {
|
||||
self.forward.set(key_state == KeyState::Released);
|
||||
if let Some(config) = self.state.config.get() {
|
||||
drop(kbvm_state);
|
||||
for shortcut in &shortcuts {
|
||||
config.invoke_shortcut(self.id(), shortcut);
|
||||
}
|
||||
kbvm_state = kbvm_state_rc.borrow_mut();
|
||||
if kbvm_state.kb_state.id != self.latest_kb_state_id.get() {
|
||||
update_pressed_keys(&mut kbvm_state);
|
||||
kbvm_state.apply_events(events);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if !self.forward.get() {
|
||||
update_pressed_keys(&mut kbvm_state);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
self.send_components(&mut components_changed, &kbvm_state);
|
||||
let state = match key_state {
|
||||
KeyState::Released => wl_keyboard::RELEASED,
|
||||
KeyState::Pressed => wl_keyboard::PRESSED,
|
||||
};
|
||||
match self.input_method_grab.get() {
|
||||
Some(g) => g.on_key(time_usec, kc.to_evdev(), state, &kbvm_state.kb_state),
|
||||
_ => self.keyboard_node.get().node_on_key(
|
||||
self,
|
||||
time_usec,
|
||||
kc.to_evdev(),
|
||||
state,
|
||||
&kbvm_state.kb_state,
|
||||
),
|
||||
}
|
||||
self.for_each_ei_seat(|ei_seat| {
|
||||
ei_seat.handle_key(time_usec, kc.to_evdev(), state, &kbvm_state.kb_state);
|
||||
});
|
||||
update_pressed_keys(&mut kbvm_state);
|
||||
}
|
||||
match key_state {
|
||||
KeyState::Released => {
|
||||
xkb_state.kb_state.pressed_keys.remove(&key);
|
||||
}
|
||||
KeyState::Pressed => {
|
||||
xkb_state.kb_state.pressed_keys.insert(key);
|
||||
}
|
||||
self.send_components(&mut components_changed, &kbvm_state);
|
||||
}
|
||||
|
||||
fn send_components(&self, components_changed: &mut bool, kbvm_state: &KbvmState) {
|
||||
if !mem::take(components_changed) {
|
||||
return;
|
||||
}
|
||||
let kb_state = &kbvm_state.kb_state;
|
||||
self.for_each_ei_seat(|ei_seat| {
|
||||
ei_seat.handle_modifiers_changed(kb_state);
|
||||
});
|
||||
self.state.for_each_seat_tester(|t| {
|
||||
t.send_modifiers(self.id, &kb_state.mods);
|
||||
});
|
||||
match self.input_method_grab.get() {
|
||||
Some(g) => g.on_modifiers(kb_state),
|
||||
_ => self.keyboard_node.get().node_on_mods(self, kb_state),
|
||||
}
|
||||
drop(xkb_state);
|
||||
self.latest_kb_state.set(xkb_state_rc);
|
||||
}
|
||||
|
||||
pub(super) fn for_each_ei_seat(&self, mut f: impl FnMut(&Rc<EiSeat>)) {
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@ use {
|
|||
crate::{
|
||||
client::ClientError,
|
||||
ifs::wl_seat::WlSeat,
|
||||
keyboard::{KeyboardState, KeyboardStateId},
|
||||
keyboard::{KeyboardError, KeyboardState, KeyboardStateId},
|
||||
leaks::Tracker,
|
||||
object::{Object, Version},
|
||||
utils::errorfmt::ErrorFmt,
|
||||
wire::{wl_keyboard::*, WlKeyboardId, WlSurfaceId},
|
||||
xkbcommon::XkbCommonError,
|
||||
},
|
||||
kbvm::Components,
|
||||
std::{cell::Cell, rc::Rc},
|
||||
|
|
@ -183,6 +182,6 @@ pub enum WlKeyboardError {
|
|||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
#[error(transparent)]
|
||||
XkbCommonError(#[from] XkbCommonError),
|
||||
KeyboardError(#[from] KeyboardError),
|
||||
}
|
||||
efrom!(WlKeyboardError, ClientError);
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ use {
|
|||
},
|
||||
wl_surface::WlSurface,
|
||||
},
|
||||
kbvm::KbvmError,
|
||||
keyboard::KeyboardState,
|
||||
leaks::Tracker,
|
||||
object::{Object, Version},
|
||||
wire::{zwp_virtual_keyboard_v1::*, ZwpVirtualKeyboardV1Id},
|
||||
xkbcommon::XkbCommonError,
|
||||
},
|
||||
std::{cell::RefCell, rc::Rc},
|
||||
thiserror::Error,
|
||||
|
|
@ -74,8 +74,8 @@ impl ZwpVirtualKeyboardV1RequestHandler for ZwpVirtualKeyboardV1 {
|
|||
let map = self
|
||||
.client
|
||||
.state
|
||||
.xkb_ctx
|
||||
.keymap_from_str(&map)
|
||||
.kb_ctx
|
||||
.parse_keymap(&map)
|
||||
.map_err(ZwpVirtualKeyboardV1Error::ParseKeymap)?;
|
||||
*self.kb_state.borrow_mut() = KeyboardState {
|
||||
id: self.client.state.keyboard_state_ids.next(),
|
||||
|
|
@ -103,6 +103,7 @@ impl ZwpVirtualKeyboardV1RequestHandler for ZwpVirtualKeyboardV1 {
|
|||
wl_keyboard::RELEASED => kb_state.pressed_keys.remove(&req.key),
|
||||
_ => kb_state.pressed_keys.insert(req.key),
|
||||
};
|
||||
self.seat.latest_kb_state_id.set(kb_state.id);
|
||||
self.seat.latest_kb_state.set(self.kb_state.clone());
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -118,6 +119,7 @@ impl ZwpVirtualKeyboardV1RequestHandler for ZwpVirtualKeyboardV1 {
|
|||
self.for_each_kb(|serial, surface, kb| {
|
||||
kb.on_mods_changed(serial, surface.id, &kb_state);
|
||||
});
|
||||
self.seat.latest_kb_state_id.set(kb_state.id);
|
||||
self.seat.latest_kb_state.set(self.kb_state.clone());
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -154,6 +156,6 @@ pub enum ZwpVirtualKeyboardV1Error {
|
|||
#[error("Could not read the keymap")]
|
||||
ReadKeymap(#[source] ClientMemError),
|
||||
#[error("Could not parse the keymap")]
|
||||
ParseKeymap(#[source] XkbCommonError),
|
||||
ParseKeymap(#[source] KbvmError),
|
||||
}
|
||||
efrom!(ZwpVirtualKeyboardV1Error, ClientError);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue