Skip to content
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

Rewrite Rust API #131

Merged
merged 27 commits into from
Jan 23, 2024
Merged
Changes from 4 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion api/rust_grpc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -7,10 +7,13 @@ edition = "2021"
pinnacle-api-defs = { path = "../../pinnacle-api-defs" }
pinnacle-api-macros = { path = "./pinnacle-api-macros" }
tokio = { version = "1.35.1", features = ["macros", "rt-multi-thread", "net"] }
tokio-stream = { version = "0.1.14", features = ["net"] }
# tokio-stream = { version = "0.1.14", features = ["net"] }
async-net = "2.0.0"
async-compat = "0.2.3"
tonic = "0.10.2"
tower = { version = "0.4.13", features = ["util"] }
futures = "0.3.30"
# futures-lite = "2.2.0"
num_enum = "0.7.2"
xkbcommon = "0.7.0"

18 changes: 0 additions & 18 deletions api/rust_grpc/examples/default_config.rs

This file was deleted.

103 changes: 103 additions & 0 deletions api/rust_grpc/examples/default_config/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use pinnacle_api::{
input::{Mod, MouseButton, MouseEdge},
ApiModules,
};
use xkbcommon::xkb::keysyms;

#[pinnacle_api::config(modules)]
#[tokio::main]
async fn main() {
let ApiModules {
pinnacle,
process,
window,
input,
output,
tag,
} = modules;

let mod_key = Mod::Ctrl;

input.mousebind([mod_key], MouseButton::Left, MouseEdge::Press, || {
window.begin_move(MouseButton::Left);
});

input.mousebind([mod_key], MouseButton::Right, MouseEdge::Press, || {
window.begin_resize(MouseButton::Right);
});

// Keybinds

input.keybind([mod_key, Mod::Alt], 'q', || {
pinnacle.quit();
});

input.keybind([mod_key, Mod::Alt], 'c', || {
if let Some(window) = window.get_focused() {
window.close();
}
});

input.keybind([mod_key], keysyms::KEY_Return, || {
process.spawn(["alacritty"]);
});

input.keybind([mod_key, Mod::Alt], keysyms::KEY_space, || {
if let Some(window) = window.get_focused() {
window.toggle_floating();
}
});

input.keybind([mod_key], 'f', || {
if let Some(window) = window.get_focused() {
window.toggle_fullscreen();
}
});

input.keybind([mod_key], 'm', || {
if let Some(window) = window.get_focused() {
window.toggle_maximized();
}
});

// Tags

let tag_names = ["1", "2", "3", "4", "5"];

output.connect_for_all(move |op| {
let mut tags = tag.add(&op, tag_names);
tags.next().unwrap().set_active(true);
});

process.spawn_once(["alacritty"]);

for tag_name in tag_names {
input.keybind([mod_key], tag_name, move || {
if let Some(tg) = tag.get(tag_name, None) {
tg.switch_to();
}
});

input.keybind([mod_key, Mod::Shift], tag_name, move || {
if let Some(tg) = tag.get(tag_name, None) {
tg.toggle_active();
}
});

input.keybind([mod_key, Mod::Alt], tag_name, move || {
if let Some(tg) = tag.get(tag_name, None) {
if let Some(win) = window.get_focused() {
win.move_to_tag(&tg);
}
}
});

input.keybind([mod_key, Mod::Shift, Mod::Alt], tag_name, move || {
if let Some(tg) = tag.get(tag_name, None) {
if let Some(win) = window.get_focused() {
win.toggle_tag(&tg);
}
}
});
}
}
46 changes: 46 additions & 0 deletions api/rust_grpc/examples/default_config/metaconfig.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# 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`.
# To use a Rust config, this should be changed to something like ["cargo", "run"].
#
# Because configuration is done using an external process, if it ever crashes, you lose all of your keybinds.
# The compositor will load the default config if that happens, but in the event that you don't have
# the necessary dependencies for it to run, you may get softlocked.
# 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 = ["cargo", "run", "--example", "default_config"]

### 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 ###
# If you need to spawn your config with any environment variables, list them here.
[envs]
# key = "value"
4 changes: 2 additions & 2 deletions api/rust_grpc/pinnacle-api-macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -20,11 +20,11 @@ pub fn config(
quote! {
#(#attrs)*
#vis #sig {
let (#module_ident, __fut_receiver) = ::pinnacle_api::create_modules().unwrap();
let (#module_ident, __fut_receiver) = ::pinnacle_api::connect().await.unwrap();

#(#stmts)*

::pinnacle_api::listen(__fut_receiver);
::pinnacle_api::listen(__fut_receiver).await;
}
}
.into()
101 changes: 58 additions & 43 deletions api/rust_grpc/src/input.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use futures::executor::block_on;
use futures::{
channel::mpsc::UnboundedSender, executor::block_on, future::BoxFuture, FutureExt, StreamExt,
};
use num_enum::TryFromPrimitive;
use pinnacle_api_defs::pinnacle::input::{
self,
@@ -8,14 +10,11 @@ use pinnacle_api_defs::pinnacle::input::{
SetKeybindRequest, SetLibinputSettingRequest, SetMousebindRequest, SetRepeatRateRequest,
},
};
use tokio_stream::StreamExt;
use tonic::transport::Channel;
use xkbcommon::xkb::Keysym;

pub use pinnacle_api_defs::pinnacle::input::v0alpha1::SetXkbConfigRequest as XkbConfig;

use crate::FutSender;

use self::libinput::LibinputSetting;
pub mod libinput;

@@ -48,13 +47,21 @@ pub enum MouseEdge {

#[derive(Debug, Clone)]
pub struct Input {
client: InputServiceClient<Channel>,
fut_sender: FutSender,
// client: InputServiceClient<Channel>,
channel: Channel,
fut_sender: UnboundedSender<BoxFuture<'static, ()>>,
}

impl Input {
pub fn new(client: InputServiceClient<Channel>, fut_sender: FutSender) -> Self {
Self { client, fut_sender }
pub fn new(channel: Channel, fut_sender: UnboundedSender<BoxFuture<'static, ()>>) -> Self {
Self {
channel,
fut_sender,
}
}

fn create_input_client(&self) -> InputServiceClient<Channel> {
InputServiceClient::new(self.channel.clone())
}

pub fn keybind(
@@ -63,27 +70,30 @@ impl Input {
key: impl Key + Send + 'static,
mut action: impl FnMut() + Send + 'static,
) {
let mut client = self.client.clone();
let mut client = self.create_input_client();

let modifiers = mods.into_iter().map(|modif| modif as i32).collect();

self.fut_sender
.send(Box::pin(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();
.unbounded_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();
}
}
}))
.boxed(),
)
.unwrap();
}

@@ -94,35 +104,40 @@ impl Input {
edge: MouseEdge,
mut action: impl FnMut() + 'static + Send,
) {
let mut client = self.client.clone();
let mut client = self.create_input_client();

let modifiers = mods.into_iter().map(|modif| modif as i32).collect();

tokio::spawn(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();
}
});
self.fut_sender
.unbounded_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();
}
}
.boxed(),
)
.unwrap();
}

pub fn set_xkb_config(&self, xkb_config: XkbConfig) {
let mut client = self.client.clone();
let mut client = self.create_input_client();

block_on(client.set_xkb_config(xkb_config)).unwrap();
}

pub fn set_repeat_rate(&self, rate: i32, delay: i32) {
let mut client = self.client.clone();
let mut client = self.create_input_client();

block_on(client.set_repeat_rate(SetRepeatRateRequest {
rate: Some(rate),
@@ -132,7 +147,7 @@ impl Input {
}

pub fn set_libinput_setting(&self, setting: LibinputSetting) {
let mut client = self.client.clone();
let mut client = self.create_input_client();

let setting = match setting {
LibinputSetting::AccelProfile(profile) => Setting::AccelProfile(profile as i32),
Loading