From 0bd64ee3aa58d24d68091ddeea1fcdcba77c2857 Mon Sep 17 00:00:00 2001 From: Ottatop Date: Sat, 16 Mar 2024 21:03:01 -0500 Subject: [PATCH] Add Rust default config comments, batch tag calls --- api/rust/examples/default_config/main.rs | 125 +++++++++++++++++------ api/rust/src/layout.rs | 2 +- 2 files changed, 97 insertions(+), 30 deletions(-) diff --git a/api/rust/examples/default_config/main.rs b/api/rust/examples/default_config/main.rs index 78fba94..9793e63 100644 --- a/api/rust/examples/default_config/main.rs +++ b/api/rust/examples/default_config/main.rs @@ -1,15 +1,21 @@ use pinnacle_api::layout::{ - CornerLayout, CyclingLayoutManager, DwindleLayout, FairLayout, MasterStackLayout, SpiralLayout, + CornerLayout, CornerLocation, CyclingLayoutManager, DwindleLayout, FairLayout, MasterSide, + MasterStackLayout, SpiralLayout, }; use pinnacle_api::signal::WindowSignal; +use pinnacle_api::util::{Axis, Batch}; use pinnacle_api::xkbcommon::xkb::Keysym; use pinnacle_api::{ input::{Mod, MouseButton, MouseEdge}, ApiModules, }; +// Pinnacle needs to perform some setup before and after your config. +// The `#[pinnacle_api::config(modules)]` attribute does so and +// will bind all the config structs to the provided identifier. #[pinnacle_api::config(modules)] async fn main() { + // Deconstruct to get all the APIs. let ApiModules { pinnacle, process, @@ -24,7 +30,9 @@ async fn main() { let terminal = "alacritty"; - // Mousebinds + //------------------------ + // Mousebinds | + //------------------------ // `mod_key + left click` starts moving a window input.mousebind([mod_key], MouseButton::Left, MouseEdge::Press, || { @@ -36,7 +44,9 @@ async fn main() { window.begin_resize(MouseButton::Right); }); - // Keybinds + //------------------------ + // Keybinds | + //------------------------ // `mod_key + alt + q` quits Pinnacle input.keybind([mod_key, Mod::Alt], 'q', || { @@ -76,25 +86,82 @@ async fn main() { } }); - // Window rules - // + //------------------------ + // Window rules | + //------------------------ // You can define window rules to get windows to open with desired properties. // See `pinnacle_api::window::rules` in the docs for more information. - // Layouts + //------------------------ + // Layouts | + //------------------------ - let master_stack = Box::::default(); - let dwindle = Box::::default(); - let spiral = Box::::default(); - let corner = Box::::default(); - let fair = Box::::default(); + // Pinnacle does not manage layouts compositor-side. + // Instead, it delegates computation of layouts to your config, + // which provides an interface to calculate the size and location of + // windows that the compositor will use to position windows. + // + // If you're familiar with River's layout generators, you'll understand the system here + // a bit better. + // + // The Rust API provides two layout system abstractions: + // 1. Layout managers, and + // 2. Layout generators. + // + // ### Layout Managers ### + // A layout manager is a struct that implements the `LayoutManager` trait. + // A manager is meant to keep track of and choose various layout generators + // across your usage of the compositor. + // + // ### Layout generators ### + // A layout generator is a struct that implements the `LayoutGenerator` trait. + // It takes in layout arguments and computes a vector of geometries that will + // determine the size and position of windows being laid out. + // + // There is one built-in layout manager and five built-in layout generators, + // as shown below. + // + // Additionally, this system is designed to be user-extensible; + // you are free to create your own layout managers and generators for + // maximum customizability! Docs for doing so are in the works, so sit tight. + // Create a `CyclingLayoutManager` that can cycle between layouts on different tags. + // + // It takes in some layout generators that need to be boxed and dyn-coerced. let layout_requester = layout.set_manager(CyclingLayoutManager::new([ - master_stack as _, - dwindle as _, - spiral as _, - corner as _, - fair as _, + Box::::default() as _, + Box::new(MasterStackLayout { + master_side: MasterSide::Right, + ..Default::default() + }) as _, + Box::new(MasterStackLayout { + master_side: MasterSide::Top, + ..Default::default() + }) as _, + Box::new(MasterStackLayout { + master_side: MasterSide::Bottom, + ..Default::default() + }) as _, + Box::::default() as _, + Box::::default() as _, + Box::::default() as _, + Box::new(CornerLayout { + corner_loc: CornerLocation::TopRight, + ..Default::default() + }) as _, + Box::new(CornerLayout { + corner_loc: CornerLocation::BottomLeft, + ..Default::default() + }) as _, + Box::new(CornerLayout { + corner_loc: CornerLocation::BottomRight, + ..Default::default() + }) as _, + Box::::default() as _, + Box::new(FairLayout { + axis: Axis::Horizontal, + ..Default::default() + }) as _, ])); let mut layout_requester_clone = layout_requester.clone(); @@ -102,11 +169,10 @@ async fn main() { // `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() - .into_iter() - .find(|tg| tg.active().unwrap_or(false)) - else { + let Some(first_active_tag) = focused_op.tags().batch_find( + |tg| Box::pin(tg.active_async()), + |active| active == &Some(true), + ) else { return; }; @@ -117,11 +183,10 @@ async fn main() { // `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() - .into_iter() - .find(|tg| tg.active().unwrap_or(false)) - else { + let Some(first_active_tag) = focused_op.tags().batch_find( + |tg| Box::pin(tg.active_async()), + |active| active == &Some(true), + ) else { return; }; @@ -129,7 +194,9 @@ async fn main() { layout_requester_clone.request_layout_on_output(&focused_op); }); - // Tags + //------------------------ + // Tags | + //------------------------ let tag_names = ["1", "2", "3", "4", "5"]; @@ -141,8 +208,6 @@ async fn main() { tags.first().unwrap().set_active(true); }); - process.spawn_once([terminal]); - for tag_name in tag_names { // `mod_key + 1-5` switches to tag "1" to "5" input.keybind([mod_key], tag_name, move || { @@ -181,4 +246,6 @@ async fn main() { window.connect_signal(WindowSignal::PointerEnter(Box::new(|win| { win.set_focused(true); }))); + + process.spawn_once([terminal]); } diff --git a/api/rust/src/layout.rs b/api/rust/src/layout.rs index 407a836..be88ef3 100644 --- a/api/rust/src/layout.rs +++ b/api/rust/src/layout.rs @@ -29,7 +29,7 @@ use crate::{ OUTPUT, TAG, WINDOW, }; -/// A struct that allows you to add and remove tags and get [`TagHandle`]s. +/// A struct that allows you to manage layouts. #[derive(Clone, Debug)] pub struct Layout { layout_client: LayoutServiceClient,