metal: enable keyboard LEDs
This commit is contained in:
parent
0e51b9469b
commit
11c10fde70
14 changed files with 188 additions and 22 deletions
|
|
@ -259,6 +259,10 @@ pub trait InputDevice {
|
||||||
fn tablet_pad_info(&self) -> Option<Box<TabletPadInit>> {
|
fn tablet_pad_info(&self) -> Option<Box<TabletPadInit>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_enabled_leds(&self, leds: Leds) {
|
||||||
|
let _ = leds;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
|
||||||
|
|
@ -328,6 +332,15 @@ pub enum AxisSource {
|
||||||
|
|
||||||
pub const AXIS_120: i32 = 120;
|
pub const AXIS_120: i32 = 120;
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
Leds: u32;
|
||||||
|
LED_NUM_LOCK = 1 << 0,
|
||||||
|
LED_CAPS_LOCK = 1 << 1,
|
||||||
|
LED_SCROLL_LOCK = 1 << 2,
|
||||||
|
LED_COMPOSE = 1 << 3,
|
||||||
|
LED_KANA = 1 << 4,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum InputEvent {
|
pub enum InputEvent {
|
||||||
Key {
|
Key {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use {
|
||||||
async_engine::SpawnedFuture,
|
async_engine::SpawnedFuture,
|
||||||
backend::{
|
backend::{
|
||||||
Backend, InputDevice, InputDeviceAccelProfile, InputDeviceCapability,
|
Backend, InputDevice, InputDeviceAccelProfile, InputDeviceCapability,
|
||||||
InputDeviceClickMethod, InputDeviceGroupId, InputDeviceId, InputEvent, KeyState,
|
InputDeviceClickMethod, InputDeviceGroupId, InputDeviceId, InputEvent, KeyState, Leds,
|
||||||
TransformMatrix, transaction::BackendConnectorTransactionError,
|
TransformMatrix, transaction::BackendConnectorTransactionError,
|
||||||
},
|
},
|
||||||
backends::metal::video::{
|
backends::metal::video::{
|
||||||
|
|
@ -31,7 +31,7 @@ use {
|
||||||
AccelProfile, ConfigClickMethod, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
|
AccelProfile, ConfigClickMethod, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
|
||||||
LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT, LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS,
|
LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT, LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS,
|
||||||
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER, LIBINPUT_CONFIG_CLICK_METHOD_NONE,
|
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER, LIBINPUT_CONFIG_CLICK_METHOD_NONE,
|
||||||
LIBINPUT_DEVICE_CAP_TABLET_PAD, LIBINPUT_DEVICE_CAP_TABLET_TOOL,
|
LIBINPUT_DEVICE_CAP_TABLET_PAD, LIBINPUT_DEVICE_CAP_TABLET_TOOL, Led,
|
||||||
},
|
},
|
||||||
device::{LibInputDevice, RegisteredDevice},
|
device::{LibInputDevice, RegisteredDevice},
|
||||||
},
|
},
|
||||||
|
|
@ -373,6 +373,7 @@ struct InputDeviceProperties {
|
||||||
calibration_matrix: Cell<Option<[[f32; 3]; 2]>>,
|
calibration_matrix: Cell<Option<[[f32; 3]; 2]>>,
|
||||||
click_method: Cell<Option<ConfigClickMethod>>,
|
click_method: Cell<Option<ConfigClickMethod>>,
|
||||||
middle_button_emulation_enabled: Cell<Option<bool>>,
|
middle_button_emulation_enabled: Cell<Option<bool>>,
|
||||||
|
enabled_leds: Cell<Option<Led>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
@ -442,6 +443,9 @@ impl MetalInputDevice {
|
||||||
if let Some(enabled) = self.desired.middle_button_emulation_enabled.get() {
|
if let Some(enabled) = self.desired.middle_button_emulation_enabled.get() {
|
||||||
self.set_middle_button_emulation_enabled(enabled);
|
self.set_middle_button_emulation_enabled(enabled);
|
||||||
}
|
}
|
||||||
|
if let Some(led) = self.desired.enabled_leds.get() {
|
||||||
|
self.set_enabled_leds_(led);
|
||||||
|
}
|
||||||
self.fetch_effective();
|
self.fetch_effective();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -527,6 +531,14 @@ impl MetalInputDevice {
|
||||||
.set(Some(dev.device().click_method()));
|
.set(Some(dev.device().click_method()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_enabled_leds_(&self, led: Led) {
|
||||||
|
self.desired.enabled_leds.set(Some(led));
|
||||||
|
if let Some(dev) = self.inputdev.get() {
|
||||||
|
dev.device().led_update(led);
|
||||||
|
self.effective.enabled_leds.set(Some(led));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InputDevice for MetalInputDevice {
|
impl InputDevice for MetalInputDevice {
|
||||||
|
|
@ -810,6 +822,11 @@ impl InputDevice for MetalInputDevice {
|
||||||
groups,
|
groups,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_enabled_leds(&self, leds: Leds) {
|
||||||
|
let led = Led(leds.0 as _);
|
||||||
|
self.set_enabled_leds_(led);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MetalInputDevice {
|
impl MetalInputDevice {
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ pub mod zwp_virtual_keyboard_v1;
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
async_engine::SpawnedFuture,
|
async_engine::SpawnedFuture,
|
||||||
backend::KeyState,
|
backend::{KeyState, LED_CAPS_LOCK, LED_NUM_LOCK, Leds},
|
||||||
client::{Client, ClientError, ClientId},
|
client::{Client, ClientError, ClientId},
|
||||||
cursor_user::{CursorUser, CursorUserGroup, CursorUserOwner},
|
cursor_user::{CursorUser, CursorUserGroup, CursorUserOwner},
|
||||||
ei::ei_ifs::ei_seat::EiSeat,
|
ei::ei_ifs::ei_seat::EiSeat,
|
||||||
|
|
@ -75,7 +75,7 @@ use {
|
||||||
xdg_toplevel_drag_v1::XdgToplevelDragV1,
|
xdg_toplevel_drag_v1::XdgToplevelDragV1,
|
||||||
},
|
},
|
||||||
kbvm::{KbvmMap, KbvmMapId, KbvmState, PhysicalKeyboardState},
|
kbvm::{KbvmMap, KbvmMapId, KbvmState, PhysicalKeyboardState},
|
||||||
keyboard::{DynKeyboardState, KeyboardState, KeyboardStateId, KeymapFd},
|
keyboard::{DynKeyboardState, KeyboardState, KeyboardStateId, KeymapFd, ModifiersListener},
|
||||||
leaks::Tracker,
|
leaks::Tracker,
|
||||||
object::{Object, Version},
|
object::{Object, Version},
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
|
|
@ -91,6 +91,7 @@ use {
|
||||||
bindings::PerClientBindings,
|
bindings::PerClientBindings,
|
||||||
clonecell::CloneCell,
|
clonecell::CloneCell,
|
||||||
copyhashmap::CopyHashMap,
|
copyhashmap::CopyHashMap,
|
||||||
|
event_listener::{EventListener, EventSource},
|
||||||
linkedlist::{LinkedList, LinkedNode, NodeRef},
|
linkedlist::{LinkedList, LinkedNode, NodeRef},
|
||||||
numcell::NumCell,
|
numcell::NumCell,
|
||||||
on_drop::OnDrop,
|
on_drop::OnDrop,
|
||||||
|
|
@ -106,7 +107,7 @@ use {
|
||||||
},
|
},
|
||||||
ahash::AHashMap,
|
ahash::AHashMap,
|
||||||
jay_config::keyboard::syms::{KeySym, SYM_Escape},
|
jay_config::keyboard::syms::{KeySym, SYM_Escape},
|
||||||
kbvm::Keycode,
|
kbvm::{Components, Keycode, ModifierMask},
|
||||||
smallvec::SmallVec,
|
smallvec::SmallVec,
|
||||||
std::{
|
std::{
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
|
|
@ -235,6 +236,8 @@ pub struct WlSeatGlobal {
|
||||||
focus_history_same_workspace: Cell<bool>,
|
focus_history_same_workspace: Cell<bool>,
|
||||||
mark_mode: Cell<Option<MarkMode>>,
|
mark_mode: Cell<Option<MarkMode>>,
|
||||||
marks: CopyHashMap<Keycode, Rc<dyn Node>>,
|
marks: CopyHashMap<Keycode, Rc<dyn Node>>,
|
||||||
|
modifiers_listener: EventListener<dyn ModifiersListener>,
|
||||||
|
modifiers_forward: EventSource<dyn ModifiersListener>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
|
@ -256,7 +259,7 @@ impl WlSeatGlobal {
|
||||||
let cursor_user_group = CursorUserGroup::create(state);
|
let cursor_user_group = CursorUserGroup::create(state);
|
||||||
let cursor_user = cursor_user_group.create_user();
|
let cursor_user = cursor_user_group.create_user();
|
||||||
cursor_user.activate();
|
cursor_user.activate();
|
||||||
let slf = Rc::new(Self {
|
let slf = Rc::new_cyclic(|slf: &Weak<WlSeatGlobal>| Self {
|
||||||
id: state.seat_ids.next(),
|
id: state.seat_ids.next(),
|
||||||
name,
|
name,
|
||||||
state: state.clone(),
|
state: state.clone(),
|
||||||
|
|
@ -322,8 +325,12 @@ impl WlSeatGlobal {
|
||||||
focus_history_same_workspace: Cell::new(false),
|
focus_history_same_workspace: Cell::new(false),
|
||||||
mark_mode: Default::default(),
|
mark_mode: Default::default(),
|
||||||
marks: Default::default(),
|
marks: Default::default(),
|
||||||
|
modifiers_listener: EventListener::new(slf.clone()),
|
||||||
|
modifiers_forward: Default::default(),
|
||||||
});
|
});
|
||||||
slf.pointer_cursor.set_owner(slf.clone());
|
slf.pointer_cursor.set_owner(slf.clone());
|
||||||
|
slf.modifiers_listener
|
||||||
|
.attach(&seat_kb_state.borrow().kb_state.mods_changed);
|
||||||
let seat = slf.clone();
|
let seat = slf.clone();
|
||||||
let future = state.eng.spawn("seat handler", async move {
|
let future = state.eng.spawn("seat handler", async move {
|
||||||
loop {
|
loop {
|
||||||
|
|
@ -524,6 +531,11 @@ impl WlSeatGlobal {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.kb_devices.lock().retain(|_, p| p.has_custom_map.get());
|
self.kb_devices.lock().retain(|_, p| p.has_custom_map.get());
|
||||||
|
{
|
||||||
|
let new = &*new.borrow();
|
||||||
|
self.modifiers_listener.attach(&new.kb_state.mods_changed);
|
||||||
|
self.dispatch_seat_modifiers_listeners(&new.kb_state.mods);
|
||||||
|
}
|
||||||
self.handle_keyboard_state_change(&old.borrow().kb_state, &new.borrow().kb_state);
|
self.handle_keyboard_state_change(&old.borrow().kb_state, &new.borrow().kb_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -558,6 +570,35 @@ impl WlSeatGlobal {
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn attach_modifiers_listener(
|
||||||
|
&self,
|
||||||
|
id: PhysicalKeyboardId,
|
||||||
|
listener: &EventListener<dyn ModifiersListener>,
|
||||||
|
map: Option<&Rc<KbvmMap>>,
|
||||||
|
) {
|
||||||
|
let _ = self.get_physical_keyboard(id, map);
|
||||||
|
let state = match map {
|
||||||
|
None => {
|
||||||
|
listener.attach(&self.modifiers_forward);
|
||||||
|
self.seat_kb_state.get()
|
||||||
|
}
|
||||||
|
Some(m) => {
|
||||||
|
let state = self.get_kb_state(m);
|
||||||
|
listener.attach(&state.borrow().kb_state.mods_changed);
|
||||||
|
state
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if let Some(l) = listener.get() {
|
||||||
|
l.locked_mods(&state.borrow().kb_state.mods);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dispatch_seat_modifiers_listeners(&self, mods: &Components) {
|
||||||
|
for listener in self.modifiers_forward.iter() {
|
||||||
|
listener.locked_mods(mods);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn prepare_for_lock(self: &Rc<Self>) {
|
pub fn prepare_for_lock(self: &Rc<Self>) {
|
||||||
self.pointer_owner.revert_to_default(self);
|
self.pointer_owner.revert_to_default(self);
|
||||||
self.kb_owner.ungrab(self);
|
self.kb_owner.ungrab(self);
|
||||||
|
|
@ -1639,17 +1680,32 @@ impl DeviceHandlerData {
|
||||||
seat.update_capabilities();
|
seat.update_capabilities();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.attach_event_listeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn destroy_physical_keyboard_state(&self) {
|
fn destroy_physical_keyboard_state(&self) {
|
||||||
|
self.mods_listener.detach();
|
||||||
if let Some(seat) = self.seat.get() {
|
if let Some(seat) = self.seat.get() {
|
||||||
seat.destroy_physical_keyboard(self.keyboard_id);
|
seat.destroy_physical_keyboard(self.keyboard_id);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn attach_event_listeners(&self) {
|
||||||
|
if self.is_kb
|
||||||
|
&& let Some(seat) = self.seat.get()
|
||||||
|
{
|
||||||
|
seat.attach_modifiers_listener(
|
||||||
|
self.keyboard_id,
|
||||||
|
&self.mods_listener,
|
||||||
|
self.keymap.get().as_ref(),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_keymap(&self, keymap: Option<Rc<KbvmMap>>) {
|
pub fn set_keymap(&self, keymap: Option<Rc<KbvmMap>>) {
|
||||||
self.destroy_physical_keyboard_state();
|
self.destroy_physical_keyboard_state();
|
||||||
self.keymap.set(keymap);
|
self.keymap.set(keymap);
|
||||||
|
self.attach_event_listeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_output(&self, output: Option<&WlOutputGlobal>) {
|
pub fn set_output(&self, output: Option<&WlOutputGlobal>) {
|
||||||
|
|
@ -1675,6 +1731,25 @@ impl DeviceHandlerData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ModifiersListener for DeviceHandlerData {
|
||||||
|
fn locked_mods(&self, mods: &Components) {
|
||||||
|
let mut leds = Leds::none();
|
||||||
|
if mods.mods_locked.contains(ModifierMask::NUM_LOCK) {
|
||||||
|
leds |= LED_NUM_LOCK;
|
||||||
|
}
|
||||||
|
if mods.mods_locked.contains(ModifierMask::LOCK) {
|
||||||
|
leds |= LED_CAPS_LOCK;
|
||||||
|
}
|
||||||
|
self.device.set_enabled_leds(leds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ModifiersListener for WlSeatGlobal {
|
||||||
|
fn locked_mods(&self, mods: &Components) {
|
||||||
|
self.dispatch_seat_modifiers_listeners(mods);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct PositionHintRequest {
|
pub struct PositionHintRequest {
|
||||||
seat: Rc<WlSeatGlobal>,
|
seat: Rc<WlSeatGlobal>,
|
||||||
node: NodeId,
|
node: NodeId,
|
||||||
|
|
|
||||||
|
|
@ -890,7 +890,7 @@ impl WlSeatGlobal {
|
||||||
let mut shortcuts = SmallVec::<[_; 1]>::new();
|
let mut shortcuts = SmallVec::<[_; 1]>::new();
|
||||||
let mut components_changed = false;
|
let mut components_changed = false;
|
||||||
while let Some(event) = events.pop() {
|
while let Some(event) = events.pop() {
|
||||||
components_changed |= kbvm_state.kb_state.mods.apply_event(event);
|
components_changed |= kbvm_state.kb_state.apply_event(event);
|
||||||
let (key_state, kc) = match event {
|
let (key_state, kc) = match event {
|
||||||
Event::KeyDown(kc) => (KeyState::Pressed, kc),
|
Event::KeyDown(kc) => (KeyState::Pressed, kc),
|
||||||
Event::KeyUp(kc) => (KeyState::Released, kc),
|
Event::KeyUp(kc) => (KeyState::Released, kc),
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,7 @@ impl ZwpVirtualKeyboardManagerV1RequestHandler for ZwpVirtualKeyboardManagerV1 {
|
||||||
xwayland_map: seat_keymap.xwayland_map.clone(),
|
xwayland_map: seat_keymap.xwayland_map.clone(),
|
||||||
pressed_keys: Default::default(),
|
pressed_keys: Default::default(),
|
||||||
mods: Default::default(),
|
mods: Default::default(),
|
||||||
|
mods_changed: Default::default(),
|
||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
track!(self.client, kb);
|
track!(self.client, kb);
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,7 @@ impl ZwpVirtualKeyboardV1RequestHandler for ZwpVirtualKeyboardV1 {
|
||||||
xwayland_map: map.xwayland_map.clone(),
|
xwayland_map: map.xwayland_map.clone(),
|
||||||
pressed_keys: Default::default(),
|
pressed_keys: Default::default(),
|
||||||
mods: Default::default(),
|
mods: Default::default(),
|
||||||
|
mods_changed: Default::default(),
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -112,11 +113,15 @@ impl ZwpVirtualKeyboardV1RequestHandler for ZwpVirtualKeyboardV1 {
|
||||||
|
|
||||||
fn modifiers(&self, req: Modifiers, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
fn modifiers(&self, req: Modifiers, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||||
let kb_state = &mut *self.kb_state.borrow_mut();
|
let kb_state = &mut *self.kb_state.borrow_mut();
|
||||||
|
let locked_mods = kb_state.mods.mods_locked;
|
||||||
kb_state.mods.mods_pressed.0 = req.mods_depressed;
|
kb_state.mods.mods_pressed.0 = req.mods_depressed;
|
||||||
kb_state.mods.mods_latched.0 = req.mods_latched;
|
kb_state.mods.mods_latched.0 = req.mods_latched;
|
||||||
kb_state.mods.mods_locked.0 = req.mods_locked;
|
kb_state.mods.mods_locked.0 = req.mods_locked;
|
||||||
kb_state.mods.group_locked.0 = req.group;
|
kb_state.mods.group_locked.0 = req.group;
|
||||||
kb_state.mods.update_effective();
|
kb_state.mods.update_effective();
|
||||||
|
if locked_mods != kb_state.mods.mods_locked {
|
||||||
|
kb_state.dispatch_locked_mods_listeners();
|
||||||
|
}
|
||||||
self.for_each_kb(|serial, surface, kb| {
|
self.for_each_kb(|serial, surface, kb| {
|
||||||
kb.on_mods_changed(serial, surface.id, &kb_state);
|
kb.on_mods_changed(serial, surface.id, &kb_state);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,7 @@ impl KbvmMap {
|
||||||
xwayland_map: self.xwayland_map.clone(),
|
xwayland_map: self.xwayland_map.clone(),
|
||||||
pressed_keys: Default::default(),
|
pressed_keys: Default::default(),
|
||||||
mods: Default::default(),
|
mods: Default::default(),
|
||||||
|
mods_changed: Default::default(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -139,7 +140,7 @@ impl KbvmState {
|
||||||
pub fn apply_events(&mut self, events: &SyncQueue<Event>) {
|
pub fn apply_events(&mut self, events: &SyncQueue<Event>) {
|
||||||
let state = &mut self.kb_state;
|
let state = &mut self.kb_state;
|
||||||
while let Some(event) = events.pop() {
|
while let Some(event) = events.pop() {
|
||||||
state.mods.apply_event(event);
|
state.apply_event(event);
|
||||||
match event {
|
match event {
|
||||||
Event::KeyDown(kc) => {
|
Event::KeyDown(kc) => {
|
||||||
state.pressed_keys.insert(kc.to_evdev());
|
state.pressed_keys.insert(kc.to_evdev());
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use {
|
use {
|
||||||
crate::utils::{oserror::OsError, vecset::VecSet},
|
crate::utils::{event_listener::EventSource, oserror::OsError, vecset::VecSet},
|
||||||
kbvm::Components,
|
kbvm::{Components, state_machine::Event},
|
||||||
std::{
|
std::{
|
||||||
cell::{Ref, RefCell},
|
cell::{Ref, RefCell},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
|
|
@ -25,6 +25,11 @@ pub struct KeyboardState {
|
||||||
pub xwayland_map: KeymapFd,
|
pub xwayland_map: KeymapFd,
|
||||||
pub pressed_keys: VecSet<u32>,
|
pub pressed_keys: VecSet<u32>,
|
||||||
pub mods: Components,
|
pub mods: Components,
|
||||||
|
pub mods_changed: EventSource<dyn ModifiersListener>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ModifiersListener {
|
||||||
|
fn locked_mods(&self, mods: &Components);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DynKeyboardState {
|
pub trait DynKeyboardState {
|
||||||
|
|
@ -37,6 +42,23 @@ impl DynKeyboardState for RefCell<KeyboardState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl KeyboardState {
|
||||||
|
pub fn apply_event(&mut self, event: Event) -> bool {
|
||||||
|
let locked_mods = self.mods.mods_locked;
|
||||||
|
let changed = self.mods.apply_event(event);
|
||||||
|
if locked_mods != self.mods.mods_locked {
|
||||||
|
self.dispatch_locked_mods_listeners();
|
||||||
|
}
|
||||||
|
changed
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dispatch_locked_mods_listeners(&self) {
|
||||||
|
for listener in self.mods_changed.iter() {
|
||||||
|
listener.locked_mods(&self.mods);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct KeymapFd {
|
pub struct KeymapFd {
|
||||||
pub map: Rc<OwnedFd>,
|
pub map: Rc<OwnedFd>,
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@ cenum! {
|
||||||
LIBINPUT_LED_NUM_LOCK = 1 << 0,
|
LIBINPUT_LED_NUM_LOCK = 1 << 0,
|
||||||
LIBINPUT_LED_CAPS_LOCK = 1 << 1,
|
LIBINPUT_LED_CAPS_LOCK = 1 << 1,
|
||||||
LIBINPUT_LED_SCROLL_LOCK = 1 << 2,
|
LIBINPUT_LED_SCROLL_LOCK = 1 << 2,
|
||||||
|
LIBINPUT_LED_COMPOSE = 1 << 3,
|
||||||
|
LIBINPUT_LED_KANA = 1 << 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
cenum! {
|
cenum! {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use {
|
||||||
LIBINPUT_CONFIG_DRAG_DISABLED, LIBINPUT_CONFIG_DRAG_ENABLED,
|
LIBINPUT_CONFIG_DRAG_DISABLED, LIBINPUT_CONFIG_DRAG_ENABLED,
|
||||||
LIBINPUT_CONFIG_DRAG_LOCK_DISABLED, LIBINPUT_CONFIG_DRAG_LOCK_ENABLED,
|
LIBINPUT_CONFIG_DRAG_LOCK_DISABLED, LIBINPUT_CONFIG_DRAG_LOCK_ENABLED,
|
||||||
LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED, LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED,
|
LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED, LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED,
|
||||||
LIBINPUT_CONFIG_TAP_DISABLED, LIBINPUT_CONFIG_TAP_ENABLED,
|
LIBINPUT_CONFIG_TAP_DISABLED, LIBINPUT_CONFIG_TAP_ENABLED, Led,
|
||||||
},
|
},
|
||||||
sys::{
|
sys::{
|
||||||
libinput_device, libinput_device_config_accel_get_profile,
|
libinput_device, libinput_device_config_accel_get_profile,
|
||||||
|
|
@ -36,8 +36,9 @@ use {
|
||||||
libinput_device_get_id_vendor, libinput_device_get_name, libinput_device_get_user_data,
|
libinput_device_get_id_vendor, libinput_device_get_name, libinput_device_get_user_data,
|
||||||
libinput_device_group, libinput_device_group_get_user_data,
|
libinput_device_group, libinput_device_group_get_user_data,
|
||||||
libinput_device_group_set_user_data, libinput_device_has_capability,
|
libinput_device_group_set_user_data, libinput_device_has_capability,
|
||||||
libinput_device_set_user_data, libinput_device_tablet_pad_get_mode_group,
|
libinput_device_led_update, libinput_device_set_user_data,
|
||||||
libinput_device_tablet_pad_get_num_buttons, libinput_device_tablet_pad_get_num_dials,
|
libinput_device_tablet_pad_get_mode_group, libinput_device_tablet_pad_get_num_buttons,
|
||||||
|
libinput_device_tablet_pad_get_num_dials,
|
||||||
libinput_device_tablet_pad_get_num_mode_groups,
|
libinput_device_tablet_pad_get_num_mode_groups,
|
||||||
libinput_device_tablet_pad_get_num_rings, libinput_device_tablet_pad_get_num_strips,
|
libinput_device_tablet_pad_get_num_rings, libinput_device_tablet_pad_get_num_strips,
|
||||||
libinput_device_unref, libinput_path_remove_device, libinput_tablet_pad_mode_group,
|
libinput_device_unref, libinput_path_remove_device, libinput_tablet_pad_mode_group,
|
||||||
|
|
@ -343,6 +344,12 @@ impl<'a> LibInputDevice<'a> {
|
||||||
}
|
}
|
||||||
[[m[0], m[1], m[2]], [m[3], m[4], m[5]]]
|
[[m[0], m[1], m[2]], [m[3], m[4], m[5]]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn led_update(&self, led: Led) {
|
||||||
|
unsafe {
|
||||||
|
libinput_device_led_update(self.dev, led.raw() as _);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> LibInputDeviceGroup<'a> {
|
impl<'a> LibInputDeviceGroup<'a> {
|
||||||
|
|
|
||||||
|
|
@ -410,6 +410,8 @@ unsafe extern "C" {
|
||||||
device: *mut libinput_device,
|
device: *mut libinput_device,
|
||||||
matrix: *mut [f32; 6],
|
matrix: *mut [f32; 6],
|
||||||
) -> c::c_int;
|
) -> c::c_int;
|
||||||
|
|
||||||
|
pub fn libinput_device_led_update(device: *mut libinput_device, leds: libinput_led);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
|
||||||
24
src/state.rs
24
src/state.rs
|
|
@ -83,7 +83,7 @@ use {
|
||||||
},
|
},
|
||||||
io_uring::IoUring,
|
io_uring::IoUring,
|
||||||
kbvm::{KbvmContext, KbvmMap},
|
kbvm::{KbvmContext, KbvmMap},
|
||||||
keyboard::KeyboardStateIds,
|
keyboard::{KeyboardStateIds, ModifiersListener},
|
||||||
leaks::Tracker,
|
leaks::Tracker,
|
||||||
logger::Logger,
|
logger::Logger,
|
||||||
pr_caps::PrCapsThread,
|
pr_caps::PrCapsThread,
|
||||||
|
|
@ -100,11 +100,21 @@ use {
|
||||||
generic_node_visitor,
|
generic_node_visitor,
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
activation_token::ActivationToken, asyncevent::AsyncEvent, bindings::Bindings,
|
activation_token::ActivationToken,
|
||||||
clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt,
|
asyncevent::AsyncEvent,
|
||||||
event_listener::EventSource, fdcloser::FdCloser, hash_map_ext::HashMapExt,
|
bindings::Bindings,
|
||||||
linkedlist::LinkedList, numcell::NumCell, queue::AsyncQueue, refcounted::RefCounted,
|
clonecell::CloneCell,
|
||||||
run_toplevel::RunToplevel, toplevel_identifier::ToplevelIdentifier,
|
copyhashmap::CopyHashMap,
|
||||||
|
errorfmt::ErrorFmt,
|
||||||
|
event_listener::{EventListener, EventSource},
|
||||||
|
fdcloser::FdCloser,
|
||||||
|
hash_map_ext::HashMapExt,
|
||||||
|
linkedlist::LinkedList,
|
||||||
|
numcell::NumCell,
|
||||||
|
queue::AsyncQueue,
|
||||||
|
refcounted::RefCounted,
|
||||||
|
run_toplevel::RunToplevel,
|
||||||
|
toplevel_identifier::ToplevelIdentifier,
|
||||||
},
|
},
|
||||||
video::{
|
video::{
|
||||||
dmabuf::DmaBufIds,
|
dmabuf::DmaBufIds,
|
||||||
|
|
@ -386,6 +396,8 @@ pub struct DeviceHandlerData {
|
||||||
pub tablet_init: Option<Box<TabletInit>>,
|
pub tablet_init: Option<Box<TabletInit>>,
|
||||||
pub tablet_pad_init: Option<Box<TabletPadInit>>,
|
pub tablet_pad_init: Option<Box<TabletPadInit>>,
|
||||||
pub is_touch: bool,
|
pub is_touch: bool,
|
||||||
|
pub is_kb: bool,
|
||||||
|
pub mods_listener: EventListener<dyn ModifiersListener>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ConnectorData {
|
pub struct ConnectorData {
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,13 @@ use {
|
||||||
ifs::wl_seat::PX_PER_SCROLL,
|
ifs::wl_seat::PX_PER_SCROLL,
|
||||||
state::{DeviceHandlerData, InputDeviceData, State},
|
state::{DeviceHandlerData, InputDeviceData, State},
|
||||||
tasks::udev_utils::{UdevProps, udev_props},
|
tasks::udev_utils::{UdevProps, udev_props},
|
||||||
utils::asyncevent::AsyncEvent,
|
utils::{asyncevent::AsyncEvent, event_listener::EventListener},
|
||||||
},
|
},
|
||||||
jay_config::_private::DEFAULT_SEAT_NAME,
|
jay_config::_private::DEFAULT_SEAT_NAME,
|
||||||
std::{cell::Cell, rc::Rc},
|
std::{
|
||||||
|
cell::Cell,
|
||||||
|
rc::{Rc, Weak},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn handle(state: &Rc<State>, dev: Rc<dyn InputDevice>) {
|
pub fn handle(state: &Rc<State>, dev: Rc<dyn InputDevice>) {
|
||||||
|
|
@ -15,7 +18,7 @@ pub fn handle(state: &Rc<State>, dev: Rc<dyn InputDevice>) {
|
||||||
None => UdevProps::default(),
|
None => UdevProps::default(),
|
||||||
Some(dev_t) => udev_props(dev_t, 3),
|
Some(dev_t) => udev_props(dev_t, 3),
|
||||||
};
|
};
|
||||||
let data = Rc::new(DeviceHandlerData {
|
let data = Rc::new_cyclic(|slf: &Weak<DeviceHandlerData>| DeviceHandlerData {
|
||||||
keyboard_id: state.physical_keyboard_ids.next(),
|
keyboard_id: state.physical_keyboard_ids.next(),
|
||||||
seat: Default::default(),
|
seat: Default::default(),
|
||||||
px_per_scroll_wheel: Cell::new(PX_PER_SCROLL),
|
px_per_scroll_wheel: Cell::new(PX_PER_SCROLL),
|
||||||
|
|
@ -27,6 +30,8 @@ pub fn handle(state: &Rc<State>, dev: Rc<dyn InputDevice>) {
|
||||||
tablet_init: dev.tablet_info(),
|
tablet_init: dev.tablet_info(),
|
||||||
tablet_pad_init: dev.tablet_pad_info(),
|
tablet_pad_init: dev.tablet_pad_info(),
|
||||||
is_touch: dev.has_capability(InputDeviceCapability::Touch),
|
is_touch: dev.has_capability(InputDeviceCapability::Touch),
|
||||||
|
is_kb: dev.has_capability(InputDeviceCapability::Keyboard),
|
||||||
|
mods_listener: EventListener::new(slf.clone()),
|
||||||
});
|
});
|
||||||
let ae = Rc::new(AsyncEvent::default());
|
let ae = Rc::new(AsyncEvent::default());
|
||||||
let oh = DeviceHandler {
|
let oh = DeviceHandler {
|
||||||
|
|
|
||||||
|
|
@ -78,4 +78,8 @@ impl<T: ?Sized> EventListener<T> {
|
||||||
pub fn detach(&self) {
|
pub fn detach(&self) {
|
||||||
self.link.detach();
|
self.link.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get(&self) -> Option<Rc<T>> {
|
||||||
|
self.link.upgrade()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue