Skip to content

Commit

Permalink
#417 prevent space operations from applying when mission-control is a…
Browse files Browse the repository at this point in the history
…ctive or display is animating
  • Loading branch information
koekeishiya committed Feb 26, 2020
1 parent f4944a2 commit 9e8c386
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 23 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
## [Unreleased]
### Changed
- Properly return focus to the active window on the current space when a window is moved through a rule [#418](https://github.com/koekeishiya/yabai/issues/418)
- Prevent space operations (create, destroy, focus, swap, move and send to display) from applying while mission-control is active or the display is animating [#417](https://github.com/koekeishiya/yabai/issues/417)

## [2.3.0] - 2020-02-14
### Added
Expand Down
34 changes: 32 additions & 2 deletions src/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -1295,7 +1295,14 @@ static void handle_domain_space(FILE *rsp, struct token domain, char *message)
if (token_equals(command, COMMAND_SPACE_FOCUS)) {
struct selector selector = parse_space_selector(rsp, &message, acting_sid);
if (selector.did_parse && selector.sid) {
space_manager_focus_space(selector.sid);
enum space_op_error result = space_manager_focus_space(selector.sid);
if (result == SPACE_OP_ERROR_SAME_SPACE) {
daemon_fail(rsp, "cannot focus an already focused space.\n");
} else if (result == SPACE_OP_ERROR_DISPLAY_IS_ANIMATING) {
daemon_fail(rsp, "cannot focus space because the display is in the middle of an animation.\n");
} else if (result == SPACE_OP_ERROR_IN_MISSION_CONTROL) {
daemon_fail(rsp, "cannot focus space because mission-control is active.\n");
}
}
} else if (token_equals(command, COMMAND_SPACE_MOVE)) {
struct selector selector = parse_space_selector(rsp, &message, acting_sid);
Expand All @@ -1305,6 +1312,10 @@ static void handle_domain_space(FILE *rsp, struct token domain, char *message)
daemon_fail(rsp, "cannot move space to itself.\n");
} else if (result == SPACE_OP_ERROR_SAME_DISPLAY) {
daemon_fail(rsp, "cannot move space across display boundaries. use --display instead.\n");
} else if (result == SPACE_OP_ERROR_DISPLAY_IS_ANIMATING) {
daemon_fail(rsp, "cannot move space because the display is in the middle of an animation.\n");
} else if (result == SPACE_OP_ERROR_IN_MISSION_CONTROL) {
daemon_fail(rsp, "cannot move space because mission-control is active.\n");
}
}
} else if (token_equals(command, COMMAND_SPACE_SWAP)) {
Expand All @@ -1315,6 +1326,10 @@ static void handle_domain_space(FILE *rsp, struct token domain, char *message)
daemon_fail(rsp, "cannot swap space with itself.\n");
} else if (result == SPACE_OP_ERROR_SAME_DISPLAY) {
daemon_fail(rsp, "cannot swap space across display boundaries. use --display instead.\n");
} else if (result == SPACE_OP_ERROR_DISPLAY_IS_ANIMATING) {
daemon_fail(rsp, "cannot swap space because the display is in the middle of an animation.\n");
} else if (result == SPACE_OP_ERROR_IN_MISSION_CONTROL) {
daemon_fail(rsp, "cannot swap space because mission-control is active.\n");
}
}
} else if (token_equals(command, COMMAND_SPACE_DISPLAY)) {
Expand All @@ -1329,10 +1344,21 @@ static void handle_domain_space(FILE *rsp, struct token domain, char *message)
daemon_fail(rsp, "acting space is the last user-space on the source display and cannot be moved.\n");
} else if (result == SPACE_OP_ERROR_INVALID_DST) {
daemon_fail(rsp, "acting space is already located on the given display.\n");
} else if (result == SPACE_OP_ERROR_DISPLAY_IS_ANIMATING) {
daemon_fail(rsp, "cannot send space to display because it is in the middle of an animation.\n");
} else if (result == SPACE_OP_ERROR_IN_MISSION_CONTROL) {
daemon_fail(rsp, "cannot send space to display because mission-control is active.\n");
}
}
} else if (token_equals(command, COMMAND_SPACE_CREATE)) {
space_manager_add_space(acting_sid);
enum space_op_error result = space_manager_add_space(acting_sid);
if (result == SPACE_OP_ERROR_MISSING_SRC) {
daemon_fail(rsp, "could not locate the space to act on.\n");
} else if (result == SPACE_OP_ERROR_DISPLAY_IS_ANIMATING) {
daemon_fail(rsp, "cannot create space because the display is in the middle of an animation.\n");
} else if (result == SPACE_OP_ERROR_IN_MISSION_CONTROL) {
daemon_fail(rsp, "cannot create space because mission-control is active.\n");
}
} else if (token_equals(command, COMMAND_SPACE_DESTROY)) {
enum space_op_error result = space_manager_destroy_space(acting_sid);
if (result == SPACE_OP_ERROR_MISSING_SRC) {
Expand All @@ -1341,6 +1367,10 @@ static void handle_domain_space(FILE *rsp, struct token domain, char *message)
daemon_fail(rsp, "acting space is the last user-space on the source display and cannot be destroyed.\n");
} else if (result == SPACE_OP_ERROR_INVALID_TYPE) {
daemon_fail(rsp, "cannot destroy a macOS fullscreen space.\n");
} else if (result == SPACE_OP_ERROR_DISPLAY_IS_ANIMATING) {
daemon_fail(rsp, "cannot destroy space because the display is in the middle of an animation.\n");
} else if (result == SPACE_OP_ERROR_IN_MISSION_CONTROL) {
daemon_fail(rsp, "cannot destroy space because mission-control is active.\n");
}
} else if (token_equals(command, COMMAND_SPACE_BALANCE)) {
space_manager_balance_space(&g_space_manager, acting_sid);
Expand Down
68 changes: 57 additions & 11 deletions src/space_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

extern struct window_manager g_window_manager;
extern char g_sa_socket_file[MAXLEN];
extern bool g_mission_control_active;
extern int g_connection;

static TABLE_HASH_FUNC(hash_view)
Expand Down Expand Up @@ -595,25 +596,34 @@ void space_manager_move_window_to_space(uint64_t sid, struct window *window)
CFRelease(window_list_ref);
}

void space_manager_focus_space(uint64_t sid)
enum space_op_error space_manager_focus_space(uint64_t sid)
{
int sockfd;
char message[MAXLEN];

bool is_in_mc = g_mission_control_active;
if (is_in_mc) return SPACE_OP_ERROR_IN_MISSION_CONTROL;

uint64_t cur_sid = space_manager_active_space();
if (cur_sid == sid) return SPACE_OP_ERROR_SAME_SPACE;

uint32_t cur_did = space_display_id(cur_sid);
uint32_t new_did = space_display_id(sid);
bool focus_display = cur_did != new_did;

bool is_animating = display_manager_display_is_animating(new_did);
if (is_animating) return SPACE_OP_ERROR_DISPLAY_IS_ANIMATING;

if (socket_connect_un(&sockfd, g_sa_socket_file)) {
snprintf(message, sizeof(message), "space %lld", sid);
socket_write(sockfd, message);
socket_wait(sockfd);

if (cur_did != new_did) {
display_manager_focus_display(new_did);
}
if (focus_display) display_manager_focus_display(new_did);
}
socket_close(sockfd);

return SPACE_OP_ERROR_SUCCESS;
}

static inline bool space_manager_is_space_last_user_space(uint64_t sid)
Expand Down Expand Up @@ -656,12 +666,18 @@ static void space_manager_move_space_after_space(uint64_t src_sid, uint64_t dst_

enum space_op_error space_manager_swap_space_with_space(uint64_t acting_sid, uint64_t selector_sid)
{
bool is_in_mc = g_mission_control_active;
if (is_in_mc) return SPACE_OP_ERROR_IN_MISSION_CONTROL;

uint32_t acting_did = space_display_id(acting_sid);
uint32_t selector_did = space_display_id(selector_sid);

if (acting_sid == selector_sid) return SPACE_OP_ERROR_SAME_SPACE;
if (acting_did != selector_did) return SPACE_OP_ERROR_SAME_DISPLAY;

bool is_animating = display_manager_display_is_animating(acting_did);
if (is_animating) return SPACE_OP_ERROR_DISPLAY_IS_ANIMATING;

uint64_t acting_prev_sid = space_manager_prev_space(acting_sid);
uint64_t selector_prev_sid = space_manager_prev_space(selector_sid);

Expand Down Expand Up @@ -699,12 +715,18 @@ enum space_op_error space_manager_swap_space_with_space(uint64_t acting_sid, uin

enum space_op_error space_manager_move_space_to_space(uint64_t acting_sid, uint64_t selector_sid)
{
bool is_in_mc = g_mission_control_active;
if (is_in_mc) return SPACE_OP_ERROR_IN_MISSION_CONTROL;

uint32_t acting_did = space_display_id(acting_sid);
uint32_t selector_did = space_display_id(selector_sid);

if (acting_sid == selector_sid) return SPACE_OP_ERROR_SAME_SPACE;
if (acting_did != selector_did) return SPACE_OP_ERROR_SAME_DISPLAY;

bool is_animating = display_manager_display_is_animating(acting_did);
if (is_animating) return SPACE_OP_ERROR_DISPLAY_IS_ANIMATING;

uint64_t acting_prev_sid = space_manager_prev_space(acting_sid);
uint64_t selector_prev_sid = space_manager_prev_space(selector_sid);

Expand Down Expand Up @@ -733,14 +755,25 @@ enum space_op_error space_manager_move_space_to_space(uint64_t acting_sid, uint6
enum space_op_error space_manager_move_space_to_display(struct space_manager *sm, uint64_t sid, uint32_t did)
{
int sockfd;
uint64_t d_sid;
char message[MAXLEN];

if (!sid) return SPACE_OP_ERROR_MISSING_SRC;
if (space_display_id(sid) == did) return SPACE_OP_ERROR_INVALID_DST;
if (space_manager_is_space_last_user_space(sid)) return SPACE_OP_ERROR_INVALID_SRC;
bool is_in_mc = g_mission_control_active;
if (is_in_mc) return SPACE_OP_ERROR_IN_MISSION_CONTROL;
if (!sid) return SPACE_OP_ERROR_MISSING_SRC;

uint32_t s_did = space_display_id(sid);
if (s_did == did) return SPACE_OP_ERROR_INVALID_DST;

bool is_src_animating = display_manager_display_is_animating(s_did);
if (is_src_animating) return SPACE_OP_ERROR_DISPLAY_IS_ANIMATING;

bool last_space = space_manager_is_space_last_user_space(sid);
if (last_space) return SPACE_OP_ERROR_INVALID_SRC;

bool is_dst_animating = display_manager_display_is_animating(did);
if (is_dst_animating) return SPACE_OP_ERROR_DISPLAY_IS_ANIMATING;

d_sid = display_space_id(did);
uint64_t d_sid = display_space_id(did);
if (!d_sid) return SPACE_OP_ERROR_MISSING_DST;

if (socket_connect_un(&sockfd, g_sa_socket_file)) {
Expand All @@ -761,10 +794,16 @@ enum space_op_error space_manager_destroy_space(uint64_t sid)
int sockfd;
char message[MAXLEN];

bool is_in_mc = g_mission_control_active;
if (is_in_mc) return SPACE_OP_ERROR_IN_MISSION_CONTROL;

if (!sid) return SPACE_OP_ERROR_MISSING_SRC;
if (!space_is_user(sid)) return SPACE_OP_ERROR_INVALID_TYPE;
if (space_manager_is_space_last_user_space(sid)) return SPACE_OP_ERROR_INVALID_SRC;

bool is_animating = display_manager_display_is_animating(space_display_id(sid));
if (is_animating) return SPACE_OP_ERROR_DISPLAY_IS_ANIMATING;

if (socket_connect_un(&sockfd, g_sa_socket_file)) {
snprintf(message, sizeof(message), "space_destroy %lld", sid);
socket_write(sockfd, message);
Expand All @@ -775,19 +814,26 @@ enum space_op_error space_manager_destroy_space(uint64_t sid)
return SPACE_OP_ERROR_SUCCESS;
}

void space_manager_add_space(uint64_t sid)
enum space_op_error space_manager_add_space(uint64_t sid)
{
int sockfd;
char message[MAXLEN];

if (!sid) return;
bool is_in_mc = g_mission_control_active;
if (is_in_mc) return SPACE_OP_ERROR_IN_MISSION_CONTROL;
if (!sid) return SPACE_OP_ERROR_MISSING_SRC;

bool is_animating = display_manager_display_is_animating(space_display_id(sid));
if (is_animating) return SPACE_OP_ERROR_DISPLAY_IS_ANIMATING;

if (socket_connect_un(&sockfd, g_sa_socket_file)) {
snprintf(message, sizeof(message), "space_create %lld", sid);
socket_write(sockfd, message);
socket_wait(sockfd);
}
socket_close(sockfd);

return SPACE_OP_ERROR_SUCCESS;
}

void space_manager_assign_process_to_space(pid_t pid, uint64_t sid)
Expand Down
22 changes: 12 additions & 10 deletions src/space_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,16 @@ struct space_manager

enum space_op_error
{
SPACE_OP_ERROR_SUCCESS = 0,
SPACE_OP_ERROR_MISSING_SRC = 1,
SPACE_OP_ERROR_MISSING_DST = 2,
SPACE_OP_ERROR_INVALID_SRC = 3,
SPACE_OP_ERROR_INVALID_DST = 4,
SPACE_OP_ERROR_INVALID_TYPE = 5,
SPACE_OP_ERROR_SAME_SPACE = 6,
SPACE_OP_ERROR_SAME_DISPLAY = 7,
SPACE_OP_ERROR_SUCCESS = 0,
SPACE_OP_ERROR_MISSING_SRC = 1,
SPACE_OP_ERROR_MISSING_DST = 2,
SPACE_OP_ERROR_INVALID_SRC = 3,
SPACE_OP_ERROR_INVALID_DST = 4,
SPACE_OP_ERROR_INVALID_TYPE = 5,
SPACE_OP_ERROR_SAME_SPACE = 6,
SPACE_OP_ERROR_SAME_DISPLAY = 7,
SPACE_OP_ERROR_DISPLAY_IS_ANIMATING = 8,
SPACE_OP_ERROR_IN_MISSION_CONTROL = 9,
};

bool space_manager_has_separate_spaces(void);
Expand Down Expand Up @@ -85,12 +87,12 @@ void space_manager_toggle_padding_for_space(struct space_manager *sm, uint64_t s
void space_manager_rotate_space(struct space_manager *sm, uint64_t sid, int degrees);
void space_manager_mirror_space(struct space_manager *sm, uint64_t sid, enum window_node_split axis);
void space_manager_move_window_to_space(uint64_t sid, struct window *window);
void space_manager_focus_space(uint64_t sid);
enum space_op_error space_manager_focus_space(uint64_t sid);
enum space_op_error space_manager_swap_space_with_space(uint64_t acting_sid, uint64_t selector_sid);
enum space_op_error space_manager_move_space_to_space(uint64_t acting_sid, uint64_t selector_sid);
enum space_op_error space_manager_move_space_to_display(struct space_manager *sm, uint64_t sid, uint32_t did);
enum space_op_error space_manager_destroy_space(uint64_t sid);
void space_manager_add_space(uint64_t sid);
enum space_op_error space_manager_add_space(uint64_t sid);
void space_manager_assign_process_to_space(pid_t pid, uint64_t sid);
void space_manager_assign_process_to_all_spaces(pid_t pid);
bool space_manager_is_window_on_active_space(struct window *window);
Expand Down

0 comments on commit 9e8c386

Please sign in to comment.