diff --git a/Cargo.lock b/Cargo.lock index 63db4d98..51f88b32 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3238,6 +3238,7 @@ version = "0.1.40" dependencies = [ "clap", "color-eyre", + "objc2-core-foundation", "schemars 1.2.1", "serde", "serde_json_lenient", diff --git a/deny.toml b/deny.toml index d8230a7d..8582b46e 100644 --- a/deny.toml +++ b/deny.toml @@ -50,6 +50,11 @@ crate = "komorebi-client" expression = "LicenseRef-Komorebi-2.0" license-files = [] +[[licenses.clarify]] +crate = "komorebi-layouts" +expression = "LicenseRef-Komorebi-2.0" +license-files = [] + [[licenses.clarify]] crate = "komorebic" expression = "LicenseRef-Komorebi-2.0" diff --git a/komorebi-layouts/Cargo.toml b/komorebi-layouts/Cargo.toml index c6858df4..4e4e5eb8 100644 --- a/komorebi-layouts/Cargo.toml +++ b/komorebi-layouts/Cargo.toml @@ -15,7 +15,12 @@ tracing = { workspace = true } # Optional dependencies schemars = { workspace = true, optional = true } windows = { workspace = true, optional = true } +objc2-core-foundation = { version = "0.3", default-features = false, features = [ + "std", + "CFCGTypes", +], optional = true } [features] schemars = ["dep:schemars"] win32 = ["dep:windows"] +darwin = ["dep:objc2-core-foundation"] diff --git a/komorebi-layouts/src/arrangement.rs b/komorebi-layouts/src/arrangement.rs index fa031f76..5058fb40 100644 --- a/komorebi-layouts/src/arrangement.rs +++ b/komorebi-layouts/src/arrangement.rs @@ -6,11 +6,15 @@ use serde::Serialize; use strum::Display; use strum::EnumString; +#[cfg(feature = "win32")] use super::CustomLayout; use super::DefaultLayout; use super::Rect; +#[cfg(feature = "win32")] use super::custom_layout::Column; +#[cfg(feature = "win32")] use super::custom_layout::ColumnSplit; +#[cfg(feature = "win32")] use super::custom_layout::ColumnSplitWithCapacity; use crate::default_layout::DEFAULT_RATIO; use crate::default_layout::DEFAULT_SECONDARY_RATIO; @@ -719,6 +723,7 @@ impl Arrangement for DefaultLayout { } } +#[cfg(feature = "win32")] impl Arrangement for CustomLayout { fn calculate( &self, @@ -857,6 +862,7 @@ pub enum Axis { HorizontalAndVertical, } +#[cfg(feature = "win32")] #[must_use] fn columns(area: &Rect, len: usize) -> Vec { columns_with_ratios(area, len, None) @@ -931,6 +937,7 @@ fn columns_with_ratios( layouts } +#[cfg(feature = "win32")] #[must_use] fn rows(area: &Rect, len: usize) -> Vec { rows_with_ratios(area, len, None) diff --git a/komorebi-layouts/src/direction.rs b/komorebi-layouts/src/direction.rs index 2027fdca..6ee9cc59 100644 --- a/komorebi-layouts/src/direction.rs +++ b/komorebi-layouts/src/direction.rs @@ -1,8 +1,12 @@ use super::DefaultLayout; use super::OperationDirection; +#[cfg(feature = "win32")] use super::custom_layout::Column; +#[cfg(feature = "win32")] use super::custom_layout::ColumnSplit; +#[cfg(feature = "win32")] use super::custom_layout::ColumnSplitWithCapacity; +#[cfg(feature = "win32")] use super::custom_layout::CustomLayout; use crate::default_layout::LayoutOptions; @@ -400,6 +404,7 @@ fn grid_neighbor( } } +#[cfg(feature = "win32")] impl Direction for CustomLayout { fn index_in_direction( &self, diff --git a/komorebi-layouts/src/layout.rs b/komorebi-layouts/src/layout.rs index 909d29f6..12c0a01b 100644 --- a/komorebi-layouts/src/layout.rs +++ b/komorebi-layouts/src/layout.rs @@ -2,6 +2,7 @@ use serde::Deserialize; use serde::Serialize; use super::Arrangement; +#[cfg(feature = "win32")] use super::CustomLayout; use super::DefaultLayout; use super::Direction; @@ -10,6 +11,7 @@ use super::Direction; #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub enum Layout { Default(DefaultLayout), + #[cfg(feature = "win32")] Custom(CustomLayout), } @@ -18,6 +20,7 @@ impl Layout { pub fn as_boxed_direction(&self) -> Box { match self { Layout::Default(layout) => Box::new(*layout), + #[cfg(feature = "win32")] Layout::Custom(layout) => Box::new(layout.clone()), } } @@ -26,6 +29,7 @@ impl Layout { pub fn as_boxed_arrangement(&self) -> Box { match self { Layout::Default(layout) => Box::new(*layout), + #[cfg(feature = "win32")] Layout::Custom(layout) => Box::new(layout.clone()), } } diff --git a/komorebi-layouts/src/lib.rs b/komorebi-layouts/src/lib.rs index d2368c1e..f9873d91 100644 --- a/komorebi-layouts/src/lib.rs +++ b/komorebi-layouts/src/lib.rs @@ -8,6 +8,7 @@ //! behind the `win32` feature flag. pub mod arrangement; +#[cfg(feature = "win32")] pub mod custom_layout; pub mod cycle_direction; pub mod default_layout; @@ -18,6 +19,7 @@ pub mod rect; pub mod sizing; pub use arrangement::*; +#[cfg(feature = "win32")] pub use custom_layout::*; pub use cycle_direction::*; pub use default_layout::*; diff --git a/komorebi-layouts/src/rect.rs b/komorebi-layouts/src/rect.rs index 33e0279c..10f76667 100644 --- a/komorebi-layouts/src/rect.rs +++ b/komorebi-layouts/src/rect.rs @@ -4,6 +4,15 @@ use serde::Serialize; #[cfg(feature = "win32")] use windows::Win32::Foundation::RECT; +#[cfg(feature = "darwin")] +use objc2_core_foundation::CGFloat; +#[cfg(feature = "darwin")] +use objc2_core_foundation::CGPoint; +#[cfg(feature = "darwin")] +use objc2_core_foundation::CGRect; +#[cfg(feature = "darwin")] +use objc2_core_foundation::CGSize; + #[derive(Debug, Default, Clone, Copy, Serialize, Deserialize, Eq, PartialEq)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] /// Rectangle dimensions @@ -42,6 +51,53 @@ impl From for RECT { } } +#[cfg(feature = "darwin")] +impl From for Rect { + fn from(value: CGSize) -> Self { + Self { + left: 0, + top: 0, + right: value.width as i32, + bottom: value.height as i32, + } + } +} + +#[cfg(feature = "darwin")] +impl From for Rect { + fn from(value: CGRect) -> Self { + Self { + left: value.origin.x as i32, + top: value.origin.y as i32, + right: value.size.width as i32, + bottom: value.size.height as i32, + } + } +} + +#[cfg(feature = "darwin")] +impl From<&Rect> for CGRect { + fn from(value: &Rect) -> Self { + Self { + origin: CGPoint { + x: value.left as CGFloat, + y: value.top as CGFloat, + }, + size: CGSize { + width: value.right as CGFloat, + height: value.bottom as CGFloat, + }, + } + } +} + +#[cfg(feature = "darwin")] +impl From for CGRect { + fn from(value: Rect) -> Self { + CGRect::from(&value) + } +} + impl Rect { pub fn is_same_size_as(&self, rhs: &Self) -> bool { self.right == rhs.right && self.bottom == rhs.bottom @@ -110,4 +166,19 @@ impl Rect { bottom: self.top + self.bottom, } } + + #[cfg(feature = "darwin")] + #[must_use] + pub fn percentage_within_horizontal_bounds(&self, other: &Rect) -> f64 { + let overlap_left = self.left.max(other.left); + let overlap_right = (self.left + self.right).min(other.left + other.right); + + let overlap_width = overlap_right - overlap_left; + + if overlap_width <= 0 { + 0.0 + } else { + (overlap_width as f64) / (other.right as f64) * 100.0 + } + } }