mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2024-12-25 09:59:21 +01:00
Get mousebinds to work
This commit is contained in:
parent
2a342c8272
commit
f7068a1146
5 changed files with 239 additions and 20 deletions
115
api/lua_grpc/examples/test/init.lua
Normal file
115
api/lua_grpc/examples/test/init.lua
Normal file
|
@ -0,0 +1,115 @@
|
|||
require("pinnacle").setup(function(Pinnacle)
|
||||
local Input = Pinnacle.input
|
||||
local Process = Pinnacle.process
|
||||
local Output = Pinnacle.output
|
||||
local Tag = Pinnacle.tag
|
||||
local Window = Pinnacle.window
|
||||
|
||||
local key = Input.key
|
||||
|
||||
---@type Modifier
|
||||
local mod_key = "ctrl"
|
||||
|
||||
local terminal = "alacritty"
|
||||
|
||||
Input:mousebind({ mod_key }, "btn_left", "press", function()
|
||||
Window:begin_move("btn_left")
|
||||
end)
|
||||
|
||||
Input:mousebind({ mod_key }, "btn_right", "press", function()
|
||||
Window:begin_resize("btn_right")
|
||||
end)
|
||||
|
||||
------
|
||||
|
||||
Input:keybind({ mod_key, "alt" }, "q", function()
|
||||
Pinnacle:quit()
|
||||
end)
|
||||
|
||||
Input:keybind({ mod_key, "alt" }, "c", function()
|
||||
local focused = Window:get_focused()
|
||||
if focused then
|
||||
focused:close()
|
||||
end
|
||||
end)
|
||||
|
||||
Input:keybind({ mod_key }, key.Return, function()
|
||||
Process:spawn(terminal)
|
||||
end)
|
||||
|
||||
Input:keybind({ mod_key, "alt" }, key.space, function()
|
||||
local focused = Window:get_focused()
|
||||
if focused then
|
||||
focused:toggle_floating()
|
||||
end
|
||||
end)
|
||||
|
||||
Input:keybind({ mod_key }, "f", function()
|
||||
local focused = Window:get_focused()
|
||||
if focused then
|
||||
focused:toggle_fullscreen()
|
||||
end
|
||||
end)
|
||||
|
||||
Input:keybind({ mod_key }, "m", function()
|
||||
local focused = Window:get_focused()
|
||||
if focused then
|
||||
focused:toggle_maximized()
|
||||
end
|
||||
end)
|
||||
|
||||
local tag_names = { "1", "2", "3", "4", "5" }
|
||||
|
||||
Output:connect_for_all(function(op)
|
||||
local tags = Tag:add(op, tag_names)
|
||||
tags[1]:set_active(true)
|
||||
end)
|
||||
|
||||
Process:spawn_once("foot")
|
||||
|
||||
local layout_cycler = Tag:new_layout_cycler({
|
||||
"master_stack",
|
||||
"dwindle",
|
||||
"spiral",
|
||||
"corner_top_left",
|
||||
"corner_top_right",
|
||||
"corner_bottom_left",
|
||||
"corner_bottom_right",
|
||||
})
|
||||
|
||||
Input:keybind({ mod_key }, key.space, function()
|
||||
local focused_op = Output:get_focused()
|
||||
if focused_op then
|
||||
layout_cycler.next(focused_op)
|
||||
end
|
||||
end)
|
||||
|
||||
Input:keybind({ mod_key, "shift" }, key.space, function()
|
||||
local focused_op = Output:get_focused()
|
||||
if focused_op then
|
||||
layout_cycler.prev(focused_op)
|
||||
end
|
||||
end)
|
||||
|
||||
for _, tag_name in ipairs(tag_names) do
|
||||
-- nil-safety: tags are guaranteed to be on the outputs due to connect_for_all above
|
||||
Input:keybind({ mod_key }, tag_name, function()
|
||||
Tag:get(tag_name):switch_to()
|
||||
end)
|
||||
Input:keybind({ mod_key, "shift" }, tag_name, function()
|
||||
Tag:get(tag_name):toggle_active()
|
||||
end)
|
||||
Input:keybind({ mod_key, "alt" }, tag_name, function()
|
||||
local focused = Window:get_focused()
|
||||
if focused then
|
||||
focused:move_to_tag(Tag:get(tag_name) --[[@as TagHandle]])
|
||||
end
|
||||
end)
|
||||
Input:keybind({ mod_key, "shift", "alt" }, tag_name, function()
|
||||
local focused = Window:get_focused()
|
||||
if focused then
|
||||
focused:toggle_tag(Tag:get(tag_name) --[[@as TagHandle]])
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
51
api/lua_grpc/examples/test/metaconfig.toml
Normal file
51
api/lua_grpc/examples/test/metaconfig.toml
Normal file
|
@ -0,0 +1,51 @@
|
|||
# This metaconfig.toml file dictates what config Pinnacle will run.
|
||||
#
|
||||
# When running Pinnacle, the compositor will look in the following directories for a metaconfig.toml file,
|
||||
# in order from top to bottom:
|
||||
# $PINNACLE_CONFIG_DIR
|
||||
# $XDG_CONFIG_HOME/pinnacle/
|
||||
# ~/.config/pinnacle/
|
||||
#
|
||||
# When Pinnacle finds a metaconfig.toml file, it will execute the command provided to `command`.
|
||||
# For now, the only thing that should be here is `lua` with a path to the main config file.
|
||||
# In the future, there will be a Rust API that can be run using `cargo run`.
|
||||
#
|
||||
# Because configuration is done using an external process, if it ever crashes, you lose all of your keybinds.
|
||||
# In order prevent you from getting stuck in the compositor, you must define keybinds to reload your config
|
||||
# and kill Pinnacle.
|
||||
#
|
||||
# More details on each setting can be found below.
|
||||
|
||||
# The command Pinnacle will run on startup and when you reload your config.
|
||||
# Paths are relative to the directory the metaconfig.toml file is in.
|
||||
# This must be an array.
|
||||
command = ["lua", "init.lua"]
|
||||
|
||||
### Keybinds ###
|
||||
# Each keybind takes in a table with two fields: `modifiers` and `key`.
|
||||
# - `modifiers` can be one of "Ctrl", "Alt", "Shift", or "Super".
|
||||
# - `key` can be a string of any lowercase letter, number,
|
||||
# "numN" where N is a number for numpad keys, or "esc"/"escape".
|
||||
# Support for any xkbcommon key is planned for a future update.
|
||||
|
||||
# The keybind that will reload your config.
|
||||
reload_keybind = { modifiers = ["Ctrl", "Alt"], key = "r" }
|
||||
# The keybind that will kill Pinnacle.
|
||||
kill_keybind = { modifiers = ["Ctrl", "Alt", "Shift"], key = "escape" }
|
||||
|
||||
### Socket directory ###
|
||||
# Pinnacle will open a Unix socket at `$XDG_RUNTIME_DIR` by default, falling back to `/tmp` if it doesn't exist.
|
||||
# If you want/need to change this, use the `socket_dir` setting set to the directory of your choosing.
|
||||
#
|
||||
# socket_dir = "/your/dir/here/"
|
||||
|
||||
### Environment Variables ###
|
||||
# You may need to specify to Lua where Pinnacle's Lua API library is.
|
||||
# This is currently done using the `envs` table, with keys as the name of the environment variable and
|
||||
# the value as the variable value. This supports $var expansion, and paths are relative to this metaconfig.toml file.
|
||||
#
|
||||
# Pinnacle will run your config with the additional PINNACLE_DIR environment variable.
|
||||
#
|
||||
# Here, LUA_PATH and LUA_CPATH are used to tell Lua the path to the library.
|
||||
[envs]
|
||||
LUA_PATH = "$PINNACLE_LUA_GRPC_DIR/?.lua;$PINNACLE_LUA_GRPC_DIR/?/init.lua;$LUA_PATH"
|
|
@ -4,6 +4,7 @@ local h2_connection = require("http.h2_connection")
|
|||
local pb = require("pb")
|
||||
local inspect = require("inspect")
|
||||
|
||||
---@nodoc
|
||||
---Create appropriate headers for a gRPC request.
|
||||
---@param service string The desired service
|
||||
---@param method string The desired method within the service
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
use std::{ffi::OsString, num::NonZeroU32, pin::Pin, process::Stdio};
|
||||
|
||||
use pinnacle_api_defs::pinnacle::{
|
||||
input::libinput::v0alpha1::set_libinput_setting_request::{
|
||||
AccelProfile, ClickMethod, ScrollMethod, TapButtonMap,
|
||||
input::{
|
||||
libinput::v0alpha1::set_libinput_setting_request::{
|
||||
AccelProfile, ClickMethod, ScrollMethod, TapButtonMap,
|
||||
},
|
||||
v0alpha1::set_mousebind_request::MouseEdge,
|
||||
},
|
||||
output::v0alpha1::{ConnectForAllRequest, ConnectForAllResponse, SetLocationRequest},
|
||||
process::v0alpha1::SetEnvRequest,
|
||||
|
@ -184,6 +187,12 @@ impl pinnacle_api_defs::pinnacle::input::v0alpha1::input_service_server::InputSe
|
|||
.button
|
||||
.ok_or_else(|| Status::invalid_argument("no key specified"))?;
|
||||
|
||||
let edge = request.edge();
|
||||
|
||||
if let MouseEdge::Unspecified = edge {
|
||||
return Err(Status::invalid_argument("press or release not specified"));
|
||||
}
|
||||
|
||||
let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
|
||||
|
||||
self.sender
|
||||
|
@ -191,7 +200,7 @@ impl pinnacle_api_defs::pinnacle::input::v0alpha1::input_service_server::InputSe
|
|||
state
|
||||
.input_state
|
||||
.grpc_mousebinds
|
||||
.insert((modifiers, button), sender);
|
||||
.insert((modifiers, button, edge), sender);
|
||||
}))
|
||||
.map_err(|_| Status::internal("internal state was not running"))?;
|
||||
|
||||
|
|
77
src/input.rs
77
src/input.rs
|
@ -12,7 +12,7 @@ use crate::{
|
|||
};
|
||||
use pinnacle_api_defs::pinnacle::input::{
|
||||
libinput::v0alpha1::set_libinput_setting_request::Setting,
|
||||
v0alpha1::{SetKeybindResponse, SetMousebindResponse},
|
||||
v0alpha1::{set_mousebind_request, SetKeybindResponse, SetMousebindResponse},
|
||||
};
|
||||
use smithay::{
|
||||
backend::input::{
|
||||
|
@ -21,7 +21,7 @@ use smithay::{
|
|||
},
|
||||
desktop::{layer_map_for_output, space::SpaceElement},
|
||||
input::{
|
||||
keyboard::{keysyms, FilterResult},
|
||||
keyboard::{keysyms, FilterResult, ModifiersState},
|
||||
pointer::{AxisFrame, ButtonEvent, MotionEvent, RelativeMotionEvent},
|
||||
},
|
||||
reexports::input::{self, Led},
|
||||
|
@ -45,6 +45,44 @@ bitflags::bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<ModifiersState> for ModifierMask {
|
||||
fn from(modifiers: ModifiersState) -> Self {
|
||||
let mut mask = ModifierMask::empty();
|
||||
if modifiers.alt {
|
||||
mask |= ModifierMask::ALT;
|
||||
}
|
||||
if modifiers.shift {
|
||||
mask |= ModifierMask::SHIFT;
|
||||
}
|
||||
if modifiers.ctrl {
|
||||
mask |= ModifierMask::CTRL;
|
||||
}
|
||||
if modifiers.logo {
|
||||
mask |= ModifierMask::SUPER;
|
||||
}
|
||||
mask
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ModifiersState> for ModifierMask {
|
||||
fn from(modifiers: &ModifiersState) -> Self {
|
||||
let mut mask = ModifierMask::empty();
|
||||
if modifiers.alt {
|
||||
mask |= ModifierMask::ALT;
|
||||
}
|
||||
if modifiers.shift {
|
||||
mask |= ModifierMask::SHIFT;
|
||||
}
|
||||
if modifiers.ctrl {
|
||||
mask |= ModifierMask::CTRL;
|
||||
}
|
||||
if modifiers.logo {
|
||||
mask |= ModifierMask::SUPER;
|
||||
}
|
||||
mask
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct InputState {
|
||||
/// A hashmap of modifier keys and keycodes to callback IDs
|
||||
|
@ -60,8 +98,10 @@ pub struct InputState {
|
|||
|
||||
pub grpc_keybinds:
|
||||
HashMap<(ModifierMask, Keysym), UnboundedSender<Result<SetKeybindResponse, tonic::Status>>>,
|
||||
pub grpc_mousebinds:
|
||||
HashMap<(ModifierMask, u32), UnboundedSender<Result<SetMousebindResponse, tonic::Status>>>,
|
||||
pub grpc_mousebinds: HashMap<
|
||||
(ModifierMask, u32, set_mousebind_request::MouseEdge),
|
||||
UnboundedSender<Result<SetMousebindResponse, tonic::Status>>,
|
||||
>,
|
||||
pub grpc_libinput_settings:
|
||||
HashMap<Discriminant<Setting>, Box<dyn Fn(&mut input::Device) + Send>>,
|
||||
}
|
||||
|
@ -231,19 +271,7 @@ impl State {
|
|||
}
|
||||
let modifier_mask = crate::api::msg::ModifierMask::from(modifier_mask);
|
||||
|
||||
let mut grpc_modifiers = ModifierMask::empty();
|
||||
if modifiers.alt {
|
||||
grpc_modifiers |= ModifierMask::ALT;
|
||||
}
|
||||
if modifiers.shift {
|
||||
grpc_modifiers |= ModifierMask::SHIFT;
|
||||
}
|
||||
if modifiers.ctrl {
|
||||
grpc_modifiers |= ModifierMask::CTRL;
|
||||
}
|
||||
if modifiers.logo {
|
||||
grpc_modifiers |= ModifierMask::SUPER;
|
||||
}
|
||||
let grpc_modifiers = ModifierMask::from(modifiers);
|
||||
|
||||
let raw_sym = keysym.raw_syms().iter().next();
|
||||
let mod_sym = keysym.modified_sym();
|
||||
|
@ -344,6 +372,8 @@ impl State {
|
|||
};
|
||||
let modifier_mask = crate::api::msg::ModifierMask::from(keyboard.modifier_state());
|
||||
|
||||
let grpc_modifier_mask = ModifierMask::from(keyboard.modifier_state());
|
||||
|
||||
// If any mousebinds are detected, call the config's callback and return.
|
||||
if let Some(&callback_id) =
|
||||
self.input_state
|
||||
|
@ -363,6 +393,19 @@ impl State {
|
|||
return;
|
||||
}
|
||||
|
||||
let grpc_mouse_edge = match button_state {
|
||||
ButtonState::Released => set_mousebind_request::MouseEdge::Release,
|
||||
ButtonState::Pressed => set_mousebind_request::MouseEdge::Press,
|
||||
};
|
||||
|
||||
if let Some(stream) =
|
||||
self.input_state
|
||||
.grpc_mousebinds
|
||||
.get(&(grpc_modifier_mask, button, grpc_mouse_edge))
|
||||
{
|
||||
let _ = stream.send(Ok(SetMousebindResponse {}));
|
||||
}
|
||||
|
||||
// If the button was clicked, focus on the window below if exists, else
|
||||
// unfocus on windows.
|
||||
if button_state == ButtonState::Pressed {
|
||||
|
|
Loading…
Reference in a new issue