mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2025-01-30 20:34:49 +01:00
Add keybind descriptions
This commit is contained in:
parent
d70a0abda5
commit
5b241a626b
9 changed files with 456 additions and 122 deletions
|
@ -34,12 +34,18 @@ require("pinnacle").setup(function(Pinnacle)
|
||||||
-- mod_key + alt + q = Quit Pinnacle
|
-- mod_key + alt + q = Quit Pinnacle
|
||||||
Input.keybind({ mod_key, "alt" }, "q", function()
|
Input.keybind({ mod_key, "alt" }, "q", function()
|
||||||
Pinnacle.quit()
|
Pinnacle.quit()
|
||||||
end)
|
end, {
|
||||||
|
group = "Compositor",
|
||||||
|
description = "Quit Pinnacle",
|
||||||
|
})
|
||||||
|
|
||||||
-- mod_key + alt + r = Reload config
|
-- mod_key + alt + r = Reload config
|
||||||
Input.keybind({ mod_key, "alt" }, "r", function()
|
Input.keybind({ mod_key, "alt" }, "r", function()
|
||||||
Pinnacle.reload_config()
|
Pinnacle.reload_config()
|
||||||
end)
|
end, {
|
||||||
|
group = "Compositor",
|
||||||
|
description = "Reload the config",
|
||||||
|
})
|
||||||
|
|
||||||
-- mod_key + alt + c = Close window
|
-- mod_key + alt + c = Close window
|
||||||
Input.keybind({ mod_key, "alt" }, "c", function()
|
Input.keybind({ mod_key, "alt" }, "c", function()
|
||||||
|
@ -47,12 +53,18 @@ require("pinnacle").setup(function(Pinnacle)
|
||||||
if focused then
|
if focused then
|
||||||
focused:close()
|
focused:close()
|
||||||
end
|
end
|
||||||
end)
|
end, {
|
||||||
|
group = "Window",
|
||||||
|
description = "Close the focused window",
|
||||||
|
})
|
||||||
|
|
||||||
-- mod_key + alt + Return = Spawn `terminal`
|
-- mod_key + alt + Return = Spawn `terminal`
|
||||||
Input.keybind({ mod_key }, key.Return, function()
|
Input.keybind({ mod_key }, key.Return, function()
|
||||||
Process.spawn(terminal)
|
Process.spawn(terminal)
|
||||||
end)
|
end, {
|
||||||
|
group = "Process",
|
||||||
|
description = "Spawn `alacritty`",
|
||||||
|
})
|
||||||
|
|
||||||
-- mod_key + alt + space = Toggle floating
|
-- mod_key + alt + space = Toggle floating
|
||||||
Input.keybind({ mod_key, "alt" }, key.space, function()
|
Input.keybind({ mod_key, "alt" }, key.space, function()
|
||||||
|
@ -61,7 +73,10 @@ require("pinnacle").setup(function(Pinnacle)
|
||||||
focused:toggle_floating()
|
focused:toggle_floating()
|
||||||
focused:raise()
|
focused:raise()
|
||||||
end
|
end
|
||||||
end)
|
end, {
|
||||||
|
group = "Window",
|
||||||
|
description = "Toggle floating on the focused window",
|
||||||
|
})
|
||||||
|
|
||||||
-- mod_key + f = Toggle fullscreen
|
-- mod_key + f = Toggle fullscreen
|
||||||
Input.keybind({ mod_key }, "f", function()
|
Input.keybind({ mod_key }, "f", function()
|
||||||
|
@ -70,7 +85,10 @@ require("pinnacle").setup(function(Pinnacle)
|
||||||
focused:toggle_fullscreen()
|
focused:toggle_fullscreen()
|
||||||
focused:raise()
|
focused:raise()
|
||||||
end
|
end
|
||||||
end)
|
end, {
|
||||||
|
group = "Window",
|
||||||
|
description = "Toggle fullscreen on the focused window",
|
||||||
|
})
|
||||||
|
|
||||||
-- mod_key + m = Toggle maximized
|
-- mod_key + m = Toggle maximized
|
||||||
Input.keybind({ mod_key }, "m", function()
|
Input.keybind({ mod_key }, "m", function()
|
||||||
|
@ -79,7 +97,10 @@ require("pinnacle").setup(function(Pinnacle)
|
||||||
focused:toggle_maximized()
|
focused:toggle_maximized()
|
||||||
focused:raise()
|
focused:raise()
|
||||||
end
|
end
|
||||||
end)
|
end, {
|
||||||
|
group = "Window",
|
||||||
|
description = "Toggle maximized on the focused window",
|
||||||
|
})
|
||||||
|
|
||||||
----------------------
|
----------------------
|
||||||
-- Tags and Outputs --
|
-- Tags and Outputs --
|
||||||
|
@ -109,12 +130,18 @@ require("pinnacle").setup(function(Pinnacle)
|
||||||
-- mod_key + 1-5 = Switch to tags 1-5
|
-- mod_key + 1-5 = Switch to tags 1-5
|
||||||
Input.keybind({ mod_key }, tag_name, function()
|
Input.keybind({ mod_key }, tag_name, function()
|
||||||
Tag.get(tag_name):switch_to()
|
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
|
-- mod_key + shift + 1-5 = Toggle tags 1-5
|
||||||
Input.keybind({ mod_key, "shift" }, tag_name, function()
|
Input.keybind({ mod_key, "shift" }, tag_name, function()
|
||||||
Tag.get(tag_name):toggle_active()
|
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
|
-- mod_key + alt + 1-5 = Move window to tags 1-5
|
||||||
Input.keybind({ mod_key, "alt" }, tag_name, function()
|
Input.keybind({ mod_key, "alt" }, tag_name, function()
|
||||||
|
@ -122,7 +149,10 @@ require("pinnacle").setup(function(Pinnacle)
|
||||||
if focused then
|
if focused then
|
||||||
focused:move_to_tag(Tag.get(tag_name) --[[@as TagHandle]])
|
focused:move_to_tag(Tag.get(tag_name) --[[@as TagHandle]])
|
||||||
end
|
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
|
-- mod_key + shift + alt + 1-5 = Toggle tags 1-5 on window
|
||||||
Input.keybind({ mod_key, "shift", "alt" }, tag_name, function()
|
Input.keybind({ mod_key, "shift", "alt" }, tag_name, function()
|
||||||
|
@ -130,7 +160,10 @@ require("pinnacle").setup(function(Pinnacle)
|
||||||
if focused then
|
if focused then
|
||||||
focused:toggle_tag(Tag.get(tag_name) --[[@as TagHandle]])
|
focused:toggle_tag(Tag.get(tag_name) --[[@as TagHandle]])
|
||||||
end
|
end
|
||||||
end)
|
end, {
|
||||||
|
group = "Tag",
|
||||||
|
description = "Toggle tag " .. tag_name .. " on the focused window",
|
||||||
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------
|
--------------------
|
||||||
|
@ -226,7 +259,10 @@ require("pinnacle").setup(function(Pinnacle)
|
||||||
Layout.request_layout(focused_op)
|
Layout.request_layout(focused_op)
|
||||||
end
|
end
|
||||||
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
|
-- mod_key + shift + space = Cycle backward one layout on the focused output
|
||||||
Input.keybind({ mod_key, "shift" }, key.space, function()
|
Input.keybind({ mod_key, "shift" }, key.space, function()
|
||||||
|
@ -257,7 +293,10 @@ require("pinnacle").setup(function(Pinnacle)
|
||||||
Layout.request_layout(focused_op)
|
Layout.request_layout(focused_op)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end, {
|
||||||
|
group = "Layout",
|
||||||
|
description = "Cycle the layout backward on the first active tag",
|
||||||
|
})
|
||||||
|
|
||||||
Input.set_libinput_settings({
|
Input.set_libinput_settings({
|
||||||
tap = true,
|
tap = true,
|
||||||
|
|
|
@ -258,6 +258,8 @@ local pinnacle_input_v0alpha1_Modifier = {
|
||||||
---@field modifiers pinnacle.input.v0alpha1.Modifier[]?
|
---@field modifiers pinnacle.input.v0alpha1.Modifier[]?
|
||||||
---@field raw_code integer?
|
---@field raw_code integer?
|
||||||
---@field xkb_name string?
|
---@field xkb_name string?
|
||||||
|
---@field group string?
|
||||||
|
---@field description string?
|
||||||
|
|
||||||
---@class pinnacle.input.v0alpha1.SetKeybindResponse
|
---@class pinnacle.input.v0alpha1.SetKeybindResponse
|
||||||
|
|
||||||
|
@ -274,6 +276,18 @@ local pinnacle_input_v0alpha1_SetMousebindRequest_MouseEdge = {
|
||||||
|
|
||||||
---@class pinnacle.input.v0alpha1.SetMousebindResponse
|
---@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
|
---@class SetXkbConfigRequest
|
||||||
---@field rules string?
|
---@field rules string?
|
||||||
---@field variant string?
|
---@field variant string?
|
||||||
|
@ -729,6 +743,13 @@ defs.pinnacle = {
|
||||||
response = "pinnacle.input.v0alpha1.SetMousebindResponse",
|
response = "pinnacle.input.v0alpha1.SetMousebindResponse",
|
||||||
},
|
},
|
||||||
---@type GrpcRequestArgs
|
---@type GrpcRequestArgs
|
||||||
|
KeybindDescriptions = {
|
||||||
|
service = "pinnacle.input.v0alpha1.InputService",
|
||||||
|
method = "KeybindDescriptions",
|
||||||
|
request = "pinnacle.input.v0alpha1.KeybindDescriptionsRequest",
|
||||||
|
response = "pinnacle.input.v0alpha1.KeybindDescriptionsResponse",
|
||||||
|
},
|
||||||
|
---@type GrpcRequestArgs
|
||||||
SetXkbConfig = {
|
SetXkbConfig = {
|
||||||
service = "pinnacle.input.v0alpha1.InputService",
|
service = "pinnacle.input.v0alpha1.InputService",
|
||||||
method = "SetXkbConfig",
|
method = "SetXkbConfig",
|
||||||
|
|
|
@ -74,6 +74,10 @@ local input = {
|
||||||
}
|
}
|
||||||
input.mouse_button_values = mouse_button_values
|
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.
|
---Set a keybind. If called with an already existing keybind, it gets replaced.
|
||||||
---
|
---
|
||||||
---You must provide three arguments:
|
---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 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 key Key | string The key used to trigger the bind
|
||||||
---@param action fun() The function to run when the bind is triggered
|
---@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 raw_code = nil
|
||||||
local xkb_name = nil
|
local xkb_name = nil
|
||||||
|
|
||||||
|
@ -130,6 +135,8 @@ function input.keybind(mods, key, action)
|
||||||
modifiers = mod_values,
|
modifiers = mod_values,
|
||||||
raw_code = raw_code,
|
raw_code = raw_code,
|
||||||
xkb_name = xkb_name,
|
xkb_name = xkb_name,
|
||||||
|
group = keybind_info and keybind_info.group,
|
||||||
|
description = keybind_info and keybind_info.description,
|
||||||
}, action)
|
}, action)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -165,6 +172,31 @@ function input.mousebind(mods, button, edge, action)
|
||||||
}, action)
|
}, action)
|
||||||
end
|
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
|
---@class XkbConfig
|
||||||
---@field rules string?
|
---@field rules string?
|
||||||
---@field model string?
|
---@field model string?
|
||||||
|
|
|
@ -18,9 +18,25 @@ message SetKeybindRequest {
|
||||||
uint32 raw_code = 2;
|
uint32 raw_code = 2;
|
||||||
string xkb_name = 3;
|
string xkb_name = 3;
|
||||||
}
|
}
|
||||||
|
optional string group = 4;
|
||||||
|
optional string description = 5;
|
||||||
}
|
}
|
||||||
message SetKeybindResponse {}
|
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 {
|
message SetMousebindRequest {
|
||||||
repeated Modifier modifiers = 1;
|
repeated Modifier modifiers = 1;
|
||||||
// A button code corresponding to one of the `BTN_` prefixed definitions in input-event-codes.h
|
// 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 SetKeybind(SetKeybindRequest) returns (stream SetKeybindResponse);
|
||||||
rpc SetMousebind(SetMousebindRequest) returns (stream SetMousebindResponse);
|
rpc SetMousebind(SetMousebindRequest) returns (stream SetMousebindResponse);
|
||||||
|
|
||||||
|
rpc KeybindDescriptions(KeybindDescriptionsRequest) returns (KeybindDescriptionsResponse);
|
||||||
|
|
||||||
rpc SetXkbConfig(SetXkbConfigRequest) returns (google.protobuf.Empty);
|
rpc SetXkbConfig(SetXkbConfigRequest) returns (google.protobuf.Empty);
|
||||||
rpc SetRepeatRate(SetRepeatRateRequest) returns (google.protobuf.Empty);
|
rpc SetRepeatRate(SetRepeatRateRequest) returns (google.protobuf.Empty);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use pinnacle_api::input::libinput::LibinputSetting;
|
use pinnacle_api::input::libinput::LibinputSetting;
|
||||||
|
use pinnacle_api::input::KeybindInfo;
|
||||||
use pinnacle_api::layout::{
|
use pinnacle_api::layout::{
|
||||||
CornerLayout, CornerLocation, CyclingLayoutManager, DwindleLayout, FairLayout, MasterSide,
|
CornerLayout, CornerLocation, CyclingLayoutManager, DwindleLayout, FairLayout, MasterSide,
|
||||||
MasterStackLayout, SpiralLayout,
|
MasterStackLayout, SpiralLayout,
|
||||||
|
@ -51,6 +52,15 @@ async fn main() {
|
||||||
|
|
||||||
let terminal = "alacritty";
|
let terminal = "alacritty";
|
||||||
|
|
||||||
|
input.keybind(
|
||||||
|
[mod_key],
|
||||||
|
'i',
|
||||||
|
|| {
|
||||||
|
dbg!(input.keybind_descriptions().collect::<Vec<_>>());
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
//------------------------
|
//------------------------
|
||||||
// Mousebinds |
|
// Mousebinds |
|
||||||
//------------------------
|
//------------------------
|
||||||
|
@ -70,54 +80,110 @@ async fn main() {
|
||||||
//------------------------
|
//------------------------
|
||||||
|
|
||||||
// `mod_key + alt + q` quits Pinnacle
|
// `mod_key + alt + q` quits Pinnacle
|
||||||
input.keybind([mod_key, Mod::Alt], 'q', || {
|
input.keybind(
|
||||||
#[cfg(feature = "snowcap")]
|
[mod_key, Mod::Alt],
|
||||||
snowcap.integration.quit_prompt().show();
|
'q',
|
||||||
|
|| {
|
||||||
|
#[cfg(feature = "snowcap")]
|
||||||
|
snowcap.integration.quit_prompt().show();
|
||||||
|
|
||||||
#[cfg(not(feature = "snowcap"))]
|
#[cfg(not(feature = "snowcap"))]
|
||||||
pinnacle.quit();
|
pinnacle.quit();
|
||||||
});
|
},
|
||||||
|
KeybindInfo {
|
||||||
|
group: Some("Compositor".into()),
|
||||||
|
description: Some("Quit Pinnacle".into()),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// `mod_key + alt + r` reloads the config
|
// `mod_key + alt + r` reloads the config
|
||||||
input.keybind([mod_key, Mod::Alt], 'r', || {
|
input.keybind(
|
||||||
pinnacle.reload_config();
|
[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
|
// `mod_key + alt + c` closes the focused window
|
||||||
input.keybind([mod_key, Mod::Alt], 'c', || {
|
input.keybind(
|
||||||
if let Some(window) = window.get_focused() {
|
[mod_key, Mod::Alt],
|
||||||
window.close();
|
'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
|
// `mod_key + Return` spawns a terminal
|
||||||
input.keybind([mod_key], Keysym::Return, move || {
|
input.keybind(
|
||||||
process.spawn([terminal]);
|
[mod_key],
|
||||||
});
|
Keysym::Return,
|
||||||
|
move || {
|
||||||
|
process.spawn([terminal]);
|
||||||
|
},
|
||||||
|
KeybindInfo {
|
||||||
|
group: Some("Process".into()),
|
||||||
|
description: Some("Spawn `alacritty`".into()),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// `mod_key + alt + space` toggles floating
|
// `mod_key + alt + space` toggles floating
|
||||||
input.keybind([mod_key, Mod::Alt], Keysym::space, || {
|
input.keybind(
|
||||||
if let Some(window) = window.get_focused() {
|
[mod_key, Mod::Alt],
|
||||||
window.toggle_floating();
|
Keysym::space,
|
||||||
window.raise();
|
|| {
|
||||||
}
|
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
|
// `mod_key + f` toggles fullscreen
|
||||||
input.keybind([mod_key], 'f', || {
|
input.keybind(
|
||||||
if let Some(window) = window.get_focused() {
|
[mod_key],
|
||||||
window.toggle_fullscreen();
|
'f',
|
||||||
window.raise();
|
|| {
|
||||||
}
|
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
|
// `mod_key + m` toggles maximized
|
||||||
input.keybind([mod_key], 'm', || {
|
input.keybind(
|
||||||
if let Some(window) = window.get_focused() {
|
[mod_key],
|
||||||
window.toggle_maximized();
|
'm',
|
||||||
window.raise();
|
|| {
|
||||||
}
|
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 |
|
// Window rules |
|
||||||
|
@ -200,32 +266,48 @@ async fn main() {
|
||||||
let mut layout_requester_clone = layout_requester.clone();
|
let mut layout_requester_clone = layout_requester.clone();
|
||||||
|
|
||||||
// `mod_key + space` cycles to the next layout
|
// `mod_key + space` cycles to the next layout
|
||||||
input.keybind([mod_key], Keysym::space, move || {
|
input.keybind(
|
||||||
let Some(focused_op) = output.get_focused() else { return };
|
[mod_key],
|
||||||
let Some(first_active_tag) = focused_op.tags().batch_find(
|
Keysym::space,
|
||||||
|tg| Box::pin(tg.active_async()),
|
move || {
|
||||||
|active| active == &Some(true),
|
let Some(focused_op) = output.get_focused() else { return };
|
||||||
) else {
|
let Some(first_active_tag) = focused_op.tags().batch_find(
|
||||||
return;
|
|tg| Box::pin(tg.active_async()),
|
||||||
};
|
|active| active == &Some(true),
|
||||||
|
) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
layout_requester.cycle_layout_forward(&first_active_tag);
|
layout_requester.cycle_layout_forward(&first_active_tag);
|
||||||
layout_requester.request_layout_on_output(&focused_op);
|
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
|
// `mod_key + shift + space` cycles to the previous layout
|
||||||
input.keybind([mod_key, Mod::Shift], Keysym::space, move || {
|
input.keybind(
|
||||||
let Some(focused_op) = output.get_focused() else { return };
|
[mod_key, Mod::Shift],
|
||||||
let Some(first_active_tag) = focused_op.tags().batch_find(
|
Keysym::space,
|
||||||
|tg| Box::pin(tg.active_async()),
|
move || {
|
||||||
|active| active == &Some(true),
|
let Some(focused_op) = output.get_focused() else { return };
|
||||||
) else {
|
let Some(first_active_tag) = focused_op.tags().batch_find(
|
||||||
return;
|
|tg| Box::pin(tg.active_async()),
|
||||||
};
|
|active| active == &Some(true),
|
||||||
|
) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
layout_requester_clone.cycle_layout_backward(&first_active_tag);
|
layout_requester_clone.cycle_layout_backward(&first_active_tag);
|
||||||
layout_requester_clone.request_layout_on_output(&focused_op);
|
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 |
|
// Tags |
|
||||||
|
@ -238,36 +320,68 @@ async fn main() {
|
||||||
|
|
||||||
for tag_name in tag_names {
|
for tag_name in tag_names {
|
||||||
// `mod_key + 1-5` switches to tag "1" to "5"
|
// `mod_key + 1-5` switches to tag "1" to "5"
|
||||||
input.keybind([mod_key], tag_name, move || {
|
input.keybind(
|
||||||
if let Some(tg) = tag.get(tag_name) {
|
[mod_key],
|
||||||
tg.switch_to();
|
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"
|
// `mod_key + shift + 1-5` toggles tag "1" to "5"
|
||||||
input.keybind([mod_key, Mod::Shift], tag_name, move || {
|
input.keybind(
|
||||||
if let Some(tg) = tag.get(tag_name) {
|
[mod_key, Mod::Shift],
|
||||||
tg.toggle_active();
|
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"
|
// `mod_key + alt + 1-5` moves the focused window to tag "1" to "5"
|
||||||
input.keybind([mod_key, Mod::Alt], tag_name, move || {
|
input.keybind(
|
||||||
if let Some(tg) = tag.get(tag_name) {
|
[mod_key, Mod::Alt],
|
||||||
if let Some(win) = window.get_focused() {
|
tag_name,
|
||||||
win.move_to_tag(&tg);
|
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
|
// `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 || {
|
input.keybind(
|
||||||
if let Some(tg) = tag.get(tag_name) {
|
[mod_key, Mod::Shift, Mod::Alt],
|
||||||
if let Some(win) = window.get_focused() {
|
tag_name,
|
||||||
win.toggle_tag(&tg);
|
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));
|
input.set_libinput_setting(LibinputSetting::Tap(true));
|
||||||
|
|
|
@ -15,8 +15,8 @@ use pinnacle_api_defs::pinnacle::input::{
|
||||||
v0alpha1::{
|
v0alpha1::{
|
||||||
input_service_client::InputServiceClient,
|
input_service_client::InputServiceClient,
|
||||||
set_libinput_setting_request::{CalibrationMatrix, Setting},
|
set_libinput_setting_request::{CalibrationMatrix, Setting},
|
||||||
SetKeybindRequest, SetLibinputSettingRequest, SetMousebindRequest, SetRepeatRateRequest,
|
KeybindDescriptionsRequest, SetKeybindRequest, SetLibinputSettingRequest,
|
||||||
SetXkbConfigRequest,
|
SetMousebindRequest, SetRepeatRateRequest, SetXkbConfigRequest,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
|
@ -99,6 +99,32 @@ pub struct Input {
|
||||||
fut_sender: UnboundedSender<BoxFuture<'static, ()>>,
|
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 {
|
impl Input {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
channel: Channel,
|
channel: Channel,
|
||||||
|
@ -157,25 +183,28 @@ impl Input {
|
||||||
mods: impl IntoIterator<Item = Mod>,
|
mods: impl IntoIterator<Item = Mod>,
|
||||||
key: impl Key + Send + 'static,
|
key: impl Key + Send + 'static,
|
||||||
mut action: impl FnMut() + Send + 'static,
|
mut action: impl FnMut() + Send + 'static,
|
||||||
|
keybind_info: impl Into<Option<KeybindInfo>>,
|
||||||
) {
|
) {
|
||||||
let mut client = self.create_input_client();
|
let mut client = self.create_input_client();
|
||||||
|
|
||||||
let modifiers = mods.into_iter().map(|modif| modif as i32).collect();
|
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
|
self.fut_sender
|
||||||
.send(
|
.send(
|
||||||
async move {
|
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 {
|
while let Some(Ok(_response)) = stream.next().await {
|
||||||
action();
|
action();
|
||||||
tokio::task::yield_now().await;
|
tokio::task::yield_now().await;
|
||||||
|
@ -218,20 +247,17 @@ impl Input {
|
||||||
let mut client = self.create_input_client();
|
let mut client = self.create_input_client();
|
||||||
|
|
||||||
let modifiers = mods.into_iter().map(|modif| modif as i32).collect();
|
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
|
self.fut_sender
|
||||||
.send(
|
.send(
|
||||||
async move {
|
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 {
|
while let Some(Ok(_response)) = stream.next().await {
|
||||||
action();
|
action();
|
||||||
tokio::task::yield_now().await;
|
tokio::task::yield_now().await;
|
||||||
|
@ -242,6 +268,31 @@ impl Input {
|
||||||
.unwrap();
|
.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.
|
/// Set the xkeyboard config.
|
||||||
///
|
///
|
||||||
/// This allows you to set several xkeyboard options like `layout` and `rules`.
|
/// This allows you to set several xkeyboard options like `layout` and `rules`.
|
||||||
|
|
|
@ -237,6 +237,7 @@ pub async fn connect() -> Result<(ApiModules, Receivers), Box<dyn std::error::Er
|
||||||
tag.finish_init(modules.clone());
|
tag.finish_init(modules.clone());
|
||||||
layout.finish_init(modules.clone());
|
layout.finish_init(modules.clone());
|
||||||
signal.read().await.finish_init(modules.clone());
|
signal.read().await.finish_init(modules.clone());
|
||||||
|
#[cfg(feature = "snowcap")]
|
||||||
modules.snowcap.finish_init(modules.clone());
|
modules.snowcap.finish_init(modules.clone());
|
||||||
|
|
||||||
#[cfg(feature = "snowcap")]
|
#[cfg(feature = "snowcap")]
|
||||||
|
|
55
src/api.rs
55
src/api.rs
|
@ -9,6 +9,7 @@ use pinnacle_api_defs::pinnacle::{
|
||||||
input_service_server,
|
input_service_server,
|
||||||
set_libinput_setting_request::{AccelProfile, ClickMethod, ScrollMethod, TapButtonMap},
|
set_libinput_setting_request::{AccelProfile, ClickMethod, ScrollMethod, TapButtonMap},
|
||||||
set_mousebind_request::MouseEdge,
|
set_mousebind_request::MouseEdge,
|
||||||
|
KeybindDescription, KeybindDescriptionsRequest, KeybindDescriptionsResponse, Modifier,
|
||||||
SetKeybindRequest, SetKeybindResponse, SetLibinputSettingRequest, SetMousebindRequest,
|
SetKeybindRequest, SetKeybindResponse, SetLibinputSettingRequest, SetMousebindRequest,
|
||||||
SetMousebindResponse, SetRepeatRateRequest, SetXkbConfigRequest,
|
SetMousebindResponse, SetRepeatRateRequest, SetXkbConfigRequest,
|
||||||
},
|
},
|
||||||
|
@ -55,7 +56,7 @@ use tracing::{debug, error, info, trace, warn};
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{udev::drm_mode_from_api_modeline, BackendData},
|
backend::{udev::drm_mode_from_api_modeline, BackendData},
|
||||||
config::ConnectorSavedState,
|
config::ConnectorSavedState,
|
||||||
input::ModifierMask,
|
input::{KeybindData, ModifierMask},
|
||||||
output::{OutputMode, OutputName},
|
output::{OutputMode, OutputName},
|
||||||
render::util::snapshot::capture_snapshots_on_output,
|
render::util::snapshot::capture_snapshots_on_output,
|
||||||
state::{State, WithState},
|
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| {
|
run_server_streaming(&self.sender, move |state, sender| {
|
||||||
|
let keybind_data = KeybindData {
|
||||||
|
sender,
|
||||||
|
group,
|
||||||
|
description,
|
||||||
|
};
|
||||||
|
|
||||||
state
|
state
|
||||||
.pinnacle
|
.pinnacle
|
||||||
.input_state
|
.input_state
|
||||||
.keybinds
|
.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(
|
async fn set_xkb_config(
|
||||||
&self,
|
&self,
|
||||||
request: Request<SetXkbConfigRequest>,
|
request: Request<SetXkbConfigRequest>,
|
||||||
|
|
15
src/input.rs
15
src/input.rs
|
@ -13,6 +13,7 @@ use crate::{
|
||||||
state::{Pinnacle, WithState},
|
state::{Pinnacle, WithState},
|
||||||
window::WindowElement,
|
window::WindowElement,
|
||||||
};
|
};
|
||||||
|
use indexmap::IndexMap;
|
||||||
use pinnacle_api_defs::pinnacle::input::v0alpha1::{
|
use pinnacle_api_defs::pinnacle::input::v0alpha1::{
|
||||||
set_libinput_setting_request::Setting, set_mousebind_request, SetKeybindResponse,
|
set_libinput_setting_request::Setting, set_mousebind_request, SetKeybindResponse,
|
||||||
SetMousebindResponse,
|
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)]
|
#[derive(Default)]
|
||||||
pub struct InputState {
|
pub struct InputState {
|
||||||
// TODO: move all of these to config
|
// TODO: move all of these to config
|
||||||
pub reload_keybind: Option<(ModifierMask, Keysym)>,
|
pub reload_keybind: Option<(ModifierMask, Keysym)>,
|
||||||
pub kill_keybind: Option<(ModifierMask, Keysym)>,
|
pub kill_keybind: Option<(ModifierMask, Keysym)>,
|
||||||
|
|
||||||
pub keybinds:
|
pub keybinds: IndexMap<(ModifierMask, Keysym), KeybindData>,
|
||||||
HashMap<(ModifierMask, Keysym), UnboundedSender<Result<SetKeybindResponse, tonic::Status>>>,
|
|
||||||
pub mousebinds: HashMap<
|
pub mousebinds: HashMap<
|
||||||
(ModifierMask, u32, set_mousebind_request::MouseEdge),
|
(ModifierMask, u32, set_mousebind_request::MouseEdge),
|
||||||
UnboundedSender<Result<SetMousebindResponse, tonic::Status>>,
|
UnboundedSender<Result<SetMousebindResponse, tonic::Status>>,
|
||||||
|
@ -540,7 +547,7 @@ impl State {
|
||||||
let raw_sym = keysym.raw_syms().iter().next();
|
let raw_sym = keysym.raw_syms().iter().next();
|
||||||
let mod_sym = keysym.modified_sym();
|
let mod_sym = keysym.modified_sym();
|
||||||
|
|
||||||
if let Some(sender) = state
|
if let Some(keybind_data) = state
|
||||||
.pinnacle
|
.pinnacle
|
||||||
.input_state
|
.input_state
|
||||||
.keybinds
|
.keybinds
|
||||||
|
@ -557,7 +564,7 @@ impl State {
|
||||||
{
|
{
|
||||||
if state.pinnacle.lock_state.is_unlocked() {
|
if state.pinnacle.lock_state.is_unlocked() {
|
||||||
return FilterResult::Intercept(KeyAction::CallCallback(
|
return FilterResult::Intercept(KeyAction::CallCallback(
|
||||||
sender.clone(),
|
keybind_data.sender.clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue