mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2024-12-26 21:58:10 +01:00
Add documentation
This commit is contained in:
parent
f5b626e14d
commit
f0e2282445
8 changed files with 189 additions and 0 deletions
|
@ -52,6 +52,10 @@ impl Input {
|
||||||
send_msg(msg).unwrap();
|
send_msg(msg).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set a mousebind. If called with an already existing mousebind, it gets replaced.
|
||||||
|
///
|
||||||
|
/// The mousebind can happen either on button press or release, so you must
|
||||||
|
/// specify which edge you desire.
|
||||||
pub fn mousebind<F>(
|
pub fn mousebind<F>(
|
||||||
&self,
|
&self,
|
||||||
modifiers: &[Modifier],
|
modifiers: &[Modifier],
|
||||||
|
|
|
@ -1,56 +1,111 @@
|
||||||
use crate::{msg::Msg, send_msg};
|
use crate::{msg::Msg, send_msg};
|
||||||
|
|
||||||
|
/// Libinput settings.
|
||||||
|
///
|
||||||
|
/// Here you can set things like pointer acceleration.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Libinput;
|
pub struct Libinput;
|
||||||
|
|
||||||
impl Libinput {
|
impl Libinput {
|
||||||
|
/// Set a libinput setting.
|
||||||
|
///
|
||||||
|
/// This takes a [`LibinputSetting`] containing what you want set.
|
||||||
pub fn set(&self, setting: LibinputSetting) {
|
pub fn set(&self, setting: LibinputSetting) {
|
||||||
let msg = Msg::SetLibinputSetting(setting);
|
let msg = Msg::SetLibinputSetting(setting);
|
||||||
send_msg(msg).unwrap();
|
send_msg(msg).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The acceleration profile.
|
||||||
#[derive(Debug, PartialEq, Copy, Clone, serde::Serialize)]
|
#[derive(Debug, PartialEq, Copy, Clone, serde::Serialize)]
|
||||||
pub enum AccelProfile {
|
pub enum AccelProfile {
|
||||||
|
/// Flat pointer acceleration.
|
||||||
Flat,
|
Flat,
|
||||||
|
/// Adaptive pointer acceleration.
|
||||||
|
///
|
||||||
|
/// This is the default for most devices.
|
||||||
Adaptive,
|
Adaptive,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The click method for a touchpad.
|
||||||
#[derive(Debug, PartialEq, Copy, Clone, serde::Serialize)]
|
#[derive(Debug, PartialEq, Copy, Clone, serde::Serialize)]
|
||||||
pub enum ClickMethod {
|
pub enum ClickMethod {
|
||||||
|
/// Use software-button areas to generate button events.
|
||||||
ButtonAreas,
|
ButtonAreas,
|
||||||
|
/// The number of fingers decides which button press to generate.
|
||||||
Clickfinger,
|
Clickfinger,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The scroll method for a touchpad.
|
||||||
#[derive(Debug, PartialEq, Copy, Clone, serde::Serialize)]
|
#[derive(Debug, PartialEq, Copy, Clone, serde::Serialize)]
|
||||||
pub enum ScrollMethod {
|
pub enum ScrollMethod {
|
||||||
|
/// Never send scroll events.
|
||||||
NoScroll,
|
NoScroll,
|
||||||
|
/// Send scroll events when two fingers are logically down on the device.
|
||||||
TwoFinger,
|
TwoFinger,
|
||||||
|
/// Send scroll events when a finger moves along the bottom or right edge of a device.
|
||||||
Edge,
|
Edge,
|
||||||
|
/// Send scroll events when a button is down and the device moves along a scroll-capable axis.
|
||||||
OnButtonDown,
|
OnButtonDown,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The mapping between finger count and button event for a touchpad.
|
||||||
#[derive(Debug, PartialEq, Copy, Clone, serde::Serialize)]
|
#[derive(Debug, PartialEq, Copy, Clone, serde::Serialize)]
|
||||||
pub enum TapButtonMap {
|
pub enum TapButtonMap {
|
||||||
|
/// 1/2/3 finger tap is mapped to left/right/middle click.
|
||||||
LeftRightMiddle,
|
LeftRightMiddle,
|
||||||
|
/// 1/2/3 finger tap is mapped to left/middle/right click.
|
||||||
LeftMiddleRight,
|
LeftMiddleRight,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Libinput settings.
|
||||||
#[derive(Debug, PartialEq, Copy, Clone, serde::Serialize)]
|
#[derive(Debug, PartialEq, Copy, Clone, serde::Serialize)]
|
||||||
pub enum LibinputSetting {
|
pub enum LibinputSetting {
|
||||||
|
/// Set the acceleration profile.
|
||||||
AccelProfile(AccelProfile),
|
AccelProfile(AccelProfile),
|
||||||
|
/// Set the acceleration speed.
|
||||||
|
///
|
||||||
|
/// This should be a float from -1.0 to 1.0.
|
||||||
AccelSpeed(f64),
|
AccelSpeed(f64),
|
||||||
|
/// Set the calibration matrix.
|
||||||
CalibrationMatrix([f32; 6]),
|
CalibrationMatrix([f32; 6]),
|
||||||
|
/// Set the click method.
|
||||||
|
///
|
||||||
|
/// The click method defines when to generate software-emulated buttons, usually on a device
|
||||||
|
/// that does not have a specific physical button available.
|
||||||
ClickMethod(ClickMethod),
|
ClickMethod(ClickMethod),
|
||||||
|
/// Set whether or not the device will be disabled while typing.
|
||||||
DisableWhileTypingEnabled(bool),
|
DisableWhileTypingEnabled(bool),
|
||||||
|
/// Set device left-handedness.
|
||||||
LeftHanded(bool),
|
LeftHanded(bool),
|
||||||
|
/// Set whether or not the middle click can be emulated.
|
||||||
MiddleEmulationEnabled(bool),
|
MiddleEmulationEnabled(bool),
|
||||||
|
/// Set the rotation angle of a device.
|
||||||
RotationAngle(u32),
|
RotationAngle(u32),
|
||||||
|
/// Set the scroll method.
|
||||||
ScrollMethod(ScrollMethod),
|
ScrollMethod(ScrollMethod),
|
||||||
|
/// Set whether or not natural scroll is enabled.
|
||||||
|
///
|
||||||
|
/// This reverses the direction of scrolling and is mainly used with touchpads.
|
||||||
NaturalScrollEnabled(bool),
|
NaturalScrollEnabled(bool),
|
||||||
|
/// Set the scroll button.
|
||||||
ScrollButton(u32),
|
ScrollButton(u32),
|
||||||
|
/// Set the tap button map,
|
||||||
|
///
|
||||||
|
/// This determines whether taps with 2 and 3 fingers register as right and middle clicks or
|
||||||
|
/// the reverse.
|
||||||
TapButtonMap(TapButtonMap),
|
TapButtonMap(TapButtonMap),
|
||||||
|
/// Set whether or not tap-and-drag is enabled.
|
||||||
|
///
|
||||||
|
/// When enabled, a single-finger tap immediately followed by a finger down results in
|
||||||
|
/// a button down event, and subsequent finger motion thus triggers a drag.
|
||||||
|
/// The button is released on finger up.
|
||||||
TapDragEnabled(bool),
|
TapDragEnabled(bool),
|
||||||
|
/// Set whether or not tap drag lock is enabled.
|
||||||
|
///
|
||||||
|
/// When enabled, a finger may be lifted and put back on the touchpad within a timeout and the drag process
|
||||||
|
/// continues. When disabled, lifting the finger during a tap-and-drag will immediately stop the drag.
|
||||||
TapDragLockEnabled(bool),
|
TapDragLockEnabled(bool),
|
||||||
|
/// Set whether or not tap-to-click is enabled.
|
||||||
TapEnabled(bool),
|
TapEnabled(bool),
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ pub use xkbcommon;
|
||||||
/// To that end, you can do `use pinnacle_api::prelude::*` to
|
/// To that end, you can do `use pinnacle_api::prelude::*` to
|
||||||
/// prevent your config file from being cluttered with imports.
|
/// prevent your config file from being cluttered with imports.
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
|
pub use crate::input::libinput::*;
|
||||||
pub use crate::input::Modifier;
|
pub use crate::input::Modifier;
|
||||||
pub use crate::input::MouseButton;
|
pub use crate::input::MouseButton;
|
||||||
pub use crate::input::MouseEdge;
|
pub use crate::input::MouseEdge;
|
||||||
|
@ -226,6 +227,7 @@ pub struct Pinnacle {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pinnacle {
|
impl Pinnacle {
|
||||||
|
/// Quit Pinnacle.
|
||||||
pub fn quit(&self) {
|
pub fn quit(&self) {
|
||||||
send_msg(Msg::Quit).unwrap();
|
send_msg(Msg::Quit).unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,19 @@ impl Output {
|
||||||
.find(|op| op.properties().focused == Some(true))
|
.find(|op| op.properties().focused == Some(true))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Connect a function to be run on all current and future outputs.
|
||||||
|
///
|
||||||
|
/// When called, `connect_for_all` will run `func` with all currently connected outputs.
|
||||||
|
/// If a new output is connected, `func` will also be called with it.
|
||||||
|
///
|
||||||
|
/// This will *not* be called if it has already been called for a given connector.
|
||||||
|
/// This means turning your monitor off and on or unplugging and replugging it *to the same port*
|
||||||
|
/// won't trigger `func`. Plugging it in to a new port *will* trigger `func`.
|
||||||
|
/// This is intended to prevent duplicate setup.
|
||||||
|
///
|
||||||
|
/// Please note: this function will be run *after* Pinnacle processes your entire config.
|
||||||
|
/// For example, if you define tags in `func` but toggle them directly after `connect_for_all`,
|
||||||
|
/// nothing will happen as the tags haven't been added yet.
|
||||||
pub fn connect_for_all<F>(&self, mut func: F)
|
pub fn connect_for_all<F>(&self, mut func: F)
|
||||||
where
|
where
|
||||||
F: FnMut(OutputHandle) + Send + 'static,
|
F: FnMut(OutputHandle) + Send + 'static,
|
||||||
|
@ -247,16 +260,24 @@ enum LeftOrRight {
|
||||||
Right,
|
Right,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Horizontal alignment.
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum AlignmentHorizontal {
|
pub enum AlignmentHorizontal {
|
||||||
|
/// Align the outputs such that the left edges are in line.
|
||||||
Left,
|
Left,
|
||||||
|
/// Center the outputs horizontally.
|
||||||
Center,
|
Center,
|
||||||
|
/// Align the outputs such that the right edges are in line.
|
||||||
Right,
|
Right,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Vertical alignment.
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum AlignmentVertical {
|
pub enum AlignmentVertical {
|
||||||
|
/// Align the outputs such that the top edges are in line.
|
||||||
Top,
|
Top,
|
||||||
|
/// Center the outputs vertically.
|
||||||
Center,
|
Center,
|
||||||
|
/// Align the outputs such that the bottom edges are in line.
|
||||||
Bottom,
|
Bottom,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,16 @@ use crate::{
|
||||||
send_msg, CALLBACK_VEC,
|
send_msg, CALLBACK_VEC,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Process management.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Process;
|
pub struct Process;
|
||||||
|
|
||||||
impl Process {
|
impl Process {
|
||||||
|
/// Spawn a process.
|
||||||
|
///
|
||||||
|
/// This will use Rust's (more specifically `async_process`'s) `Command` to spawn the provided
|
||||||
|
/// arguments. If you are using any shell syntax like `~`, you may need to spawn a shell
|
||||||
|
/// instead. If so, you may *also* need to correctly escape the input.
|
||||||
pub fn spawn(&self, command: Vec<&str>) -> anyhow::Result<()> {
|
pub fn spawn(&self, command: Vec<&str>) -> anyhow::Result<()> {
|
||||||
let msg = Msg::Spawn {
|
let msg = Msg::Spawn {
|
||||||
command: command.into_iter().map(|s| s.to_string()).collect(),
|
command: command.into_iter().map(|s| s.to_string()).collect(),
|
||||||
|
@ -16,6 +22,13 @@ impl Process {
|
||||||
send_msg(msg)
|
send_msg(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Spawn a process with an optional callback for its stdout, stderr, and exit information.
|
||||||
|
///
|
||||||
|
/// `callback` has the following parameters:
|
||||||
|
/// - `0`: The process's stdout printed this line.
|
||||||
|
/// - `1`: The process's stderr printed this line.
|
||||||
|
/// - `2`: The process exited with this code.
|
||||||
|
/// - `3`: The process exited with this message.
|
||||||
pub fn spawn_with_callback<F>(&self, command: Vec<&str>, mut callback: F) -> anyhow::Result<()>
|
pub fn spawn_with_callback<F>(&self, command: Vec<&str>, mut callback: F) -> anyhow::Result<()>
|
||||||
where
|
where
|
||||||
F: FnMut(Option<String>, Option<String>, Option<i32>, Option<String>) + Send + 'static,
|
F: FnMut(Option<String>, Option<String>, Option<i32>, Option<String>) + Send + 'static,
|
||||||
|
|
|
@ -6,6 +6,7 @@ use crate::{
|
||||||
request, send_msg,
|
request, send_msg,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Tag management.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Tag;
|
pub struct Tag;
|
||||||
|
|
||||||
|
@ -48,6 +49,15 @@ impl Tag {
|
||||||
send_msg(msg).unwrap();
|
send_msg(msg).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a `LayoutCycler` to cycle layouts on tags.
|
||||||
|
///
|
||||||
|
/// Given a slice of layouts, this will create a `LayoutCycler` with two methods;
|
||||||
|
/// one will cycle forward the layout for the active tag, and one will cycle backward.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// todo!()
|
||||||
|
/// ```
|
||||||
pub fn layout_cycler(&self, layouts: &[Layout]) -> LayoutCycler {
|
pub fn layout_cycler(&self, layouts: &[Layout]) -> LayoutCycler {
|
||||||
let mut indices = HashMap::<TagId, usize>::new();
|
let mut indices = HashMap::<TagId, usize>::new();
|
||||||
let layouts = layouts.to_vec();
|
let layouts = layouts.to_vec();
|
||||||
|
@ -174,13 +184,21 @@ impl TagHandle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Layouts for tags.
|
||||||
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum Layout {
|
pub enum Layout {
|
||||||
|
/// One master window on the left with all other windows stacked to the right.
|
||||||
MasterStack,
|
MasterStack,
|
||||||
|
/// Windows split in half towards the bottom right corner.
|
||||||
Dwindle,
|
Dwindle,
|
||||||
|
/// Windows split in half in a spiral
|
||||||
Spiral,
|
Spiral,
|
||||||
|
/// One main corner window in the top left with a column of windows on the right and a row on the bottom.
|
||||||
CornerTopLeft,
|
CornerTopLeft,
|
||||||
|
/// One main corner window in the top right with a column of windows on the left and a row on the bottom.
|
||||||
CornerTopRight,
|
CornerTopRight,
|
||||||
|
/// One main corner window in the bottom left with a column of windows on the right and a row on the top.
|
||||||
CornerBottomLeft,
|
CornerBottomLeft,
|
||||||
|
/// One main corner window in the bottom right with a column of windows on the left and a row on the top.
|
||||||
CornerBottomRight,
|
CornerBottomRight,
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,22 +19,27 @@ pub enum WindowId {
|
||||||
Some(u32),
|
Some(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Window management.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Window {
|
pub struct Window {
|
||||||
|
/// Window rules.
|
||||||
pub rules: WindowRules,
|
pub rules: WindowRules,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
|
/// Get all windows with the class `class`.
|
||||||
pub fn get_by_class<'a>(&self, class: &'a str) -> impl Iterator<Item = WindowHandle> + 'a {
|
pub fn get_by_class<'a>(&self, class: &'a str) -> impl Iterator<Item = WindowHandle> + 'a {
|
||||||
self.get_all()
|
self.get_all()
|
||||||
.filter(|win| win.properties().class.as_deref() == Some(class))
|
.filter(|win| win.properties().class.as_deref() == Some(class))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the currently focused window, or `None` if there isn't one.
|
||||||
pub fn get_focused(&self) -> Option<WindowHandle> {
|
pub fn get_focused(&self) -> Option<WindowHandle> {
|
||||||
self.get_all()
|
self.get_all()
|
||||||
.find(|win| win.properties().focused.is_some_and(|focused| focused))
|
.find(|win| win.properties().focused.is_some_and(|focused| focused))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get all windows.
|
||||||
pub fn get_all(&self) -> impl Iterator<Item = WindowHandle> {
|
pub fn get_all(&self) -> impl Iterator<Item = WindowHandle> {
|
||||||
let RequestResponse::Windows { window_ids } = request(Request::GetWindows) else {
|
let RequestResponse::Windows { window_ids } = request(Request::GetWindows) else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
@ -43,6 +48,10 @@ impl Window {
|
||||||
window_ids.into_iter().map(WindowHandle)
|
window_ids.into_iter().map(WindowHandle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Begin a window move.
|
||||||
|
///
|
||||||
|
/// This will start a window move grab with the provided button on the window the pointer
|
||||||
|
/// is currently hovering over. Once `button` is let go, the move will end.
|
||||||
pub fn begin_move(&self, button: MouseButton) {
|
pub fn begin_move(&self, button: MouseButton) {
|
||||||
let msg = Msg::WindowMoveGrab {
|
let msg = Msg::WindowMoveGrab {
|
||||||
button: button as u32,
|
button: button as u32,
|
||||||
|
@ -51,6 +60,10 @@ impl Window {
|
||||||
send_msg(msg).unwrap();
|
send_msg(msg).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Begin a window resize.
|
||||||
|
///
|
||||||
|
/// This will start a window resize grab with the provided button on the window the
|
||||||
|
/// pointer is currently hovering over. Once `button` is let go, the resize will end.
|
||||||
pub fn begin_resize(&self, button: MouseButton) {
|
pub fn begin_resize(&self, button: MouseButton) {
|
||||||
let msg = Msg::WindowResizeGrab {
|
let msg = Msg::WindowResizeGrab {
|
||||||
button: button as u32,
|
button: button as u32,
|
||||||
|
@ -143,15 +156,34 @@ impl WindowHandle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether or not a window is floating or tiled.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize)]
|
||||||
pub enum FloatingOrTiled {
|
pub enum FloatingOrTiled {
|
||||||
|
/// The window is floating.
|
||||||
|
///
|
||||||
|
/// It can be freely moved around and resized and will not respond to layouts.
|
||||||
Floating,
|
Floating,
|
||||||
|
/// The window is tiled.
|
||||||
|
///
|
||||||
|
/// It cannot be resized and can only move by swapping places with other tiled windows.
|
||||||
Tiled,
|
Tiled,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether the window is fullscreen, maximized, or neither.
|
||||||
|
///
|
||||||
|
/// These three states are mutually exclusive. Setting a window to maximized while it is fullscreen
|
||||||
|
/// will make it stop being fullscreen and vice versa.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum FullscreenOrMaximized {
|
pub enum FullscreenOrMaximized {
|
||||||
|
/// The window is not fullscreen or maximized.
|
||||||
Neither,
|
Neither,
|
||||||
|
/// The window is fullscreen.
|
||||||
|
///
|
||||||
|
/// It will be the only rendered window on screen and will fill the output it resides on.
|
||||||
|
/// Layer surfaces will also not be rendered while a window is fullscreen.
|
||||||
Fullscreen,
|
Fullscreen,
|
||||||
|
/// The window is maximized.
|
||||||
|
///
|
||||||
|
/// It will fill up as much space on its output as it can, respecting any layer surfaces.
|
||||||
Maximized,
|
Maximized,
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,12 @@ use crate::{msg::Msg, output::OutputHandle, send_msg, tag::TagHandle};
|
||||||
|
|
||||||
use super::{FloatingOrTiled, FullscreenOrMaximized};
|
use super::{FloatingOrTiled, FullscreenOrMaximized};
|
||||||
|
|
||||||
|
/// Window rules.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct WindowRules;
|
pub struct WindowRules;
|
||||||
|
|
||||||
impl WindowRules {
|
impl WindowRules {
|
||||||
|
/// Add a window rule.
|
||||||
pub fn add(&self, cond: WindowRuleCondition, rule: WindowRule) {
|
pub fn add(&self, cond: WindowRuleCondition, rule: WindowRule) {
|
||||||
let msg = Msg::AddWindowRule {
|
let msg = Msg::AddWindowRule {
|
||||||
cond: cond.0,
|
cond: cond.0,
|
||||||
|
@ -18,29 +20,40 @@ impl WindowRules {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A window rule.
|
||||||
|
///
|
||||||
|
/// This is what will be applied to a window if it meets a [`WindowRuleCondition`].
|
||||||
|
///
|
||||||
|
/// `WindowRule`s are built using the builder pattern.
|
||||||
|
/// // TODO: show example
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct WindowRule(crate::msg::WindowRule);
|
pub struct WindowRule(crate::msg::WindowRule);
|
||||||
|
|
||||||
impl WindowRule {
|
impl WindowRule {
|
||||||
|
/// Create a new, empty window rule.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This rule will force windows to open on the provided `output`.
|
||||||
pub fn output(mut self, output: &OutputHandle) -> Self {
|
pub fn output(mut self, output: &OutputHandle) -> Self {
|
||||||
self.0.output = Some(output.0.clone());
|
self.0.output = Some(output.0.clone());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This rule will force windows to open with the provided `tags`.
|
||||||
pub fn tags(mut self, tags: &[TagHandle]) -> Self {
|
pub fn tags(mut self, tags: &[TagHandle]) -> Self {
|
||||||
self.0.tags = Some(tags.iter().map(|tag| tag.0).collect());
|
self.0.tags = Some(tags.iter().map(|tag| tag.0).collect());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This rule will force windows to open either floating or tiled.
|
||||||
pub fn floating_or_tiled(mut self, floating_or_tiled: FloatingOrTiled) -> Self {
|
pub fn floating_or_tiled(mut self, floating_or_tiled: FloatingOrTiled) -> Self {
|
||||||
self.0.floating_or_tiled = Some(floating_or_tiled);
|
self.0.floating_or_tiled = Some(floating_or_tiled);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This rule will force windows to open either fullscreen, maximized, or neither.
|
||||||
pub fn fullscreen_or_maximized(
|
pub fn fullscreen_or_maximized(
|
||||||
mut self,
|
mut self,
|
||||||
fullscreen_or_maximized: FullscreenOrMaximized,
|
fullscreen_or_maximized: FullscreenOrMaximized,
|
||||||
|
@ -49,45 +62,76 @@ impl WindowRule {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This rule will force windows to open with a specific size.
|
||||||
|
///
|
||||||
|
/// This will only actually be visible if the window is also floating.
|
||||||
pub fn size(mut self, width: NonZeroU32, height: NonZeroU32) -> Self {
|
pub fn size(mut self, width: NonZeroU32, height: NonZeroU32) -> Self {
|
||||||
self.0.size = Some((width, height));
|
self.0.size = Some((width, height));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This rule will force windows to open at a specific location.
|
||||||
|
///
|
||||||
|
/// This will only actually be visible if the window is also floating.
|
||||||
pub fn location(mut self, x: i32, y: i32) -> Self {
|
pub fn location(mut self, x: i32, y: i32) -> Self {
|
||||||
self.0.location = Some((x, y));
|
self.0.location = Some((x, y));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A condition for a [`WindowRule`] to apply to a window.
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct WindowRuleCondition(crate::msg::WindowRuleCondition);
|
pub struct WindowRuleCondition(crate::msg::WindowRuleCondition);
|
||||||
|
|
||||||
impl WindowRuleCondition {
|
impl WindowRuleCondition {
|
||||||
|
/// Create a new, empty `WindowRuleCondition`.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This condition requires that at least one provided condition is true.
|
||||||
pub fn any(mut self, conds: &[WindowRuleCondition]) -> Self {
|
pub fn any(mut self, conds: &[WindowRuleCondition]) -> Self {
|
||||||
self.0.cond_any = Some(conds.iter().map(|cond| cond.0.clone()).collect());
|
self.0.cond_any = Some(conds.iter().map(|cond| cond.0.clone()).collect());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This condition requires that all provided conditions are true.
|
||||||
pub fn all(mut self, conds: &[WindowRuleCondition]) -> Self {
|
pub fn all(mut self, conds: &[WindowRuleCondition]) -> Self {
|
||||||
self.0.cond_all = Some(conds.iter().map(|cond| cond.0.clone()).collect());
|
self.0.cond_all = Some(conds.iter().map(|cond| cond.0.clone()).collect());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This condition requires that the window's class matches.
|
||||||
|
///
|
||||||
|
/// When used in a top level condition or inside of [`WindowRuleCondition::all`],
|
||||||
|
/// *all* classes must match (this is impossible).
|
||||||
|
///
|
||||||
|
/// When used in [`WindowRuleCondition::any`], at least one of the
|
||||||
|
/// provided classes must match.
|
||||||
pub fn class(mut self, classes: &[&str]) -> Self {
|
pub fn class(mut self, classes: &[&str]) -> Self {
|
||||||
self.0.class = Some(classes.iter().map(|s| s.to_string()).collect());
|
self.0.class = Some(classes.iter().map(|s| s.to_string()).collect());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This condition requires that the window's title matches.
|
||||||
|
///
|
||||||
|
/// When used in a top level condition or inside of [`WindowRuleCondition::all`],
|
||||||
|
/// *all* titles must match (this is impossible).
|
||||||
|
///
|
||||||
|
/// When used in [`WindowRuleCondition::any`], at least one of the
|
||||||
|
/// provided titles must match.
|
||||||
pub fn title(mut self, titles: &[&str]) -> Self {
|
pub fn title(mut self, titles: &[&str]) -> Self {
|
||||||
self.0.title = Some(titles.iter().map(|s| s.to_string()).collect());
|
self.0.title = Some(titles.iter().map(|s| s.to_string()).collect());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This condition requires that the window's is opened on the given tags.
|
||||||
|
///
|
||||||
|
/// When used in a top level condition or inside of [`WindowRuleCondition::all`],
|
||||||
|
/// the window must opne on *all* given tags.
|
||||||
|
///
|
||||||
|
/// When used in [`WindowRuleCondition::any`], the window must open on at least
|
||||||
|
/// one of the given tags.
|
||||||
pub fn tag(mut self, tags: &[TagHandle]) -> Self {
|
pub fn tag(mut self, tags: &[TagHandle]) -> Self {
|
||||||
self.0.tag = Some(tags.iter().map(|tag| tag.0).collect());
|
self.0.tag = Some(tags.iter().map(|tag| tag.0).collect());
|
||||||
self
|
self
|
||||||
|
|
Loading…
Reference in a new issue