mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2024-12-26 21:58:10 +01:00
Merge pull request #96 from pinnacle-comp/input
Add input options to API
This commit is contained in:
commit
a109c704ec
10 changed files with 500 additions and 70 deletions
|
@ -35,7 +35,6 @@ xdg = "2.5.2"
|
|||
lazy_static = "1.4.0"
|
||||
sysinfo = "0.29.10"
|
||||
|
||||
|
||||
[features]
|
||||
default = ["egl", "winit", "udev", "xwayland"]
|
||||
egl = ["smithay/use_system_lib", "smithay/backend_egl"]
|
||||
|
|
|
@ -31,14 +31,19 @@ require("pinnacle").setup(function(pinnacle)
|
|||
process.set_env("MOZ_ENABLE_WAYLAND", "1")
|
||||
|
||||
-- Outputs -----------------------------------------------------------------------
|
||||
|
||||
-- You can set your own monitor layout as I have done below for my monitors.
|
||||
|
||||
--
|
||||
-- local lg = output.get_by_name("DP-2") --[[@as Output]]
|
||||
-- local dell = output.get_by_name("DP-3") --[[@as Output]]
|
||||
--
|
||||
-- dell:set_loc_left_of(lg, "bottom")
|
||||
|
||||
-- Libinput settings -------------------------------------------------------------
|
||||
-- If you want to change settings like pointer acceleration,
|
||||
-- you can do them in `input.libinput`.
|
||||
--
|
||||
-- input.libinput.set_accel_profile("Flat")
|
||||
|
||||
-- Mousebinds --------------------------------------------------------------------
|
||||
|
||||
input.mousebind({ "Ctrl" }, buttons.left, "Press", function()
|
||||
|
|
|
@ -26,6 +26,13 @@ local buttons = {
|
|||
back = 0x116,
|
||||
}
|
||||
|
||||
---@class XkbConfig
|
||||
---@field rules string?
|
||||
---@field model string?
|
||||
---@field layout string?
|
||||
---@field variant string?
|
||||
---@field options string?
|
||||
|
||||
---Input management.
|
||||
---
|
||||
---This module provides utilities to set keybinds.
|
||||
|
@ -36,6 +43,8 @@ local input_module = {
|
|||
--- A table with mouse button codes. You can use indexes (1, 2, and 3 are left, right, and middle)
|
||||
--- or keyed values (buttons.left, buttons.right, etc.).
|
||||
buttons = buttons,
|
||||
--- Libinput settings.
|
||||
libinput = require("input.libinput"),
|
||||
}
|
||||
|
||||
---Set a keybind. If called with an already existing keybind, it gets replaced.
|
||||
|
@ -114,4 +123,25 @@ function input_module.mousebind(modifiers, button, edge, action)
|
|||
})
|
||||
end
|
||||
|
||||
---Set the xkbconfig for your keyboard.
|
||||
---
|
||||
---Fields not present will be set to their default values.
|
||||
---
|
||||
---Read `xkeyboard-config(7)` for more information.
|
||||
---
|
||||
---### Example
|
||||
---```lua
|
||||
---input.set_xkb_config({
|
||||
--- layout = "us,fr,ge",
|
||||
--- options = "ctrl:swapcaps,caps:shift"
|
||||
---})
|
||||
---```
|
||||
---
|
||||
---@param xkb_config XkbConfig
|
||||
function input_module.set_xkb_config(xkb_config)
|
||||
SendMsg({
|
||||
SetXkbConfig = xkb_config,
|
||||
})
|
||||
end
|
||||
|
||||
return input_module
|
||||
|
|
211
api/lua/input/libinput.lua
Normal file
211
api/lua/input/libinput.lua
Normal file
|
@ -0,0 +1,211 @@
|
|||
-- SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
---@class LibinputSetting
|
||||
---@field AccelProfile (AccelProfile)?
|
||||
---@field AccelSpeed float?
|
||||
---@field CalibrationMatrix float[]?
|
||||
---@field ClickMethod (ClickMethod)?
|
||||
---@field DisableWhileTypingEnabled boolean?
|
||||
---@field LeftHanded boolean?
|
||||
---@field MiddleEmulationEnabled boolean?
|
||||
---@field RotationAngle integer? A u32
|
||||
---@field ScrollMethod (ScrollMethod)?
|
||||
---@field NaturalScrollEnabled boolean?
|
||||
---@field ScrollButton integer? A u32
|
||||
---@field TapButtonMap TapButtonMap?
|
||||
---@field TapDragEnabled boolean?
|
||||
---@field TapDragLockEnabled boolean?
|
||||
---@field TapEnabled boolean?
|
||||
|
||||
---@alias AccelProfile
|
||||
---| "Flat" # Flat pointer acceleration.
|
||||
---| "Adaptive" Adaptive pointer acceleration. This is the default for most devices.
|
||||
|
||||
---@alias ClickMethod
|
||||
---| "ButtonAreas" # Use software-button areas to generate button events.
|
||||
---| "Clickfinger" # The number of fingers decides which button press to generate.
|
||||
|
||||
---@alias ScrollMethod
|
||||
---| "NoScroll" # Never send scroll events.
|
||||
---| "TwoFinger" # Send scroll events when two fingers are logically down on the device.
|
||||
---| "Edge" # Send scroll events when a finger moves along the bottom or right edge of a device.
|
||||
---| "OnButtonDown" # Send scroll events when a button is down and the device moves along a scroll-capable axis.
|
||||
|
||||
---@alias TapButtonMap
|
||||
---| "LeftRightMiddle" # 1/2/3 finger tap is mapped to left/right/middle click.
|
||||
---| "LeftMiddleRight" # 1/2/3 finger tap is mapped to left/middle/right click.
|
||||
|
||||
---Configuration options for libinput.
|
||||
---
|
||||
---Here, you can configure how input devices like your mouse and touchpad function.
|
||||
---@class Libinput
|
||||
local libinput = {}
|
||||
|
||||
---Set the acceleration profile.
|
||||
---@param profile AccelProfile
|
||||
function libinput.set_accel_profile(profile)
|
||||
SendMsg({
|
||||
SetLibinputSetting = {
|
||||
AccelProfile = profile,
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
---Set the acceleration speed.
|
||||
---@param speed float The speed from -1 to 1.
|
||||
function libinput.set_accel_speed(speed)
|
||||
SendMsg({
|
||||
SetLibinputSetting = {
|
||||
AccelSpeed = speed,
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
---Set the calibration matrix.
|
||||
---@param matrix float[] A 6-element float array.
|
||||
function libinput.set_calibration_matrix(matrix)
|
||||
if #matrix ~= 6 then
|
||||
return
|
||||
end
|
||||
|
||||
SendMsg({
|
||||
SetLibinputSetting = {
|
||||
CalibrationMatrix = matrix,
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
---Set the click method.
|
||||
---
|
||||
---The click method defines when to generate software-emulated buttons, usually on a device
|
||||
---that does not have a specific physical button available.
|
||||
---@param method ClickMethod
|
||||
function libinput.set_click_method(method)
|
||||
SendMsg({
|
||||
SetLibinputSetting = {
|
||||
ClickMethod = method,
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
---Set whether or not the device will be disabled while typing.
|
||||
---@param enabled boolean
|
||||
function libinput.set_disable_while_typing_enabled(enabled)
|
||||
SendMsg({
|
||||
SetLibinputSetting = {
|
||||
DisableWhileTypingEnabled = enabled,
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
---Set device left-handedness.
|
||||
---@param enabled boolean
|
||||
function libinput.set_left_handed(enabled)
|
||||
SendMsg({
|
||||
SetLibinputSetting = {
|
||||
LeftHanded = enabled,
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
---Set whether or not the middle click can be emulated.
|
||||
---@param enabled boolean
|
||||
function libinput.set_middle_emulation_enabled(enabled)
|
||||
SendMsg({
|
||||
SetLibinputSetting = {
|
||||
MiddleEmulationEnabled = enabled,
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
---Set the rotation angle of a device.
|
||||
---@param angle integer An integer in the range [0, 360].
|
||||
function libinput.set_rotation_angle(angle)
|
||||
SendMsg({
|
||||
SetLibinputSetting = {
|
||||
RotationAngle = angle,
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
---Set the scroll method.
|
||||
---@param method ScrollMethod
|
||||
function libinput.set_scroll_method(method)
|
||||
SendMsg({
|
||||
SetLibinputSetting = {
|
||||
ScrollMethod = method,
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
---Set whether or not natural scroll is enabled.
|
||||
---
|
||||
---This reverses the direction of scrolling and is mainly used with touchpads.
|
||||
---@param enabled boolean
|
||||
function libinput.set_natural_scroll_enabled(enabled)
|
||||
SendMsg({
|
||||
SetLibinputSetting = {
|
||||
NaturalScrollEnabled = enabled,
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
---Set the scroll button.
|
||||
---@param button integer
|
||||
function libinput.set_scroll_button(button)
|
||||
SendMsg({
|
||||
SetLibinputSetting = {
|
||||
ScrollButton = button,
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
---Set the tap button map.
|
||||
---
|
||||
---This determines whether taps with 2 and 3 fingers register as right and middle clicks or the reverse.
|
||||
---@param map TapButtonMap
|
||||
function libinput.set_tap_button_map(map)
|
||||
SendMsg({
|
||||
SetLibinputSetting = {
|
||||
TapButtonMap = map,
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
---Set whether or not tap-to-click is enabled.
|
||||
---@param enabled boolean
|
||||
function libinput.set_tap_enabled(enabled)
|
||||
SendMsg({
|
||||
SetLibinputSetting = {
|
||||
TapEnabled = enabled,
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
---Set whether or not tap-and-drag is enabled.
|
||||
---
|
||||
---When enabled, a single-finger tap immediately followed by a finger down results in
|
||||
---a button down event, and subsequent finger motion thus triggers a drag. The button is released on finger up.
|
||||
---@param enabled boolean
|
||||
function libinput.set_tap_drag_enabled(enabled)
|
||||
SendMsg({
|
||||
SetLibinputSetting = {
|
||||
TapDragEnabled = enabled,
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
---Set whether or not tap drag lock is enabled.
|
||||
---
|
||||
---When enabled, a finger may be lifted and put back on the touchpad within a timeout and the drag process
|
||||
---continues. When disabled, lifting the finger during a tap-and-drag will immediately stop the drag.
|
||||
---@param enabled boolean
|
||||
function libinput.set_tap_drag_lock_enabled(enabled)
|
||||
SendMsg({
|
||||
SetLibinputSetting = {
|
||||
TapDragLockEnabled = enabled,
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
return libinput
|
|
@ -19,7 +19,6 @@
|
|||
--
|
||||
---@field Spawn { command: string[], callback_id: integer? }?
|
||||
---@field SetEnv { key: string, value: string }?
|
||||
---@field Request Request?
|
||||
--Tags
|
||||
---@field ToggleTag { tag_id: TagId }?
|
||||
---@field SwitchToTag { tag_id: TagId }?
|
||||
|
@ -29,6 +28,10 @@
|
|||
--Outputs
|
||||
---@field ConnectForAllOutputs { callback_id: integer }?
|
||||
---@field SetOutputLocation { output_name: OutputName, x: integer?, y: integer? }?
|
||||
--Input
|
||||
---@field SetXkbConfig XkbConfig?
|
||||
---@field SetLibinputSetting LibinputSetting?
|
||||
---@field Request Request?
|
||||
|
||||
---@alias Msg _Msg | "Quit"
|
||||
|
||||
|
|
|
@ -259,6 +259,7 @@ pub fn run_udev() -> anyhow::Result<()> {
|
|||
.handle()
|
||||
.insert_source(libinput_backend, move |event, _, data| {
|
||||
// println!("event: {:?}", event);
|
||||
data.state.apply_libinput_settings(&event);
|
||||
data.state.process_input_event(event);
|
||||
});
|
||||
|
||||
|
|
|
@ -150,6 +150,7 @@ impl State {
|
|||
tracing::debug!("Clearing mouse and keybinds");
|
||||
self.input_state.keybinds.clear();
|
||||
self.input_state.mousebinds.clear();
|
||||
self.input_state.libinput_settings.clear();
|
||||
self.config.window_rules.clear();
|
||||
|
||||
tracing::debug!("Killing old config");
|
||||
|
|
|
@ -8,6 +8,7 @@ pub mod window_rules;
|
|||
use smithay::input::keyboard::ModifiersState;
|
||||
|
||||
use crate::{
|
||||
input::LibinputSetting,
|
||||
layout::Layout,
|
||||
output::OutputName,
|
||||
tag::TagId,
|
||||
|
@ -31,7 +32,7 @@ pub enum MouseEdge {
|
|||
Release,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
pub enum Msg {
|
||||
// Input
|
||||
SetKeybind {
|
||||
|
@ -134,6 +135,22 @@ pub enum Msg {
|
|||
/// Quit the compositor.
|
||||
Quit,
|
||||
|
||||
// Input management
|
||||
SetXkbConfig {
|
||||
#[serde(default)]
|
||||
rules: Option<String>,
|
||||
#[serde(default)]
|
||||
variant: Option<String>,
|
||||
#[serde(default)]
|
||||
layout: Option<String>,
|
||||
#[serde(default)]
|
||||
model: Option<String>,
|
||||
#[serde(default)]
|
||||
options: Option<String>,
|
||||
},
|
||||
|
||||
SetLibinputSetting(LibinputSetting),
|
||||
|
||||
Request {
|
||||
request_id: RequestId,
|
||||
request: Request,
|
||||
|
|
262
src/input.rs
262
src/input.rs
|
@ -14,6 +14,7 @@ use smithay::{
|
|||
AbsolutePositionEvent, Axis, AxisSource, ButtonState, Event, InputBackend, InputEvent,
|
||||
KeyState, KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent, PointerMotionEvent,
|
||||
},
|
||||
libinput::LibinputInputBackend,
|
||||
session::Session,
|
||||
},
|
||||
desktop::{layer_map_for_output, space::SpaceElement},
|
||||
|
@ -21,6 +22,7 @@ use smithay::{
|
|||
keyboard::{keysyms, FilterResult},
|
||||
pointer::{AxisFrame, ButtonEvent, MotionEvent, RelativeMotionEvent},
|
||||
},
|
||||
reexports::input::{self, AccelProfile, ClickMethod, Led, ScrollMethod, TapButtonMap},
|
||||
utils::{Logical, Point, SERIAL_COUNTER},
|
||||
wayland::{seat::WaylandFocus, shell::wlr_layer},
|
||||
};
|
||||
|
@ -35,6 +37,8 @@ pub struct InputState {
|
|||
pub mousebinds: HashMap<(ModifierMask, u32, MouseEdge), CallbackId>,
|
||||
pub reload_keybind: Option<(ModifierMask, u32)>,
|
||||
pub kill_keybind: Option<(ModifierMask, u32)>,
|
||||
pub libinput_settings: Vec<LibinputSetting>,
|
||||
pub libinput_devices: Vec<input::Device>,
|
||||
}
|
||||
|
||||
impl InputState {
|
||||
|
@ -51,7 +55,125 @@ enum KeyAction {
|
|||
ReloadConfig,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
#[serde(remote = "AccelProfile")]
|
||||
enum AccelProfileDef {
|
||||
Flat,
|
||||
Adaptive,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
#[serde(remote = "ClickMethod")]
|
||||
enum ClickMethodDef {
|
||||
ButtonAreas,
|
||||
Clickfinger,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
#[serde(remote = "ScrollMethod")]
|
||||
enum ScrollMethodDef {
|
||||
NoScroll,
|
||||
TwoFinger,
|
||||
Edge,
|
||||
OnButtonDown,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
#[serde(remote = "TapButtonMap")]
|
||||
enum TapButtonMapDef {
|
||||
LeftRightMiddle,
|
||||
LeftMiddleRight,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Copy, Clone, serde::Deserialize)]
|
||||
pub enum LibinputSetting {
|
||||
#[serde(with = "AccelProfileDef")]
|
||||
AccelProfile(AccelProfile),
|
||||
AccelSpeed(f64),
|
||||
CalibrationMatrix([f32; 6]),
|
||||
#[serde(with = "ClickMethodDef")]
|
||||
ClickMethod(ClickMethod),
|
||||
DisableWhileTypingEnabled(bool),
|
||||
LeftHanded(bool),
|
||||
MiddleEmulationEnabled(bool),
|
||||
RotationAngle(u32),
|
||||
#[serde(with = "ScrollMethodDef")]
|
||||
ScrollMethod(ScrollMethod),
|
||||
NaturalScrollEnabled(bool),
|
||||
ScrollButton(u32),
|
||||
#[serde(with = "TapButtonMapDef")]
|
||||
TapButtonMap(TapButtonMap),
|
||||
TapDragEnabled(bool),
|
||||
TapDragLockEnabled(bool),
|
||||
TapEnabled(bool),
|
||||
}
|
||||
|
||||
impl LibinputSetting {
|
||||
pub fn apply_to_device(&self, device: &mut input::Device) {
|
||||
let _ = match self {
|
||||
LibinputSetting::AccelProfile(profile) => device.config_accel_set_profile(*profile),
|
||||
LibinputSetting::AccelSpeed(speed) => device.config_accel_set_speed(*speed),
|
||||
LibinputSetting::CalibrationMatrix(matrix) => {
|
||||
device.config_calibration_set_matrix(*matrix)
|
||||
}
|
||||
LibinputSetting::ClickMethod(method) => device.config_click_set_method(*method),
|
||||
LibinputSetting::DisableWhileTypingEnabled(enabled) => {
|
||||
device.config_dwt_set_enabled(*enabled)
|
||||
}
|
||||
LibinputSetting::LeftHanded(enabled) => device.config_left_handed_set(*enabled),
|
||||
LibinputSetting::MiddleEmulationEnabled(enabled) => {
|
||||
device.config_middle_emulation_set_enabled(*enabled)
|
||||
}
|
||||
LibinputSetting::RotationAngle(angle) => device.config_rotation_set_angle(*angle),
|
||||
LibinputSetting::ScrollMethod(method) => device.config_scroll_set_method(*method),
|
||||
LibinputSetting::NaturalScrollEnabled(enabled) => {
|
||||
device.config_scroll_set_natural_scroll_enabled(*enabled)
|
||||
}
|
||||
LibinputSetting::ScrollButton(button) => device.config_scroll_set_button(*button),
|
||||
LibinputSetting::TapButtonMap(map) => device.config_tap_set_button_map(*map),
|
||||
LibinputSetting::TapDragEnabled(enabled) => {
|
||||
device.config_tap_set_drag_enabled(*enabled)
|
||||
}
|
||||
LibinputSetting::TapDragLockEnabled(enabled) => {
|
||||
device.config_tap_set_drag_lock_enabled(*enabled)
|
||||
}
|
||||
LibinputSetting::TapEnabled(enabled) => device.config_tap_set_enabled(*enabled),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// We want to completely replace old settings, so we hash only the discriminant.
|
||||
impl std::hash::Hash for LibinputSetting {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
core::mem::discriminant(self).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
/// Apply current libinput settings to new devices.
|
||||
pub fn apply_libinput_settings(&mut self, event: &InputEvent<LibinputInputBackend>) {
|
||||
let mut device = match event {
|
||||
InputEvent::DeviceAdded { device } => device.clone(),
|
||||
InputEvent::DeviceRemoved { device } => {
|
||||
self.input_state
|
||||
.libinput_devices
|
||||
.retain(|dev| dev != device);
|
||||
return;
|
||||
}
|
||||
_ => return,
|
||||
};
|
||||
|
||||
if self.input_state.libinput_devices.contains(&device) {
|
||||
return;
|
||||
}
|
||||
|
||||
for setting in self.input_state.libinput_settings.iter() {
|
||||
setting.apply_to_device(&mut device);
|
||||
}
|
||||
|
||||
self.input_state.libinput_devices.push(device);
|
||||
}
|
||||
|
||||
pub fn process_input_event<B: InputBackend>(&mut self, event: InputEvent<B>) {
|
||||
match event {
|
||||
// TODO: rest of input events
|
||||
|
@ -152,79 +274,89 @@ impl State {
|
|||
let reload_keybind = self.input_state.reload_keybind;
|
||||
let kill_keybind = self.input_state.kill_keybind;
|
||||
|
||||
let action = self
|
||||
.seat
|
||||
.get_keyboard()
|
||||
.expect("Seat has no keyboard") // FIXME: handle err
|
||||
.input(
|
||||
self,
|
||||
event.key_code(),
|
||||
press_state,
|
||||
serial,
|
||||
time,
|
||||
|state, modifiers, keysym| {
|
||||
if press_state == KeyState::Pressed {
|
||||
let mut modifier_mask = Vec::<Modifier>::new();
|
||||
if modifiers.alt {
|
||||
modifier_mask.push(Modifier::Alt);
|
||||
}
|
||||
if modifiers.shift {
|
||||
modifier_mask.push(Modifier::Shift);
|
||||
}
|
||||
if modifiers.ctrl {
|
||||
modifier_mask.push(Modifier::Ctrl);
|
||||
}
|
||||
if modifiers.logo {
|
||||
modifier_mask.push(Modifier::Super);
|
||||
}
|
||||
let modifier_mask = ModifierMask::from(modifier_mask);
|
||||
let raw_sym = keysym.raw_syms().iter().next();
|
||||
let mod_sym = keysym.modified_sym();
|
||||
let keyboard = self.seat.get_keyboard().expect("Seat has no keyboard");
|
||||
|
||||
let cb_id_mod = state
|
||||
.input_state
|
||||
.keybinds
|
||||
.get(&(modifier_mask, mod_sym));
|
||||
let modifiers = keyboard.modifier_state();
|
||||
|
||||
let cb_id_raw = if let Some(raw_sym) = raw_sym {
|
||||
state.input_state.keybinds.get(&(modifier_mask, *raw_sym))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let mut leds = Led::empty();
|
||||
if modifiers.num_lock {
|
||||
leds |= Led::NUMLOCK;
|
||||
}
|
||||
if modifiers.caps_lock {
|
||||
leds |= Led::CAPSLOCK;
|
||||
}
|
||||
|
||||
match (cb_id_mod, cb_id_raw) {
|
||||
(Some(cb_id), _) | (None, Some(cb_id)) => {
|
||||
return FilterResult::Intercept(KeyAction::CallCallback(*cb_id));
|
||||
}
|
||||
(None, None) => ()
|
||||
// FIXME: Leds only update once another key is pressed.
|
||||
for device in self.input_state.libinput_devices.iter_mut() {
|
||||
device.led_update(leds);
|
||||
}
|
||||
|
||||
let action = keyboard.input(
|
||||
self,
|
||||
event.key_code(),
|
||||
press_state,
|
||||
serial,
|
||||
time,
|
||||
|state, modifiers, keysym| {
|
||||
if press_state == KeyState::Pressed {
|
||||
let mut modifier_mask = Vec::<Modifier>::new();
|
||||
if modifiers.alt {
|
||||
modifier_mask.push(Modifier::Alt);
|
||||
}
|
||||
if modifiers.shift {
|
||||
modifier_mask.push(Modifier::Shift);
|
||||
}
|
||||
if modifiers.ctrl {
|
||||
modifier_mask.push(Modifier::Ctrl);
|
||||
}
|
||||
if modifiers.logo {
|
||||
modifier_mask.push(Modifier::Super);
|
||||
}
|
||||
let modifier_mask = ModifierMask::from(modifier_mask);
|
||||
let raw_sym = keysym.raw_syms().iter().next();
|
||||
let mod_sym = keysym.modified_sym();
|
||||
|
||||
let cb_id_mod = state.input_state.keybinds.get(&(modifier_mask, mod_sym));
|
||||
|
||||
let cb_id_raw = if let Some(raw_sym) = raw_sym {
|
||||
state.input_state.keybinds.get(&(modifier_mask, *raw_sym))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
match (cb_id_mod, cb_id_raw) {
|
||||
(Some(cb_id), _) | (None, Some(cb_id)) => {
|
||||
return FilterResult::Intercept(KeyAction::CallCallback(*cb_id));
|
||||
}
|
||||
|
||||
if Some((modifier_mask, mod_sym)) == kill_keybind {
|
||||
return FilterResult::Intercept(KeyAction::Quit);
|
||||
} else if Some((modifier_mask, mod_sym)) == reload_keybind {
|
||||
return FilterResult::Intercept(KeyAction::ReloadConfig);
|
||||
} else if let mut vt @ keysyms::KEY_XF86Switch_VT_1..=keysyms::KEY_XF86Switch_VT_12 =
|
||||
keysym.modified_sym() {
|
||||
vt = vt - keysyms::KEY_XF86Switch_VT_1 + 1;
|
||||
tracing::info!("Switching to vt {vt}");
|
||||
return FilterResult::Intercept(KeyAction::SwitchVt(vt as i32));
|
||||
}
|
||||
|
||||
(None, None) => (),
|
||||
}
|
||||
|
||||
if keysym.modified_sym() == keysyms::KEY_Control_L {
|
||||
match press_state {
|
||||
KeyState::Pressed => {
|
||||
move_mode = true;
|
||||
}
|
||||
KeyState::Released => {
|
||||
move_mode = false;
|
||||
}
|
||||
if Some((modifier_mask, mod_sym)) == kill_keybind {
|
||||
return FilterResult::Intercept(KeyAction::Quit);
|
||||
} else if Some((modifier_mask, mod_sym)) == reload_keybind {
|
||||
return FilterResult::Intercept(KeyAction::ReloadConfig);
|
||||
} else if let mut vt @ keysyms::KEY_XF86Switch_VT_1
|
||||
..=keysyms::KEY_XF86Switch_VT_12 = keysym.modified_sym()
|
||||
{
|
||||
vt = vt - keysyms::KEY_XF86Switch_VT_1 + 1;
|
||||
tracing::info!("Switching to vt {vt}");
|
||||
return FilterResult::Intercept(KeyAction::SwitchVt(vt as i32));
|
||||
}
|
||||
}
|
||||
|
||||
if keysym.modified_sym() == keysyms::KEY_Control_L {
|
||||
match press_state {
|
||||
KeyState::Pressed => {
|
||||
move_mode = true;
|
||||
}
|
||||
KeyState::Released => {
|
||||
move_mode = false;
|
||||
}
|
||||
}
|
||||
FilterResult::Forward
|
||||
},
|
||||
);
|
||||
}
|
||||
FilterResult::Forward
|
||||
},
|
||||
);
|
||||
|
||||
match action {
|
||||
Some(KeyAction::CallCallback(callback_id)) => {
|
||||
|
|
|
@ -4,6 +4,7 @@ use async_process::Stdio;
|
|||
use futures_lite::AsyncBufReadExt;
|
||||
use smithay::{
|
||||
desktop::space::SpaceElement,
|
||||
input::keyboard::XkbConfig,
|
||||
reexports::wayland_protocols::xdg::shell::server::xdg_toplevel::ResizeEdge,
|
||||
utils::{Point, Rectangle, SERIAL_COUNTER},
|
||||
wayland::{compositor, shell::xdg::XdgToplevelSurfaceData},
|
||||
|
@ -349,6 +350,36 @@ impl State {
|
|||
self.loop_signal.stop();
|
||||
}
|
||||
|
||||
Msg::SetXkbConfig {
|
||||
rules,
|
||||
variant,
|
||||
layout,
|
||||
model,
|
||||
options,
|
||||
} => {
|
||||
let new_config = XkbConfig {
|
||||
rules: &rules.unwrap_or_default(),
|
||||
model: &model.unwrap_or_default(),
|
||||
layout: &layout.unwrap_or_default(),
|
||||
variant: &variant.unwrap_or_default(),
|
||||
options,
|
||||
};
|
||||
if let Some(kb) = self.seat.get_keyboard() {
|
||||
if let Err(err) = kb.set_xkb_config(self, new_config) {
|
||||
tracing::error!("Failed to set xkbconfig: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Msg::SetLibinputSetting(setting) => {
|
||||
for device in self.input_state.libinput_devices.iter_mut() {
|
||||
// We're just gonna indiscriminately apply everything and ignore errors
|
||||
setting.apply_to_device(device);
|
||||
}
|
||||
|
||||
self.input_state.libinput_settings.push(setting);
|
||||
}
|
||||
|
||||
Msg::Request {
|
||||
request_id,
|
||||
request,
|
||||
|
|
Loading…
Reference in a new issue