diff --git a/api/rust/src/lib.rs b/api/rust/src/lib.rs index c0205fe..d6a2814 100644 --- a/api/rust/src/lib.rs +++ b/api/rust/src/lib.rs @@ -15,6 +15,7 @@ pub use input::MouseButton; pub use input::MouseEdge; use output::Output; use tag::Tag; +use window::rules::WindowRules; use window::Window; pub use xkbcommon::xkb::keysyms; pub use xkbcommon::xkb::Keysym; @@ -53,7 +54,7 @@ pub fn setup(config_func: impl FnOnce(Pinnacle)) -> anyhow::Result<()> { let pinnacle = Pinnacle { process: Process, input: Input, - window: Window, + window: Window { rules: WindowRules }, output: Output, tag: Tag, }; diff --git a/api/rust/src/msg.rs b/api/rust/src/msg.rs index 5508f68..754645a 100644 --- a/api/rust/src/msg.rs +++ b/api/rust/src/msg.rs @@ -10,6 +10,48 @@ use crate::{ #[derive(Debug, Hash, PartialEq, Eq, serde::Serialize, serde::Deserialize, Clone, Copy)] pub struct CallbackId(pub u32); +#[derive(Default, Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct WindowRuleCondition { + /// This condition is met when any of the conditions provided is met. + #[serde(default)] + pub cond_any: Option>, + /// This condition is met when all of the conditions provided are met. + #[serde(default)] + pub cond_all: Option>, + /// This condition is met when the class matches. + #[serde(default)] + pub class: Option>, + /// This condition is met when the title matches. + #[serde(default)] + pub title: Option>, + /// This condition is met when the tag matches. + #[serde(default)] + pub tag: Option>, +} + +#[derive(Default, Debug, Clone, PartialEq, Eq, serde::Serialize)] +pub struct WindowRule { + /// Set the output the window will open on. + #[serde(default)] + pub output: Option, + /// Set the tags the output will have on open. + #[serde(default)] + pub tags: Option>, + /// Set the window to floating or tiled on open. + #[serde(default)] + pub floating_or_tiled: Option, + /// Set the window to fullscreen, maximized, or force it to neither. + #[serde(default)] + pub fullscreen_or_maximized: Option, + /// Set the window's initial size. + #[serde(default)] + pub size: Option<(NonZeroU32, NonZeroU32)>, + /// Set the window's initial location. If the window is tiled, it will snap to this position + /// when set to floating. + #[serde(default)] + pub location: Option<(i32, i32)>, +} + #[derive(Debug, PartialEq, Copy, Clone, serde::Serialize)] pub enum AccelProfile { Flat, @@ -58,48 +100,6 @@ pub enum LibinputSetting { #[derive(Debug, Hash, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct RequestId(pub u32); -#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] -pub struct WindowRuleCondition { - /// This condition is met when any of the conditions provided is met. - #[serde(default)] - cond_any: Option>, - /// This condition is met when all of the conditions provided are met. - #[serde(default)] - cond_all: Option>, - /// This condition is met when the class matches. - #[serde(default)] - class: Option>, - /// This condition is met when the title matches. - #[serde(default)] - title: Option>, - /// This condition is met when the tag matches. - #[serde(default)] - tag: Option>, -} - -#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)] -pub struct WindowRule { - /// Set the output the window will open on. - #[serde(default)] - pub output: Option, - /// Set the tags the output will have on open. - #[serde(default)] - pub tags: Option>, - /// Set the window to floating or tiled on open. - #[serde(default)] - pub floating_or_tiled: Option, - /// Set the window to fullscreen, maximized, or force it to neither. - #[serde(default)] - pub fullscreen_or_maximized: Option, - /// Set the window's initial size. - #[serde(default)] - pub size: Option<(NonZeroU32, NonZeroU32)>, - /// Set the window's initial location. If the window is tiled, it will snap to this position - /// when set to floating. - #[serde(default)] - pub location: Option<(i32, i32)>, -} - #[derive(Debug, serde::Serialize)] pub(crate) enum Msg { // Input diff --git a/api/rust/src/window.rs b/api/rust/src/window.rs index 1fec9e9..d27b562 100644 --- a/api/rust/src/window.rs +++ b/api/rust/src/window.rs @@ -1,3 +1,5 @@ +pub mod rules; + use crate::{ msg::{Msg, Request, RequestResponse}, request, send_msg, @@ -5,6 +7,8 @@ use crate::{ MouseButton, }; +use self::rules::WindowRules; + /// A unique identifier for each window. #[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub enum WindowId { @@ -15,7 +19,9 @@ pub enum WindowId { Some(u32), } -pub struct Window; +pub struct Window { + pub rules: WindowRules, +} impl Window { pub fn get_by_class<'a>(&self, class: &'a str) -> impl Iterator + 'a { diff --git a/api/rust/src/window/rules.rs b/api/rust/src/window/rules.rs new file mode 100644 index 0000000..2648d16 --- /dev/null +++ b/api/rust/src/window/rules.rs @@ -0,0 +1,94 @@ +use std::num::NonZeroU32; + +use crate::{msg::Msg, output::OutputHandle, send_msg, tag::TagHandle}; + +use super::{FloatingOrTiled, FullscreenOrMaximized}; + +pub struct WindowRules; + +impl WindowRules { + pub fn add(&self, cond: WindowRuleCondition, rule: WindowRule) { + let msg = Msg::AddWindowRule { + cond: cond.0, + rule: rule.0, + }; + + send_msg(msg).unwrap(); + } +} + +#[derive(Default)] +pub struct WindowRule(crate::msg::WindowRule); + +impl WindowRule { + pub fn new() -> Self { + Default::default() + } + + pub fn output(mut self, output: &OutputHandle) -> Self { + self.0.output = Some(output.0.clone()); + self + } + + pub fn tags(mut self, tags: &[TagHandle]) -> Self { + self.0.tags = Some(tags.iter().map(|tag| tag.0).collect()); + self + } + + pub fn floating_or_tiled(mut self, floating_or_tiled: FloatingOrTiled) -> Self { + self.0.floating_or_tiled = Some(floating_or_tiled); + self + } + + pub fn fullscreen_or_maximized( + mut self, + fullscreen_or_maximized: FullscreenOrMaximized, + ) -> Self { + self.0.fullscreen_or_maximized = Some(fullscreen_or_maximized); + self + } + + pub fn size(mut self, width: NonZeroU32, height: NonZeroU32) -> Self { + self.0.size = Some((width, height)); + self + } + + pub fn location(mut self, x: i32, y: i32) -> Self { + self.0.location = Some((x, y)); + self + } +} + +#[derive(Default, Debug)] +pub struct WindowRuleCondition(crate::msg::WindowRuleCondition); + +impl WindowRuleCondition { + pub fn new() -> Self { + Default::default() + } + + pub fn any(mut self, conds: &[WindowRuleCondition]) -> Self { + self.0.cond_any = Some(conds.iter().map(|cond| cond.0.clone()).collect()); + self + } + + pub fn all(mut self, conds: &[WindowRuleCondition]) -> Self { + self.0.cond_all = Some(conds.iter().map(|cond| cond.0.clone()).collect()); + self + } + + pub fn class(mut self, classes: &[&str]) -> Self { + self.0.class = Some(classes.iter().map(|s| s.to_string()).collect()); + self + } + + pub fn title(mut self, titles: &[&str]) -> Self { + self.0.title = Some(titles.iter().map(|s| s.to_string()).collect()); + self + } + + pub fn tag(mut self, tags: &[TagHandle]) -> Self { + self.0.tag = Some(tags.iter().map(|tag| tag.0).collect()); + self + } +}