Add keybind descriptions

This commit is contained in:
Ottatop 2024-06-15 14:06:23 -05:00
parent d70a0abda5
commit 5b241a626b
9 changed files with 456 additions and 122 deletions

View file

@ -34,12 +34,18 @@ require("pinnacle").setup(function(Pinnacle)
-- mod_key + alt + q = Quit Pinnacle
Input.keybind({ mod_key, "alt" }, "q", function()
Pinnacle.quit()
end)
end, {
group = "Compositor",
description = "Quit Pinnacle",
})
-- mod_key + alt + r = Reload config
Input.keybind({ mod_key, "alt" }, "r", function()
Pinnacle.reload_config()
end)
end, {
group = "Compositor",
description = "Reload the config",
})
-- mod_key + alt + c = Close window
Input.keybind({ mod_key, "alt" }, "c", function()
@ -47,12 +53,18 @@ require("pinnacle").setup(function(Pinnacle)
if focused then
focused:close()
end
end)
end, {
group = "Window",
description = "Close the focused window",
})
-- mod_key + alt + Return = Spawn `terminal`
Input.keybind({ mod_key }, key.Return, function()
Process.spawn(terminal)
end)
end, {
group = "Process",
description = "Spawn `alacritty`",
})
-- mod_key + alt + space = Toggle floating
Input.keybind({ mod_key, "alt" }, key.space, function()
@ -61,7 +73,10 @@ require("pinnacle").setup(function(Pinnacle)
focused:toggle_floating()
focused:raise()
end
end)
end, {
group = "Window",
description = "Toggle floating on the focused window",
})
-- mod_key + f = Toggle fullscreen
Input.keybind({ mod_key }, "f", function()
@ -70,7 +85,10 @@ require("pinnacle").setup(function(Pinnacle)
focused:toggle_fullscreen()
focused:raise()
end
end)
end, {
group = "Window",
description = "Toggle fullscreen on the focused window",
})
-- mod_key + m = Toggle maximized
Input.keybind({ mod_key }, "m", function()
@ -79,7 +97,10 @@ require("pinnacle").setup(function(Pinnacle)
focused:toggle_maximized()
focused:raise()
end
end)
end, {
group = "Window",
description = "Toggle maximized on the focused window",
})
----------------------
-- Tags and Outputs --
@ -109,12 +130,18 @@ require("pinnacle").setup(function(Pinnacle)
-- mod_key + 1-5 = Switch to tags 1-5
Input.keybind({ mod_key }, tag_name, function()
Tag.get(tag_name):switch_to()
end)
end, {
group = "Tag",
description = "Switch to tag " .. tag_name,
})
-- mod_key + shift + 1-5 = Toggle tags 1-5
Input.keybind({ mod_key, "shift" }, tag_name, function()
Tag.get(tag_name):toggle_active()
end)
end, {
group = "Tag",
description = "Toggle tag " .. tag_name,
})
-- mod_key + alt + 1-5 = Move window to tags 1-5
Input.keybind({ mod_key, "alt" }, tag_name, function()
@ -122,7 +149,10 @@ require("pinnacle").setup(function(Pinnacle)
if focused then
focused:move_to_tag(Tag.get(tag_name) --[[@as TagHandle]])
end
end)
end, {
group = "Tag",
description = "Move the focused window to tag " .. tag_name,
})
-- mod_key + shift + alt + 1-5 = Toggle tags 1-5 on window
Input.keybind({ mod_key, "shift", "alt" }, tag_name, function()
@ -130,7 +160,10 @@ require("pinnacle").setup(function(Pinnacle)
if focused then
focused:toggle_tag(Tag.get(tag_name) --[[@as TagHandle]])
end
end)
end, {
group = "Tag",
description = "Toggle tag " .. tag_name .. " on the focused window",
})
end
--------------------
@ -226,7 +259,10 @@ require("pinnacle").setup(function(Pinnacle)
Layout.request_layout(focused_op)
end
end
end)
end, {
group = "Layout",
description = "Cycle the layout forward on the first active tag",
})
-- mod_key + shift + space = Cycle backward one layout on the focused output
Input.keybind({ mod_key, "shift" }, key.space, function()
@ -257,7 +293,10 @@ require("pinnacle").setup(function(Pinnacle)
Layout.request_layout(focused_op)
end
end
end)
end, {
group = "Layout",
description = "Cycle the layout backward on the first active tag",
})
Input.set_libinput_settings({
tap = true,

View file

@ -258,6 +258,8 @@ local pinnacle_input_v0alpha1_Modifier = {
---@field modifiers pinnacle.input.v0alpha1.Modifier[]?
---@field raw_code integer?
---@field xkb_name string?
---@field group string?
---@field description string?
---@class pinnacle.input.v0alpha1.SetKeybindResponse
@ -274,6 +276,18 @@ local pinnacle_input_v0alpha1_SetMousebindRequest_MouseEdge = {
---@class pinnacle.input.v0alpha1.SetMousebindResponse
---@class pinnacle.input.v0alpha1.KeybindDescriptionsRequest
---@class pinnacle.input.v0alpha1.KeybindDescriptionsResponse
---@field descriptions pinnacle.input.v0alpha1.KeybindDescription[]?
---@class pinnacle.input.v0alpha1.KeybindDescription
---@field modifiers pinnacle.input.v0alpha1.Modifier[]?
---@field raw_code integer?
---@field xkb_name string?
---@field group string?
---@field description string?
---@class SetXkbConfigRequest
---@field rules string?
---@field variant string?
@ -729,6 +743,13 @@ defs.pinnacle = {
response = "pinnacle.input.v0alpha1.SetMousebindResponse",
},
---@type GrpcRequestArgs
KeybindDescriptions = {
service = "pinnacle.input.v0alpha1.InputService",
method = "KeybindDescriptions",
request = "pinnacle.input.v0alpha1.KeybindDescriptionsRequest",
response = "pinnacle.input.v0alpha1.KeybindDescriptionsResponse",
},
---@type GrpcRequestArgs
SetXkbConfig = {
service = "pinnacle.input.v0alpha1.InputService",
method = "SetXkbConfig",

View file

@ -74,6 +74,10 @@ local input = {
}
input.mouse_button_values = mouse_button_values
---@class KeybindInfo
---@field group string? The group to place this keybind in. Used for the keybind list.
---@field description string? The description of this keybind. Used for the keybind list.
---Set a keybind. If called with an already existing keybind, it gets replaced.
---
---You must provide three arguments:
@ -111,7 +115,8 @@ input.mouse_button_values = mouse_button_values
---@param mods Modifier[] The modifiers that need to be held down for the bind to trigger
---@param key Key | string The key used to trigger the bind
---@param action fun() The function to run when the bind is triggered
function input.keybind(mods, key, action)
---@param keybind_info KeybindInfo?
function input.keybind(mods, key, action, keybind_info)
local raw_code = nil
local xkb_name = nil
@ -130,6 +135,8 @@ function input.keybind(mods, key, action)
modifiers = mod_values,
raw_code = raw_code,
xkb_name = xkb_name,
group = keybind_info and keybind_info.group,
description = keybind_info and keybind_info.description,
}, action)
end
@ -165,6 +172,31 @@ function input.mousebind(mods, button, edge, action)
}, action)
end
---@class KeybindDescription
---@field modifiers Modifier[]
---@field raw_code integer
---@field xkb_name string
---@field group string?
---@field description string?
---Get all keybinds along with their descriptions
---
---@return KeybindDescription[]
function input.keybind_descriptions()
---@type pinnacle.input.v0alpha1.KeybindDescriptionsResponse
local descs = client.unary_request(input_service.KeybindDescriptions, {})
local descs = descs.descriptions or {}
local ret = {}
for _, desc in ipairs(descs) do
desc.modifiers = desc.modifiers or {}
table.insert(ret, desc)
end
return ret
end
---@class XkbConfig
---@field rules string?
---@field model string?

View file

@ -18,9 +18,25 @@ message SetKeybindRequest {
uint32 raw_code = 2;
string xkb_name = 3;
}
optional string group = 4;
optional string description = 5;
}
message SetKeybindResponse {}
message KeybindDescriptionsRequest {}
message KeybindDescriptionsResponse {
repeated KeybindDescription descriptions = 1;
}
message KeybindDescription {
repeated Modifier modifiers = 1;
optional uint32 raw_code = 2;
optional string xkb_name = 3;
optional string group = 4;
optional string description = 5;
}
message SetMousebindRequest {
repeated Modifier modifiers = 1;
// A button code corresponding to one of the `BTN_` prefixed definitions in input-event-codes.h
@ -131,6 +147,8 @@ service InputService {
rpc SetKeybind(SetKeybindRequest) returns (stream SetKeybindResponse);
rpc SetMousebind(SetMousebindRequest) returns (stream SetMousebindResponse);
rpc KeybindDescriptions(KeybindDescriptionsRequest) returns (KeybindDescriptionsResponse);
rpc SetXkbConfig(SetXkbConfigRequest) returns (google.protobuf.Empty);
rpc SetRepeatRate(SetRepeatRateRequest) returns (google.protobuf.Empty);

View file

@ -1,4 +1,5 @@
use pinnacle_api::input::libinput::LibinputSetting;
use pinnacle_api::input::KeybindInfo;
use pinnacle_api::layout::{
CornerLayout, CornerLocation, CyclingLayoutManager, DwindleLayout, FairLayout, MasterSide,
MasterStackLayout, SpiralLayout,
@ -51,6 +52,15 @@ async fn main() {
let terminal = "alacritty";
input.keybind(
[mod_key],
'i',
|| {
dbg!(input.keybind_descriptions().collect::<Vec<_>>());
},
None,
);
//------------------------
// Mousebinds |
//------------------------
@ -70,54 +80,110 @@ async fn main() {
//------------------------
// `mod_key + alt + q` quits Pinnacle
input.keybind([mod_key, Mod::Alt], 'q', || {
#[cfg(feature = "snowcap")]
snowcap.integration.quit_prompt().show();
input.keybind(
[mod_key, Mod::Alt],
'q',
|| {
#[cfg(feature = "snowcap")]
snowcap.integration.quit_prompt().show();
#[cfg(not(feature = "snowcap"))]
pinnacle.quit();
});
#[cfg(not(feature = "snowcap"))]
pinnacle.quit();
},
KeybindInfo {
group: Some("Compositor".into()),
description: Some("Quit Pinnacle".into()),
},
);
// `mod_key + alt + r` reloads the config
input.keybind([mod_key, Mod::Alt], 'r', || {
pinnacle.reload_config();
});
input.keybind(
[mod_key, Mod::Alt],
'r',
|| {
pinnacle.reload_config();
},
KeybindInfo {
group: Some("Compositor".into()),
description: Some("Reload the config".into()),
},
);
// `mod_key + alt + c` closes the focused window
input.keybind([mod_key, Mod::Alt], 'c', || {
if let Some(window) = window.get_focused() {
window.close();
}
});
input.keybind(
[mod_key, Mod::Alt],
'c',
|| {
if let Some(window) = window.get_focused() {
window.close();
}
},
KeybindInfo {
group: Some("Window".into()),
description: Some("Close the focused window".into()),
},
);
// `mod_key + Return` spawns a terminal
input.keybind([mod_key], Keysym::Return, move || {
process.spawn([terminal]);
});
input.keybind(
[mod_key],
Keysym::Return,
move || {
process.spawn([terminal]);
},
KeybindInfo {
group: Some("Process".into()),
description: Some("Spawn `alacritty`".into()),
},
);
// `mod_key + alt + space` toggles floating
input.keybind([mod_key, Mod::Alt], Keysym::space, || {
if let Some(window) = window.get_focused() {
window.toggle_floating();
window.raise();
}
});
input.keybind(
[mod_key, Mod::Alt],
Keysym::space,
|| {
if let Some(window) = window.get_focused() {
window.toggle_floating();
window.raise();
}
},
KeybindInfo {
group: Some("Window".into()),
description: Some("Toggle floating on the focused window".into()),
},
);
// `mod_key + f` toggles fullscreen
input.keybind([mod_key], 'f', || {
if let Some(window) = window.get_focused() {
window.toggle_fullscreen();
window.raise();
}
});
input.keybind(
[mod_key],
'f',
|| {
if let Some(window) = window.get_focused() {
window.toggle_fullscreen();
window.raise();
}
},
KeybindInfo {
group: Some("Window".into()),
description: Some("Toggle fullscreen on the focused window".into()),
},
);
// `mod_key + m` toggles maximized
input.keybind([mod_key], 'm', || {
if let Some(window) = window.get_focused() {
window.toggle_maximized();
window.raise();
}
});
input.keybind(
[mod_key],
'm',
|| {
if let Some(window) = window.get_focused() {
window.toggle_maximized();
window.raise();
}
},
KeybindInfo {
group: Some("Window".into()),
description: Some("Toggle maximized on the focused window".into()),
},
);
//------------------------
// Window rules |
@ -200,32 +266,48 @@ async fn main() {
let mut layout_requester_clone = layout_requester.clone();
// `mod_key + space` cycles to the next layout
input.keybind([mod_key], Keysym::space, move || {
let Some(focused_op) = output.get_focused() else { return };
let Some(first_active_tag) = focused_op.tags().batch_find(
|tg| Box::pin(tg.active_async()),
|active| active == &Some(true),
) else {
return;
};
input.keybind(
[mod_key],
Keysym::space,
move || {
let Some(focused_op) = output.get_focused() else { return };
let Some(first_active_tag) = focused_op.tags().batch_find(
|tg| Box::pin(tg.active_async()),
|active| active == &Some(true),
) else {
return;
};
layout_requester.cycle_layout_forward(&first_active_tag);
layout_requester.request_layout_on_output(&focused_op);
});
layout_requester.cycle_layout_forward(&first_active_tag);
layout_requester.request_layout_on_output(&focused_op);
},
KeybindInfo {
group: Some("Layout".into()),
description: Some("Cycle the layout forward on the first active tag".into()),
},
);
// `mod_key + shift + space` cycles to the previous layout
input.keybind([mod_key, Mod::Shift], Keysym::space, move || {
let Some(focused_op) = output.get_focused() else { return };
let Some(first_active_tag) = focused_op.tags().batch_find(
|tg| Box::pin(tg.active_async()),
|active| active == &Some(true),
) else {
return;
};
input.keybind(
[mod_key, Mod::Shift],
Keysym::space,
move || {
let Some(focused_op) = output.get_focused() else { return };
let Some(first_active_tag) = focused_op.tags().batch_find(
|tg| Box::pin(tg.active_async()),
|active| active == &Some(true),
) else {
return;
};
layout_requester_clone.cycle_layout_backward(&first_active_tag);
layout_requester_clone.request_layout_on_output(&focused_op);
});
layout_requester_clone.cycle_layout_backward(&first_active_tag);
layout_requester_clone.request_layout_on_output(&focused_op);
},
KeybindInfo {
group: Some("Layout".into()),
description: Some("Cycle the layout backward on the first active tag".into()),
},
);
//------------------------
// Tags |
@ -238,36 +320,68 @@ async fn main() {
for tag_name in tag_names {
// `mod_key + 1-5` switches to tag "1" to "5"
input.keybind([mod_key], tag_name, move || {
if let Some(tg) = tag.get(tag_name) {
tg.switch_to();
}
});
input.keybind(
[mod_key],
tag_name,
move || {
if let Some(tg) = tag.get(tag_name) {
tg.switch_to();
}
},
KeybindInfo {
group: Some("Tag".into()),
description: Some(format!("Switch to tag {tag_name}")),
},
);
// `mod_key + shift + 1-5` toggles tag "1" to "5"
input.keybind([mod_key, Mod::Shift], tag_name, move || {
if let Some(tg) = tag.get(tag_name) {
tg.toggle_active();
}
});
input.keybind(
[mod_key, Mod::Shift],
tag_name,
move || {
if let Some(tg) = tag.get(tag_name) {
tg.toggle_active();
}
},
KeybindInfo {
group: Some("Tag".into()),
description: Some(format!("Toggle tag {tag_name}")),
},
);
// `mod_key + alt + 1-5` moves the focused window to tag "1" to "5"
input.keybind([mod_key, Mod::Alt], tag_name, move || {
if let Some(tg) = tag.get(tag_name) {
if let Some(win) = window.get_focused() {
win.move_to_tag(&tg);
input.keybind(
[mod_key, Mod::Alt],
tag_name,
move || {
if let Some(tg) = tag.get(tag_name) {
if let Some(win) = window.get_focused() {
win.move_to_tag(&tg);
}
}
}
});
},
KeybindInfo {
group: Some("Tag".into()),
description: Some(format!("Move the focused window to tag {tag_name}")),
},
);
// `mod_key + shift + alt + 1-5` toggles tag "1" to "5" on the focused window
input.keybind([mod_key, Mod::Shift, Mod::Alt], tag_name, move || {
if let Some(tg) = tag.get(tag_name) {
if let Some(win) = window.get_focused() {
win.toggle_tag(&tg);
input.keybind(
[mod_key, Mod::Shift, Mod::Alt],
tag_name,
move || {
if let Some(tg) = tag.get(tag_name) {
if let Some(win) = window.get_focused() {
win.toggle_tag(&tg);
}
}
}
});
},
KeybindInfo {
group: Some("Tag".into()),
description: Some(format!("Toggle tag {tag_name} on the focused window")),
},
);
}
input.set_libinput_setting(LibinputSetting::Tap(true));

View file

@ -15,8 +15,8 @@ use pinnacle_api_defs::pinnacle::input::{
v0alpha1::{
input_service_client::InputServiceClient,
set_libinput_setting_request::{CalibrationMatrix, Setting},
SetKeybindRequest, SetLibinputSettingRequest, SetMousebindRequest, SetRepeatRateRequest,
SetXkbConfigRequest,
KeybindDescriptionsRequest, SetKeybindRequest, SetLibinputSettingRequest,
SetMousebindRequest, SetRepeatRateRequest, SetXkbConfigRequest,
},
};
use tokio::sync::mpsc::UnboundedSender;
@ -99,6 +99,32 @@ pub struct Input {
fut_sender: UnboundedSender<BoxFuture<'static, ()>>,
}
/// Keybind information.
///
/// Mainly used for the keybind list.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
pub struct KeybindInfo {
/// The group to place this keybind in.
pub group: Option<String>,
/// The description of this keybind.
pub description: Option<String>,
}
/// The description of a keybind.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct KeybindDescription {
/// The keybind's modifiers.
pub modifiers: Vec<Mod>,
/// The keysym code.
pub key_code: u32,
/// The name of the key.
pub xkb_name: String,
/// The group.
pub group: Option<String>,
/// The description of the keybind.
pub description: Option<String>,
}
impl Input {
pub(crate) fn new(
channel: Channel,
@ -157,25 +183,28 @@ impl Input {
mods: impl IntoIterator<Item = Mod>,
key: impl Key + Send + 'static,
mut action: impl FnMut() + Send + 'static,
keybind_info: impl Into<Option<KeybindInfo>>,
) {
let mut client = self.create_input_client();
let modifiers = mods.into_iter().map(|modif| modif as i32).collect();
let keybind_info: Option<KeybindInfo> = keybind_info.into();
let mut stream = block_on_tokio(client.set_keybind(SetKeybindRequest {
modifiers,
key: Some(input::v0alpha1::set_keybind_request::Key::RawCode(
key.into_keysym().raw(),
)),
group: keybind_info.clone().and_then(|info| info.group),
description: keybind_info.clone().and_then(|info| info.description),
}))
.unwrap()
.into_inner();
self.fut_sender
.send(
async move {
let mut stream = client
.set_keybind(SetKeybindRequest {
modifiers,
key: Some(input::v0alpha1::set_keybind_request::Key::RawCode(
key.into_keysym().raw(),
)),
})
.await
.unwrap()
.into_inner();
while let Some(Ok(_response)) = stream.next().await {
action();
tokio::task::yield_now().await;
@ -218,20 +247,17 @@ impl Input {
let mut client = self.create_input_client();
let modifiers = mods.into_iter().map(|modif| modif as i32).collect();
let mut stream = block_on_tokio(client.set_mousebind(SetMousebindRequest {
modifiers,
button: Some(button as u32),
edge: Some(edge as i32),
}))
.unwrap()
.into_inner();
self.fut_sender
.send(
async move {
let mut stream = client
.set_mousebind(SetMousebindRequest {
modifiers,
button: Some(button as u32),
edge: Some(edge as i32),
})
.await
.unwrap()
.into_inner();
while let Some(Ok(_response)) = stream.next().await {
action();
tokio::task::yield_now().await;
@ -242,6 +268,31 @@ impl Input {
.unwrap();
}
/// Get all keybinds and their information.
pub fn keybind_descriptions(&self) -> impl Iterator<Item = KeybindDescription> {
let mut client = self.create_input_client();
let descriptions =
block_on_tokio(client.keybind_descriptions(KeybindDescriptionsRequest {})).unwrap();
let descriptions = descriptions.into_inner();
descriptions.descriptions.into_iter().map(|desc| {
let mods = desc.modifiers().flat_map(|m| match m {
input::v0alpha1::Modifier::Unspecified => None,
input::v0alpha1::Modifier::Shift => Some(Mod::Shift),
input::v0alpha1::Modifier::Ctrl => Some(Mod::Ctrl),
input::v0alpha1::Modifier::Alt => Some(Mod::Alt),
input::v0alpha1::Modifier::Super => Some(Mod::Super),
});
KeybindDescription {
modifiers: mods.collect(),
key_code: desc.raw_code(),
xkb_name: desc.xkb_name().to_string(),
group: desc.group,
description: desc.description,
}
})
}
/// Set the xkeyboard config.
///
/// This allows you to set several xkeyboard options like `layout` and `rules`.

View file

@ -237,6 +237,7 @@ pub async fn connect() -> Result<(ApiModules, Receivers), Box<dyn std::error::Er
tag.finish_init(modules.clone());
layout.finish_init(modules.clone());
signal.read().await.finish_init(modules.clone());
#[cfg(feature = "snowcap")]
modules.snowcap.finish_init(modules.clone());
#[cfg(feature = "snowcap")]

View file

@ -9,6 +9,7 @@ use pinnacle_api_defs::pinnacle::{
input_service_server,
set_libinput_setting_request::{AccelProfile, ClickMethod, ScrollMethod, TapButtonMap},
set_mousebind_request::MouseEdge,
KeybindDescription, KeybindDescriptionsRequest, KeybindDescriptionsResponse, Modifier,
SetKeybindRequest, SetKeybindResponse, SetLibinputSettingRequest, SetMousebindRequest,
SetMousebindResponse, SetRepeatRateRequest, SetXkbConfigRequest,
},
@ -55,7 +56,7 @@ use tracing::{debug, error, info, trace, warn};
use crate::{
backend::{udev::drm_mode_from_api_modeline, BackendData},
config::ConnectorSavedState,
input::ModifierMask,
input::{KeybindData, ModifierMask},
output::{OutputMode, OutputName},
render::util::snapshot::capture_snapshots_on_output,
state::{State, WithState},
@ -293,12 +294,21 @@ impl input_service_server::InputService for InputService {
}
};
let group = request.group;
let description = request.description;
run_server_streaming(&self.sender, move |state, sender| {
let keybind_data = KeybindData {
sender,
group,
description,
};
state
.pinnacle
.input_state
.keybinds
.insert((modifiers, keysym), sender);
.insert((modifiers, keysym), keybind_data);
})
}
@ -346,6 +356,47 @@ impl input_service_server::InputService for InputService {
})
}
async fn keybind_descriptions(
&self,
_request: Request<KeybindDescriptionsRequest>,
) -> Result<Response<KeybindDescriptionsResponse>, Status> {
run_unary(&self.sender, |state| {
let descriptions =
state
.pinnacle
.input_state
.keybinds
.iter()
.map(|((mods, key), data)| {
let mut modifiers = Vec::<i32>::new();
if mods.contains(ModifierMask::CTRL) {
modifiers.push(Modifier::Ctrl as i32);
}
if mods.contains(ModifierMask::ALT) {
modifiers.push(Modifier::Alt as i32);
}
if mods.contains(ModifierMask::SUPER) {
modifiers.push(Modifier::Super as i32);
}
if mods.contains(ModifierMask::SHIFT) {
modifiers.push(Modifier::Shift as i32);
}
KeybindDescription {
modifiers,
raw_code: Some(key.raw()),
xkb_name: Some(xkbcommon::xkb::keysym_get_name(*key)),
group: data.group.clone(),
description: data.description.clone(),
}
});
KeybindDescriptionsResponse {
descriptions: descriptions.collect(),
}
})
.await
}
async fn set_xkb_config(
&self,
request: Request<SetXkbConfigRequest>,

View file

@ -13,6 +13,7 @@ use crate::{
state::{Pinnacle, WithState},
window::WindowElement,
};
use indexmap::IndexMap;
use pinnacle_api_defs::pinnacle::input::v0alpha1::{
set_libinput_setting_request::Setting, set_mousebind_request, SetKeybindResponse,
SetMousebindResponse,
@ -93,14 +94,20 @@ impl From<&ModifiersState> for ModifierMask {
}
}
#[derive(Debug)]
pub struct KeybindData {
pub sender: UnboundedSender<Result<SetKeybindResponse, tonic::Status>>,
pub group: Option<String>,
pub description: Option<String>,
}
#[derive(Default)]
pub struct InputState {
// TODO: move all of these to config
pub reload_keybind: Option<(ModifierMask, Keysym)>,
pub kill_keybind: Option<(ModifierMask, Keysym)>,
pub keybinds:
HashMap<(ModifierMask, Keysym), UnboundedSender<Result<SetKeybindResponse, tonic::Status>>>,
pub keybinds: IndexMap<(ModifierMask, Keysym), KeybindData>,
pub mousebinds: HashMap<
(ModifierMask, u32, set_mousebind_request::MouseEdge),
UnboundedSender<Result<SetMousebindResponse, tonic::Status>>,
@ -540,7 +547,7 @@ impl State {
let raw_sym = keysym.raw_syms().iter().next();
let mod_sym = keysym.modified_sym();
if let Some(sender) = state
if let Some(keybind_data) = state
.pinnacle
.input_state
.keybinds
@ -557,7 +564,7 @@ impl State {
{
if state.pinnacle.lock_state.is_unlocked() {
return FilterResult::Intercept(KeyAction::CallCallback(
sender.clone(),
keybind_data.sender.clone(),
));
}
}