diff --git a/CHANGELOG.md b/CHANGELOG.md index 7906dbea..07d7a238 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added +- New command *space --swap SPACE_SEL* command to swap the position of a selected space with the position of a given space. The selected and given space must belong to the same display [#127](https://github.com/koekeishiya/yabai/issues/127) + ### Changed - Allow use of *DISPLAY_SEL* and *SPACE_SEL* for specifying display and space in rules [#378](https://github.com/koekeishiya/yabai/issues/378) - Extend *space --move* command to operate on *SPACE_SEL* instead of prev/next. However, the selected and given space must belong to the same display [#127](https://github.com/koekeishiya/yabai/issues/127) diff --git a/doc/yabai.1 b/doc/yabai.1 index 5db91810..bbc4c23f 100644 --- a/doc/yabai.1 +++ b/doc/yabai.1 @@ -322,6 +322,11 @@ Remove the selected space. Move position of the selected space to the position of the given space. The selected space and given space must both belong to the same display. .RE .sp +\fB\-\-swap\fP \fI\fP +.RS 4 +Swap the selected space with the given space. The selected space and given space must both belong to the same display. +.RE +.sp \fB\-\-display\fP \fI\fP .RS 4 Send the selected space to the given display. diff --git a/doc/yabai.asciidoc b/doc/yabai.asciidoc index 89f3043f..294a7192 100644 --- a/doc/yabai.asciidoc +++ b/doc/yabai.asciidoc @@ -245,6 +245,9 @@ COMMAND *--move* '':: Move position of the selected space to the position of the given space. The selected space and given space must both belong to the same display. +*--swap* '':: + Swap the selected space with the given space. The selected space and given space must both belong to the same display. + *--display* '':: Send the selected space to the given display. diff --git a/src/message.c b/src/message.c index 337720ea..16f86a12 100644 --- a/src/message.c +++ b/src/message.c @@ -87,6 +87,7 @@ extern bool g_verbose; #define COMMAND_SPACE_CREATE "--create" #define COMMAND_SPACE_DESTROY "--destroy" #define COMMAND_SPACE_MOVE "--move" +#define COMMAND_SPACE_SWAP "--swap" #define COMMAND_SPACE_DISPLAY "--display" #define COMMAND_SPACE_BALANCE "--balance" #define COMMAND_SPACE_MIRROR "--mirror" @@ -1319,6 +1320,37 @@ static void handle_domain_space(FILE *rsp, struct token domain, char *message) } } } + } else if (token_equals(command, COMMAND_SPACE_SWAP)) { + struct selector selector = parse_space_selector(rsp, &message, acting_sid); + if (selector.did_parse && selector.sid) { + if (acting_sid == selector.sid) { + daemon_fail(rsp, "cannot swap space with itself.\n"); + } else if (space_display_id(acting_sid) != space_display_id(selector.sid)) { + daemon_fail(rsp, "cannot swap space across display boundaries. use --display instead.\n"); + } else { + int acting_mci = space_manager_mission_control_index(acting_sid); + int selector_mci = space_manager_mission_control_index(selector.sid); + if (selector_mci == 1 && acting_mci == 2) { + space_manager_move_space_after_space(selector.sid, acting_sid, false); + } else if (selector_mci == 1 && acting_mci > 2) { + uint64_t prev_space = space_manager_prev_space(acting_sid); + space_manager_move_space_after_space(acting_sid, selector.sid, acting_sid == space_manager_active_space()); + space_manager_move_space_after_space(selector.sid, prev_space, false); + } else if (acting_mci == 1 && selector_mci > 2) { + uint64_t prev_space = space_manager_prev_space(selector.sid); + space_manager_move_space_after_space(selector.sid, acting_sid, false); + space_manager_move_space_after_space(acting_sid, prev_space, acting_sid == space_manager_active_space()); + } else if (acting_mci > selector_mci) { + uint64_t prev_space = space_manager_prev_space(selector.sid); + space_manager_move_space_after_space(selector.sid, acting_sid, false); + space_manager_move_space_after_space(acting_sid, prev_space, acting_sid == space_manager_active_space()); + } else { + uint64_t prev_space = space_manager_prev_space(acting_sid); + space_manager_move_space_after_space(acting_sid, selector.sid, acting_sid == space_manager_active_space()); + space_manager_move_space_after_space(selector.sid, prev_space, false); + } + } + } } else if (token_equals(command, COMMAND_SPACE_DISPLAY)) { struct selector selector = parse_display_selector(rsp, &message, display_manager_active_display_id()); if (selector.did_parse && selector.did) {