feat(custom_layout): implement navigation

This commit introduces a number of refactors to layouts in general in
order to enable navigation across custom layouts and integrate both
default and custom layouts cleanly into komorebi and komorebic.

Layout has been renamed to DefaultLayout, and Layout is now an enum with
the variants Default and Custom, both of which implement the new traits
Arrangement (for layout calculation) and Direction (for operation
destination calculation).

CustomLayout has been simplified to wrap Vec<Column> and no longer
requires the primary column index to be explicitly defined as this can
be looked up at runtime for any valid CustomLayout.

Given the focus on ultrawide layouts for this feature, I have disabled
(and have not yet written the logic for) vertical column splits in
custom layouts.

Since CustomLayouts will be loaded from a file path, a bunch of
clap-related code generation stuff has been removed from the related
enums and structs.

Layout flipping has not yet been worked on for custom layouts.

When switching between Default and Custom layout variants, the primary
column index and the 0 element are swapped to ensure that the same
window container is always at the focal point of every layout.

Resizing/dragging to resize is in a bit of weird spot at the moment
because the logic is only implemented for DefaultLayout::BSP right now
and nothing else. I think eventually this will need to be extracted to a
Resize trait and implemented on everything.
This commit is contained in:
LGUG2Z
2021-10-18 07:09:44 -07:00
parent f19bd3032b
commit ac0f33f7ed
11 changed files with 1350 additions and 919 deletions

View File

@@ -29,9 +29,9 @@ use derive_ahk::AhkFunction;
use derive_ahk::AhkLibrary;
use komorebi_core::ApplicationIdentifier;
use komorebi_core::CycleDirection;
use komorebi_core::DefaultLayout;
use komorebi_core::Flip;
use komorebi_core::FocusFollowsMouseImplementation;
use komorebi_core::Layout;
use komorebi_core::OperationDirection;
use komorebi_core::Rect;
use komorebi_core::Sizing;
@@ -86,7 +86,7 @@ gen_enum_subcommand_args! {
Stack: OperationDirection,
CycleStack: CycleDirection,
FlipLayout: Flip,
ChangeLayout: Layout,
ChangeLayout: DefaultLayout,
WatchConfiguration: BooleanState,
Query: StateQuery,
}
@@ -143,7 +143,8 @@ macro_rules! gen_workspace_subcommand_args {
gen_workspace_subcommand_args! {
Name: String,
Layout: #[enum] Layout,
Layout: #[enum] DefaultLayout,
CustomLayout: String,
Tiling: #[enum] BooleanState,
}
@@ -296,6 +297,12 @@ struct Load {
path: String,
}
#[derive(Clap, AhkFunction)]
struct LoadLayout {
/// File from which the custom layout definition should be loaded
path: String,
}
#[derive(Clap)]
#[clap(author, about, version, setting = AppSettings::DeriveDisplayOrder)]
struct Opts {
@@ -390,6 +397,9 @@ enum SubCommand {
/// Set the layout on the focused workspace
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
ChangeLayout(ChangeLayout),
/// Load a custom layout from file for the focused workspace
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
LoadLayout(LoadLayout),
/// Flip the layout on the focused workspace (BSP only)
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
FlipLayout(FlipLayout),
@@ -409,6 +419,9 @@ enum SubCommand {
/// Set the layout for the specified workspace
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
WorkspaceLayout(WorkspaceLayout),
/// Set a custom layout for the specified workspace
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
WorkspaceCustomLayout(WorkspaceCustomLayout),
/// Enable or disable window tiling for the specified workspace
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
WorkspaceTiling(WorkspaceTiling),
@@ -607,6 +620,16 @@ fn main() -> Result<()> {
.as_bytes()?,
)?;
}
SubCommand::WorkspaceCustomLayout(arg) => {
send_message(
&*SocketMessage::WorkspaceLayoutCustom(
arg.monitor,
arg.workspace,
resolve_windows_path(&arg.value)?,
)
.as_bytes()?,
)?;
}
SubCommand::WorkspaceTiling(arg) => {
send_message(
&*SocketMessage::WorkspaceTiling(arg.monitor, arg.workspace, arg.value.into())
@@ -691,7 +714,12 @@ fn main() -> Result<()> {
send_message(&*SocketMessage::CycleStack(arg.cycle_direction).as_bytes()?)?;
}
SubCommand::ChangeLayout(arg) => {
send_message(&*SocketMessage::ChangeLayout(arg.layout).as_bytes()?)?;
send_message(&*SocketMessage::ChangeLayout(arg.default_layout).as_bytes()?)?;
}
SubCommand::LoadLayout(arg) => {
send_message(
&*SocketMessage::ChangeLayoutCustom(resolve_windows_path(&arg.path)?).as_bytes()?,
)?;
}
SubCommand::FlipLayout(arg) => {
send_message(&*SocketMessage::FlipLayout(arg.flip).as_bytes()?)?;