-
-
Notifications
You must be signed in to change notification settings - Fork 24
Gestures #417
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Gestures #417
Changes from 10 commits
521e3c2
6421ae9
2f63fd4
3492c6c
b4a5f5e
72f7e2a
3a80379
ba548bc
a9185cc
6d5ab7a
324cfd2
f8af4e6
8842b73
5f0ac71
383c7be
7797de1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,6 +33,7 @@ message Bind { | |
| oneof bind { | ||
| Keybind key = 6; | ||
| Mousebind mouse = 7; | ||
| Gesturebind gesture = 8; | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -93,6 +94,50 @@ message MousebindOnPressRequest { | |
| uint32 bind_id = 1; | ||
| } | ||
|
|
||
| // Gesturebinds | ||
|
|
||
| enum GestureDirection { | ||
| DOWN = 0; | ||
| LEFT = 1; | ||
| RIGHT = 2; | ||
| UP = 3; | ||
| DOWN_AND_LEFT = 4; | ||
| DOWN_AND_RIGHT = 5; | ||
| UP_AND_LEFT = 6; | ||
| UP_AND_RIGHT = 7; | ||
| } | ||
|
|
||
| enum GestureType { | ||
| HOLD = 0; | ||
| PINCH = 1; | ||
| SWIPE = 2; | ||
| } | ||
|
rustysec marked this conversation as resolved.
Outdated
|
||
|
|
||
| message Gesturebind { | ||
| GestureDirection direction = 1; | ||
| uint32 fingers = 2; | ||
| GestureType gesture_type = 3; | ||
| } | ||
|
|
||
| message GesturebindStreamRequest { | ||
| uint32 bind_id = 1; | ||
| } | ||
| message GesturebindStreamResponse { | ||
| Edge edge = 1; | ||
| } | ||
|
|
||
| message GesturebindRequest { | ||
| uint32 bind_id = 1; | ||
| } | ||
|
|
||
| message GesturebindOnBeginRequest { | ||
| uint32 bind_id = 1; | ||
| } | ||
|
|
||
| message GesturebindOnFinishRequest { | ||
| uint32 bind_id = 1; | ||
| } | ||
|
|
||
| /////// | ||
|
|
||
| message GetBindInfosRequest {} | ||
|
|
@@ -313,9 +358,13 @@ service InputService { | |
|
|
||
| rpc KeybindStream(KeybindStreamRequest) returns (stream KeybindStreamResponse); | ||
| rpc MousebindStream(MousebindStreamRequest) returns (stream MousebindStreamResponse); | ||
| rpc GesturebindStream(GesturebindStreamRequest) returns (stream GesturebindStreamResponse); | ||
|
|
||
| rpc KeybindOnPress(KeybindOnPressRequest) returns (google.protobuf.Empty); | ||
| rpc MousebindOnPress(MousebindOnPressRequest) returns (google.protobuf.Empty); | ||
| rpc Gesturebind(GesturebindRequest) returns (google.protobuf.Empty); | ||
| rpc GesturebindOnBegin(GesturebindOnBeginRequest) returns (google.protobuf.Empty); | ||
| rpc GesturebindOnFinish(GesturebindOnFinishRequest) returns (google.protobuf.Empty); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What are
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. New RPCs should return a custom message so we don't need to make a breaking change in case we ever need to return data. |
||
|
|
||
| // Xkb | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,7 +10,8 @@ use num_enum::{FromPrimitive, IntoPrimitive}; | |
| use pinnacle_api_defs::pinnacle::input::{ | ||
| self, | ||
| v1::{ | ||
| BindProperties, BindRequest, EnterBindLayerRequest, GetBindInfosRequest, | ||
| BindProperties, BindRequest, EnterBindLayerRequest, GesturebindOnBeginRequest, | ||
| GesturebindOnFinishRequest, GesturebindStreamRequest, GetBindInfosRequest, | ||
| KeybindOnPressRequest, KeybindStreamRequest, MousebindOnPressRequest, | ||
| MousebindStreamRequest, SetBindPropertiesRequest, SetRepeatRateRequest, SetXcursorRequest, | ||
| SetXkbConfigRequest, SetXkbKeymapRequest, SwitchXkbLayoutRequest, | ||
|
|
@@ -30,6 +31,8 @@ pub mod libinput; | |
|
|
||
| pub use xkbcommon::xkb::Keysym; | ||
|
|
||
| pub use pinnacle_api_defs::pinnacle::input::v1::{GestureDirection, GestureType}; | ||
|
|
||
| /// A mouse button. | ||
| #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, FromPrimitive, IntoPrimitive)] | ||
| #[repr(u32)] | ||
|
|
@@ -176,6 +179,17 @@ impl BindLayer { | |
| new_mousebind(mods, button, self).block_on_tokio() | ||
| } | ||
|
|
||
| /// Creates a gesturebind on this layer. | ||
| pub fn gesturebind( | ||
| &self, | ||
| mods: Mod, | ||
| direction: GestureDirection, | ||
| fingers: u32, | ||
| gesture_type: GestureType, | ||
| ) -> Gesturebind { | ||
| new_gesturebind(mods, direction, fingers, gesture_type, self).block_on_tokio() | ||
| } | ||
|
|
||
| /// Enters this layer, causing only its binds to be in effect. | ||
| pub fn enter(&self) { | ||
| Client::input() | ||
|
|
@@ -524,6 +538,145 @@ async fn new_mousebind_stream( | |
| send | ||
| } | ||
|
|
||
| // Gesturebinds | ||
|
|
||
| type GesturebindCallback = (Box<dyn FnMut() + Send + 'static>, Edge); | ||
|
|
||
| /// A Gesturebind. | ||
| pub struct Gesturebind { | ||
| bind_id: u32, | ||
| callback_sender: Option<UnboundedSender<GesturebindCallback>>, | ||
| } | ||
|
|
||
| bind_impl!(Gesturebind); | ||
|
|
||
| /// Creates a gesturebind on the [`DEFAULT`][BindLayer::DEFAULT] bind layer. | ||
| pub fn gesturebind( | ||
| mods: Mod, | ||
| direction: GestureDirection, | ||
| fingers: u32, | ||
| gesture_type: GestureType, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not the biggest fan of how
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should create enums for |
||
| ) -> Gesturebind { | ||
| BindLayer::DEFAULT.gesturebind(mods, direction, fingers, gesture_type) | ||
| } | ||
|
|
||
| impl Gesturebind { | ||
| /// Runs a closure whenever this mousebind is pressed. | ||
| pub fn on_begin<F: FnMut() + Send + 'static>(&mut self, on_begin: F) -> &mut Self { | ||
| let sender = self | ||
| .callback_sender | ||
| .get_or_insert_with(|| new_gesturebind_stream(self.bind_id).block_on_tokio()); | ||
| let _ = sender.send((Box::new(on_begin), Edge::Press)); | ||
|
|
||
| Client::input() | ||
| .gesturebind_on_begin(GesturebindOnBeginRequest { | ||
| bind_id: self.bind_id, | ||
| }) | ||
| .block_on_tokio() | ||
| .unwrap(); | ||
|
|
||
| self | ||
| } | ||
|
|
||
| /// Runs a closure whenever this mousebind is released. | ||
| pub fn on_finish<F: FnMut() + Send + 'static>(&mut self, on_finish: F) -> &mut Self { | ||
| let sender = self | ||
| .callback_sender | ||
| .get_or_insert_with(|| new_gesturebind_stream(self.bind_id).block_on_tokio()); | ||
| let _ = sender.send((Box::new(on_finish), Edge::Release)); | ||
|
|
||
| Client::input() | ||
| .gesturebind_on_finish(GesturebindOnFinishRequest { | ||
| bind_id: self.bind_id, | ||
| }) | ||
| .block_on_tokio() | ||
| .unwrap(); | ||
|
Comment on lines
+649
to
+654
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| self | ||
| } | ||
| } | ||
|
|
||
| async fn new_gesturebind( | ||
| mods: Mod, | ||
| direction: GestureDirection, | ||
| fingers: u32, | ||
| gesture_type: GestureType, | ||
| layer: &BindLayer, | ||
| ) -> Gesturebind { | ||
| let ignore_mods = mods.api_ignore_mods(); | ||
| let mods = mods.api_mods(); | ||
|
|
||
| let bind_id = Client::input() | ||
| .bind(BindRequest { | ||
| bind: Some(input::v1::Bind { | ||
| mods: mods.into_iter().map(|m| m.into()).collect(), | ||
| ignore_mods: ignore_mods.into_iter().map(|m| m.into()).collect(), | ||
| layer_name: layer.name.clone(), | ||
| properties: Some(BindProperties::default()), | ||
| bind: Some(input::v1::bind::Bind::Gesture(input::v1::Gesturebind { | ||
| direction: direction.into(), | ||
| fingers, | ||
| gesture_type: gesture_type.into(), | ||
| })), | ||
| }), | ||
| }) | ||
| .await | ||
| .unwrap() | ||
| .into_inner() | ||
| .bind_id; | ||
|
|
||
| Gesturebind { | ||
| bind_id, | ||
| callback_sender: None, | ||
| } | ||
| } | ||
|
|
||
| async fn new_gesturebind_stream( | ||
| bind_id: u32, | ||
| ) -> UnboundedSender<(Box<dyn FnMut() + Send + 'static>, Edge)> { | ||
| let mut from_server = Client::input() | ||
| .gesturebind_stream(GesturebindStreamRequest { bind_id }) | ||
| .await | ||
| .unwrap() | ||
| .into_inner(); | ||
|
|
||
| let (send, mut recv) = unbounded_channel(); | ||
|
|
||
| tokio::spawn(async move { | ||
| let mut on_presses = Vec::<Box<dyn FnMut() + Send + 'static>>::new(); | ||
| let mut on_releases = Vec::<Box<dyn FnMut() + Send + 'static>>::new(); | ||
|
|
||
| loop { | ||
| tokio::select! { | ||
| Some(Ok(response)) = from_server.next() => { | ||
| match response.edge() { | ||
| input::v1::Edge::Unspecified => (), | ||
| input::v1::Edge::Press => { | ||
| for on_press in on_presses.iter_mut() { | ||
| on_press(); | ||
| } | ||
| } | ||
| input::v1::Edge::Release => { | ||
| for on_release in on_releases.iter_mut() { | ||
| on_release(); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Some((cb, edge)) = recv.recv() => { | ||
| match edge { | ||
| Edge::Press => on_presses.push(cb), | ||
| Edge::Release => on_releases.push(cb), | ||
| } | ||
| } | ||
| else => break, | ||
| } | ||
| } | ||
| }); | ||
|
|
||
| send | ||
| } | ||
|
|
||
| /// A struct that lets you define xkeyboard config options. | ||
| /// | ||
| /// See `xkeyboard-config(7)` for more information. | ||
|
|
@@ -699,6 +852,13 @@ pub enum BindInfoKind { | |
| /// Which mouse button this bind uses. | ||
| button: MouseButton, | ||
| }, | ||
| /// This is a gesturebind. | ||
| Gesture { | ||
| /// Direction of the gesture. | ||
| direction: GestureDirection, | ||
| /// Fingers used in the gesture. | ||
| fingers: u32, | ||
| }, | ||
| } | ||
|
|
||
| /// Sets the keyboard's repeat rate. | ||
|
|
@@ -845,6 +1005,11 @@ pub fn bind_infos() -> impl Iterator<Item = BindInfo> { | |
| input::v1::bind::Bind::Mouse(mousebind) => BindInfoKind::Mouse { | ||
| button: MouseButton::from(mousebind.button), | ||
| }, | ||
| input::v1::bind::Bind::Gesture(gesturebind) => BindInfoKind::Gesture { | ||
| direction: GestureDirection::try_from(gesturebind.direction) | ||
| .expect("invalid gesture direction value"), | ||
| fingers: gesturebind.fingers, | ||
| }, | ||
| }; | ||
|
|
||
| let layer = BindLayer { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.