feat(wm): add cmd to resize by axis

This commit adds a new command to resize by axis. Resizing is still
limited to the BSP layout. This command is intended to be bound to mouse
wheel up and down events, with different modified keys determining the
axis to operate on.
This commit is contained in:
LGUG2Z
2021-11-01 15:53:01 -07:00
parent d627a1a771
commit 2814349228
9 changed files with 147 additions and 59 deletions
+12 -12
View File
@@ -19,7 +19,7 @@ pub trait Arrangement {
area: &Rect, area: &Rect,
len: NonZeroUsize, len: NonZeroUsize,
container_padding: Option<i32>, container_padding: Option<i32>,
layout_flip: Option<Flip>, layout_flip: Option<Axis>,
resize_dimensions: &[Option<Rect>], resize_dimensions: &[Option<Rect>],
) -> Vec<Rect>; ) -> Vec<Rect>;
} }
@@ -31,7 +31,7 @@ impl Arrangement for DefaultLayout {
area: &Rect, area: &Rect,
len: NonZeroUsize, len: NonZeroUsize,
container_padding: Option<i32>, container_padding: Option<i32>,
layout_flip: Option<Flip>, layout_flip: Option<Axis>,
resize_dimensions: &[Option<Rect>], resize_dimensions: &[Option<Rect>],
) -> Vec<Rect> { ) -> Vec<Rect> {
let len = usize::from(len); let len = usize::from(len);
@@ -57,7 +57,7 @@ impl Arrangement for DefaultLayout {
let mut stack_left = area.left + primary_right; let mut stack_left = area.left + primary_right;
match layout_flip { match layout_flip {
Some(Flip::Horizontal | Flip::HorizontalAndVertical) if len > 1 => { Some(Axis::Horizontal | Axis::HorizontalAndVertical) if len > 1 => {
main_left = main_left + area.right - primary_right; main_left = main_left + area.right - primary_right;
stack_left = area.left; stack_left = area.left;
} }
@@ -99,7 +99,7 @@ impl Arrangement for DefaultLayout {
let mut stack_top = area.top + bottom; let mut stack_top = area.top + bottom;
match layout_flip { match layout_flip {
Some(Flip::Vertical | Flip::HorizontalAndVertical) if len > 1 => { Some(Axis::Vertical | Axis::HorizontalAndVertical) if len > 1 => {
main_top = main_top + area.bottom - bottom; main_top = main_top + area.bottom - bottom;
stack_top = area.top; stack_top = area.top;
} }
@@ -150,7 +150,7 @@ impl Arrangement for DefaultLayout {
let mut secondary = area.left; let mut secondary = area.left;
match layout_flip { match layout_flip {
Some(Flip::Horizontal | Flip::HorizontalAndVertical) if len > 1 => { Some(Axis::Horizontal | Axis::HorizontalAndVertical) if len > 1 => {
primary = area.left; primary = area.left;
secondary = area.left + primary_right; secondary = area.left + primary_right;
} }
@@ -165,7 +165,7 @@ impl Arrangement for DefaultLayout {
let mut stack = area.left + primary_right + secondary_right; let mut stack = area.left + primary_right + secondary_right;
match layout_flip { match layout_flip {
Some(Flip::Horizontal | Flip::HorizontalAndVertical) if len > 1 => { Some(Axis::Horizontal | Axis::HorizontalAndVertical) if len > 1 => {
secondary = area.left + primary_right + secondary_right; secondary = area.left + primary_right + secondary_right;
stack = area.left; stack = area.left;
} }
@@ -224,7 +224,7 @@ impl Arrangement for CustomLayout {
area: &Rect, area: &Rect,
len: NonZeroUsize, len: NonZeroUsize,
container_padding: Option<i32>, container_padding: Option<i32>,
_layout_flip: Option<Flip>, _layout_flip: Option<Axis>,
_resize_dimensions: &[Option<Rect>], _resize_dimensions: &[Option<Rect>],
) -> Vec<Rect> { ) -> Vec<Rect> {
let mut dimensions = vec![]; let mut dimensions = vec![];
@@ -343,7 +343,7 @@ impl Arrangement for CustomLayout {
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)] #[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)]
#[strum(serialize_all = "snake_case")] #[strum(serialize_all = "snake_case")]
pub enum Flip { pub enum Axis {
Horizontal, Horizontal,
Vertical, Vertical,
HorizontalAndVertical, HorizontalAndVertical,
@@ -478,7 +478,7 @@ fn recursive_fibonacci(
idx: usize, idx: usize,
count: usize, count: usize,
area: &Rect, area: &Rect,
layout_flip: Option<Flip>, layout_flip: Option<Axis>,
resize_adjustments: Vec<Option<Rect>>, resize_adjustments: Vec<Option<Rect>>,
) -> Vec<Rect> { ) -> Vec<Rect> {
let mut a = *area; let mut a = *area;
@@ -502,21 +502,21 @@ fn recursive_fibonacci(
if let Some(flip) = layout_flip { if let Some(flip) = layout_flip {
match flip { match flip {
Flip::Horizontal => { Axis::Horizontal => {
main_x = resized.left + half_width + (half_width - half_resized_width); main_x = resized.left + half_width + (half_width - half_resized_width);
alt_x = resized.left; alt_x = resized.left;
alt_y = resized.top + half_resized_height; alt_y = resized.top + half_resized_height;
main_y = resized.top; main_y = resized.top;
} }
Flip::Vertical => { Axis::Vertical => {
main_y = resized.top + half_height + (half_height - half_resized_height); main_y = resized.top + half_height + (half_height - half_resized_height);
alt_y = resized.top; alt_y = resized.top;
main_x = resized.left; main_x = resized.left;
alt_x = resized.left + half_resized_width; alt_x = resized.left + half_resized_width;
} }
Flip::HorizontalAndVertical => { Axis::HorizontalAndVertical => {
main_x = resized.left + half_width + (half_width - half_resized_width); main_x = resized.left + half_width + (half_width - half_resized_width);
alt_x = resized.left; alt_x = resized.left;
main_y = resized.top + half_height + (half_height - half_resized_height); main_y = resized.top + half_height + (half_height - half_resized_height);
+4 -3
View File
@@ -12,7 +12,7 @@ use strum::Display;
use strum::EnumString; use strum::EnumString;
pub use arrangement::Arrangement; pub use arrangement::Arrangement;
pub use arrangement::Flip; pub use arrangement::Axis;
pub use custom_layout::CustomLayout; pub use custom_layout::CustomLayout;
pub use cycle_direction::CycleDirection; pub use cycle_direction::CycleDirection;
pub use default_layout::DefaultLayout; pub use default_layout::DefaultLayout;
@@ -39,7 +39,8 @@ pub enum SocketMessage {
CycleFocusWindow(CycleDirection), CycleFocusWindow(CycleDirection),
CycleMoveWindow(CycleDirection), CycleMoveWindow(CycleDirection),
StackWindow(OperationDirection), StackWindow(OperationDirection),
ResizeWindow(OperationDirection, Sizing), ResizeWindowEdge(OperationDirection, Sizing),
ResizeWindowAxis(Axis, Sizing),
UnstackWindow, UnstackWindow,
CycleStack(CycleDirection), CycleStack(CycleDirection),
MoveContainerToMonitorNumber(usize), MoveContainerToMonitorNumber(usize),
@@ -57,7 +58,7 @@ pub enum SocketMessage {
AdjustWorkspacePadding(Sizing, i32), AdjustWorkspacePadding(Sizing, i32),
ChangeLayout(DefaultLayout), ChangeLayout(DefaultLayout),
ChangeLayoutCustom(PathBuf), ChangeLayoutCustom(PathBuf),
FlipLayout(Flip), FlipLayout(Axis),
// Monitor and Workspace Commands // Monitor and Workspace Commands
EnsureWorkspaces(usize, usize), EnsureWorkspaces(usize, usize),
NewWorkspace, NewWorkspace,
+11 -11
View File
@@ -7,7 +7,7 @@ use strum::Display;
use strum::EnumString; use strum::EnumString;
use crate::direction::Direction; use crate::direction::Direction;
use crate::Flip; use crate::Axis;
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)] #[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)]
#[strum(serialize_all = "snake_case")] #[strum(serialize_all = "snake_case")]
@@ -29,23 +29,23 @@ impl OperationDirection {
} }
} }
fn flip(self, layout_flip: Option<Flip>) -> Self { fn flip(self, layout_flip: Option<Axis>) -> Self {
layout_flip.map_or(self, |flip| match self { layout_flip.map_or(self, |flip| match self {
Self::Left => match flip { Self::Left => match flip {
Flip::Horizontal | Flip::HorizontalAndVertical => Self::Right, Axis::Horizontal | Axis::HorizontalAndVertical => Self::Right,
Flip::Vertical => self, Axis::Vertical => self,
}, },
Self::Right => match flip { Self::Right => match flip {
Flip::Horizontal | Flip::HorizontalAndVertical => Self::Left, Axis::Horizontal | Axis::HorizontalAndVertical => Self::Left,
Flip::Vertical => self, Axis::Vertical => self,
}, },
Self::Up => match flip { Self::Up => match flip {
Flip::Vertical | Flip::HorizontalAndVertical => Self::Down, Axis::Vertical | Axis::HorizontalAndVertical => Self::Down,
Flip::Horizontal => self, Axis::Horizontal => self,
}, },
Self::Down => match flip { Self::Down => match flip {
Flip::Vertical | Flip::HorizontalAndVertical => Self::Up, Axis::Vertical | Axis::HorizontalAndVertical => Self::Up,
Flip::Horizontal => self, Axis::Horizontal => self,
}, },
}) })
} }
@@ -54,7 +54,7 @@ impl OperationDirection {
pub fn destination( pub fn destination(
self, self,
layout: &dyn Direction, layout: &dyn Direction,
layout_flip: Option<Flip>, layout_flip: Option<Axis>,
idx: usize, idx: usize,
len: NonZeroUsize, len: NonZeroUsize,
) -> Option<usize> { ) -> Option<usize> {
+63 -2
View File
@@ -15,7 +15,9 @@ use miow::pipe::connect;
use parking_lot::Mutex; use parking_lot::Mutex;
use uds_windows::UnixStream; use uds_windows::UnixStream;
use komorebi_core::Axis;
use komorebi_core::FocusFollowsMouseImplementation; use komorebi_core::FocusFollowsMouseImplementation;
use komorebi_core::OperationDirection;
use komorebi_core::Rect; use komorebi_core::Rect;
use komorebi_core::SocketMessage; use komorebi_core::SocketMessage;
use komorebi_core::StateQuery; use komorebi_core::StateQuery;
@@ -260,8 +262,67 @@ impl WindowManager {
let mut stream = UnixStream::connect(&socket)?; let mut stream = UnixStream::connect(&socket)?;
stream.write_all(response.as_bytes())?; stream.write_all(response.as_bytes())?;
} }
SocketMessage::ResizeWindow(direction, sizing) => { SocketMessage::ResizeWindowEdge(direction, sizing) => {
self.resize_window(direction, sizing, Option::from(50))?; self.resize_window(direction, sizing, Option::from(50), true)?;
}
SocketMessage::ResizeWindowAxis(axis, sizing) => {
match axis {
Axis::Horizontal => {
self.resize_window(
OperationDirection::Left,
sizing,
Option::from(50),
false,
)?;
self.resize_window(
OperationDirection::Right,
sizing,
Option::from(50),
false,
)?;
}
Axis::Vertical => {
self.resize_window(
OperationDirection::Up,
sizing,
Option::from(50),
false,
)?;
self.resize_window(
OperationDirection::Down,
sizing,
Option::from(50),
false,
)?;
}
Axis::HorizontalAndVertical => {
self.resize_window(
OperationDirection::Left,
sizing,
Option::from(50),
false,
)?;
self.resize_window(
OperationDirection::Right,
sizing,
Option::from(50),
false,
)?;
self.resize_window(
OperationDirection::Up,
sizing,
Option::from(50),
false,
)?;
self.resize_window(
OperationDirection::Down,
sizing,
Option::from(50),
false,
)?;
}
}
self.update_focused_workspace(false)?;
} }
SocketMessage::FocusFollowsMouse(mut implementation, enable) => { SocketMessage::FocusFollowsMouse(mut implementation, enable) => {
if !CUSTOM_FFM.load(Ordering::SeqCst) { if !CUSTOM_FFM.load(Ordering::SeqCst) {
+1 -1
View File
@@ -384,7 +384,7 @@ impl WindowManager {
} }
for (edge, sizing, step) in ops { for (edge, sizing, step) in ops {
self.resize_window(edge, sizing, Option::from(step))?; self.resize_window(edge, sizing, Option::from(step), true)?;
} }
self.update_focused_workspace(false)?; self.update_focused_workspace(false)?;
+28 -22
View File
@@ -16,9 +16,9 @@ use uds_windows::UnixListener;
use komorebi_core::custom_layout::CustomLayout; use komorebi_core::custom_layout::CustomLayout;
use komorebi_core::Arrangement; use komorebi_core::Arrangement;
use komorebi_core::Axis;
use komorebi_core::CycleDirection; use komorebi_core::CycleDirection;
use komorebi_core::DefaultLayout; use komorebi_core::DefaultLayout;
use komorebi_core::Flip;
use komorebi_core::FocusFollowsMouseImplementation; use komorebi_core::FocusFollowsMouseImplementation;
use komorebi_core::Layout; use komorebi_core::Layout;
use komorebi_core::OperationDirection; use komorebi_core::OperationDirection;
@@ -677,6 +677,7 @@ impl WindowManager {
direction: OperationDirection, direction: OperationDirection,
sizing: Sizing, sizing: Sizing,
step: Option<i32>, step: Option<i32>,
update: bool,
) -> Result<()> { ) -> Result<()> {
let work_area = self.focused_monitor_work_area()?; let work_area = self.focused_monitor_work_area()?;
let workspace = self.focused_workspace_mut()?; let workspace = self.focused_workspace_mut()?;
@@ -715,21 +716,21 @@ impl WindowManager {
// can flip them however they need to be flipped once the resizing has been done // can flip them however they need to be flipped once the resizing has been done
if let Some(flip) = workspace.layout_flip() { if let Some(flip) = workspace.layout_flip() {
match flip { match flip {
Flip::Horizontal => { Axis::Horizontal => {
if matches!(direction, OperationDirection::Left) if matches!(direction, OperationDirection::Left)
|| matches!(direction, OperationDirection::Right) || matches!(direction, OperationDirection::Right)
{ {
direction = direction.opposite(); direction = direction.opposite();
} }
} }
Flip::Vertical => { Axis::Vertical => {
if matches!(direction, OperationDirection::Up) if matches!(direction, OperationDirection::Up)
|| matches!(direction, OperationDirection::Down) || matches!(direction, OperationDirection::Down)
{ {
direction = direction.opposite(); direction = direction.opposite();
} }
} }
Flip::HorizontalAndVertical => direction = direction.opposite(), Axis::HorizontalAndVertical => direction = direction.opposite(),
} }
} }
@@ -744,7 +745,12 @@ impl WindowManager {
); );
workspace.resize_dimensions_mut()[focused_idx] = resize; workspace.resize_dimensions_mut()[focused_idx] = resize;
return self.update_focused_workspace(false);
return if update {
self.update_focused_workspace(false)
} else {
Ok(())
};
} }
tracing::warn!("cannot resize container in this direction"); tracing::warn!("cannot resize container in this direction");
@@ -1085,7 +1091,7 @@ impl WindowManager {
} }
#[tracing::instrument(skip(self))] #[tracing::instrument(skip(self))]
pub fn flip_layout(&mut self, layout_flip: Flip) -> Result<()> { pub fn flip_layout(&mut self, layout_flip: Axis) -> Result<()> {
tracing::info!("flipping layout"); tracing::info!("flipping layout");
let workspace = self.focused_workspace_mut()?; let workspace = self.focused_workspace_mut()?;
@@ -1097,28 +1103,28 @@ impl WindowManager {
} }
Some(current_layout_flip) => { Some(current_layout_flip) => {
match current_layout_flip { match current_layout_flip {
Flip::Horizontal => match layout_flip { Axis::Horizontal => match layout_flip {
Flip::Horizontal => workspace.set_layout_flip(None), Axis::Horizontal => workspace.set_layout_flip(None),
Flip::Vertical => { Axis::Vertical => {
workspace.set_layout_flip(Option::from(Flip::HorizontalAndVertical)) workspace.set_layout_flip(Option::from(Axis::HorizontalAndVertical))
} }
Flip::HorizontalAndVertical => { Axis::HorizontalAndVertical => {
workspace.set_layout_flip(Option::from(Flip::HorizontalAndVertical)) workspace.set_layout_flip(Option::from(Axis::HorizontalAndVertical))
} }
}, },
Flip::Vertical => match layout_flip { Axis::Vertical => match layout_flip {
Flip::Horizontal => { Axis::Horizontal => {
workspace.set_layout_flip(Option::from(Flip::HorizontalAndVertical)) workspace.set_layout_flip(Option::from(Axis::HorizontalAndVertical))
} }
Flip::Vertical => workspace.set_layout_flip(None), Axis::Vertical => workspace.set_layout_flip(None),
Flip::HorizontalAndVertical => { Axis::HorizontalAndVertical => {
workspace.set_layout_flip(Option::from(Flip::HorizontalAndVertical)) workspace.set_layout_flip(Option::from(Axis::HorizontalAndVertical))
} }
}, },
Flip::HorizontalAndVertical => match layout_flip { Axis::HorizontalAndVertical => match layout_flip {
Flip::Horizontal => workspace.set_layout_flip(Option::from(Flip::Vertical)), Axis::Horizontal => workspace.set_layout_flip(Option::from(Axis::Vertical)),
Flip::Vertical => workspace.set_layout_flip(Option::from(Flip::Horizontal)), Axis::Vertical => workspace.set_layout_flip(Option::from(Axis::Horizontal)),
Flip::HorizontalAndVertical => workspace.set_layout_flip(None), Axis::HorizontalAndVertical => workspace.set_layout_flip(None),
}, },
}; };
} }
+2 -2
View File
@@ -9,9 +9,9 @@ use getset::MutGetters;
use getset::Setters; use getset::Setters;
use serde::Serialize; use serde::Serialize;
use komorebi_core::Axis;
use komorebi_core::CycleDirection; use komorebi_core::CycleDirection;
use komorebi_core::DefaultLayout; use komorebi_core::DefaultLayout;
use komorebi_core::Flip;
use komorebi_core::Layout; use komorebi_core::Layout;
use komorebi_core::OperationDirection; use komorebi_core::OperationDirection;
use komorebi_core::Rect; use komorebi_core::Rect;
@@ -41,7 +41,7 @@ pub struct Workspace {
#[getset(get = "pub", set = "pub")] #[getset(get = "pub", set = "pub")]
layout: Layout, layout: Layout,
#[getset(get_copy = "pub", set = "pub")] #[getset(get_copy = "pub", set = "pub")]
layout_flip: Option<Flip>, layout_flip: Option<Axis>,
#[getset(get_copy = "pub", set = "pub")] #[getset(get_copy = "pub", set = "pub")]
workspace_padding: Option<i32>, workspace_padding: Option<i32>,
#[getset(get_copy = "pub", set = "pub")] #[getset(get_copy = "pub", set = "pub")]
+6 -2
View File
@@ -68,6 +68,10 @@ Resize(edge, sizing) {
Run, komorebic.exe resize %edge% %sizing%, , Hide Run, komorebic.exe resize %edge% %sizing%, , Hide
} }
ResizeAxis(axis, sizing) {
Run, komorebic.exe resize-axis %axis% %sizing%, , Hide
}
Unstack() { Unstack() {
Run, komorebic.exe unstack, , Hide Run, komorebic.exe unstack, , Hide
} }
@@ -136,8 +140,8 @@ LoadCustomLayout(path) {
Run, komorebic.exe load-custom-layout %path%, , Hide Run, komorebic.exe load-custom-layout %path%, , Hide
} }
FlipLayout(flip) { FlipLayout(axis) {
Run, komorebic.exe flip-layout %flip%, , Hide Run, komorebic.exe flip-layout %axis%, , Hide
} }
Promote() { Promote() {
+20 -4
View File
@@ -28,9 +28,9 @@ use windows::Win32::UI::WindowsAndMessaging::SW_RESTORE;
use derive_ahk::AhkFunction; use derive_ahk::AhkFunction;
use derive_ahk::AhkLibrary; use derive_ahk::AhkLibrary;
use komorebi_core::ApplicationIdentifier; use komorebi_core::ApplicationIdentifier;
use komorebi_core::Axis;
use komorebi_core::CycleDirection; use komorebi_core::CycleDirection;
use komorebi_core::DefaultLayout; use komorebi_core::DefaultLayout;
use komorebi_core::Flip;
use komorebi_core::FocusFollowsMouseImplementation; use komorebi_core::FocusFollowsMouseImplementation;
use komorebi_core::OperationDirection; use komorebi_core::OperationDirection;
use komorebi_core::Rect; use komorebi_core::Rect;
@@ -85,7 +85,7 @@ gen_enum_subcommand_args! {
CycleWorkspace: CycleDirection, CycleWorkspace: CycleDirection,
Stack: OperationDirection, Stack: OperationDirection,
CycleStack: CycleDirection, CycleStack: CycleDirection,
FlipLayout: Flip, FlipLayout: Axis,
ChangeLayout: DefaultLayout, ChangeLayout: DefaultLayout,
WatchConfiguration: BooleanState, WatchConfiguration: BooleanState,
MouseFollowsFocus: BooleanState, MouseFollowsFocus: BooleanState,
@@ -168,6 +168,14 @@ struct Resize {
sizing: Sizing, sizing: Sizing,
} }
#[derive(Parser, AhkFunction)]
struct ResizeAxis {
#[clap(arg_enum)]
axis: Axis,
#[clap(arg_enum)]
sizing: Sizing,
}
#[derive(Parser, AhkFunction)] #[derive(Parser, AhkFunction)]
struct InvisibleBorders { struct InvisibleBorders {
/// Size of the left invisible border /// Size of the left invisible border
@@ -381,6 +389,9 @@ enum SubCommand {
/// Resize the focused window in the specified direction /// Resize the focused window in the specified direction
#[clap(setting = AppSettings::ArgRequiredElseHelp)] #[clap(setting = AppSettings::ArgRequiredElseHelp)]
Resize(Resize), Resize(Resize),
/// Resize the focused window along the specified axis
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
ResizeAxis(ResizeAxis),
/// Unstack the focused window /// Unstack the focused window
Unstack, Unstack,
/// Cycle the focused stack in the specified cycle direction /// Cycle the focused stack in the specified cycle direction
@@ -757,7 +768,7 @@ fn main() -> Result<()> {
)?; )?;
} }
SubCommand::FlipLayout(arg) => { SubCommand::FlipLayout(arg) => {
send_message(&*SocketMessage::FlipLayout(arg.flip).as_bytes()?)?; send_message(&*SocketMessage::FlipLayout(arg.axis).as_bytes()?)?;
} }
SubCommand::FocusMonitor(arg) => { SubCommand::FocusMonitor(arg) => {
send_message(&*SocketMessage::FocusMonitorNumber(arg.target).as_bytes()?)?; send_message(&*SocketMessage::FocusMonitorNumber(arg.target).as_bytes()?)?;
@@ -868,7 +879,12 @@ fn main() -> Result<()> {
} }
} }
SubCommand::Resize(resize) => { SubCommand::Resize(resize) => {
send_message(&*SocketMessage::ResizeWindow(resize.edge, resize.sizing).as_bytes()?)?; send_message(
&*SocketMessage::ResizeWindowEdge(resize.edge, resize.sizing).as_bytes()?,
)?;
}
SubCommand::ResizeAxis(arg) => {
send_message(&*SocketMessage::ResizeWindowAxis(arg.axis, arg.sizing).as_bytes()?)?;
} }
SubCommand::FocusFollowsMouse(arg) => { SubCommand::FocusFollowsMouse(arg) => {
send_message( send_message(