Skip to content

Commit

Permalink
#182 prevent last user-space from being destroyed or moved
Browse files Browse the repository at this point in the history
  • Loading branch information
koekeishiya committed Oct 1, 2019
1 parent 4475414 commit 9b6b8e2
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Changed
- Don't draw borders for minimized or hidden windows when a display is (dis)connected [#250](https://github.com/koekeishiya/yabai/issues/250)
- Sticky windows are no longer automatically topmost. New option to toggle window always on top through command or rule. New attribute topmost returned in window queries. [#255](https://github.com/koekeishiya/yabai/issues/255)
- Prevent the last user-space from being destroyed or moved to another display, because macOS does not actually support this [#182](https://github.com/koekeishiya/yabai/issues/182)

## [2.0.1] - 2019-09-04
### Changed
Expand Down
20 changes: 18 additions & 2 deletions src/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -1201,12 +1201,28 @@ static void handle_domain_space(FILE *rsp, struct token domain, char *message)
} 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) {
space_manager_move_space_to_display(&g_space_manager, acting_sid, selector.did);
enum space_op_error result = space_manager_move_space_to_display(&g_space_manager, acting_sid, selector.did);
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_MISSING_DST) {
daemon_fail(rsp, "could not locate the active space of the given display.\n");
} else if (result == SPACE_OP_ERROR_INVALID_SRC) {
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 (token_equals(command, COMMAND_SPACE_CREATE)) {
space_manager_add_space(acting_sid);
} else if (token_equals(command, COMMAND_SPACE_DESTROY)) {
space_manager_destroy_space(acting_sid);
enum space_op_error result = space_manager_destroy_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_INVALID_SRC) {
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 (token_equals(command, COMMAND_SPACE_BALANCE)) {
space_manager_balance_space(&g_space_manager, acting_sid);
} else if (token_equals(command, COMMAND_SPACE_MIRROR)) {
Expand Down
42 changes: 36 additions & 6 deletions src/space_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -619,17 +619,41 @@ void space_manager_move_space_after_space(uint64_t src_sid, uint64_t dst_sid, bo
socket_close(sockfd);
}

void space_manager_move_space_to_display(struct space_manager *sm, uint64_t sid, uint32_t did)
static inline bool
space_manager_is_space_last_user_space(uint64_t sid)
{
bool result = true;

int count;
uint64_t *space_list = display_space_list(space_display_id(sid), &count);
if (!space_list) return true;

for (int i = 0; i < count; ++i) {
uint64_t c_sid = space_list[i];
if (sid == c_sid) continue;

if (space_is_user(c_sid)) {
result = false;
break;
}
}
free(space_list);

return result;
}

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;
if (space_display_id(sid) == did) return;
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;

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

if (socket_connect_un(&sockfd, g_sa_socket_file)) {
snprintf(message, sizeof(message), "space_move %lld %lld 1", sid, d_sid);
Expand All @@ -640,21 +664,27 @@ void space_manager_move_space_to_display(struct space_manager *sm, uint64_t sid,

space_manager_mark_view_invalid(sm, sid);
space_manager_focus_space(sid);

return SPACE_OP_ERROR_SUCCESS;
}

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

if (!sid || !space_is_user(sid)) return;
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;

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

return SPACE_OP_ERROR_SUCCESS;
}

void space_manager_add_space(uint64_t sid)
Expand Down
14 changes: 12 additions & 2 deletions src/space_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ struct space_manager
bool auto_balance;
};

enum space_op_error
{
SPACE_OP_ERROR_SUCCESS = 0,
SPACE_OP_ERROR_MISSNG_SRC = 1,
SPACE_OP_ERROR_MISSNG_DST = 2,
SPACE_OP_ERROR_INVALID_SRC = 3,
SPACE_OP_ERROR_INVALID_DST = 4,
SPACE_OP_ERROR_INVALID_TYPE = 5,
};

bool space_manager_has_separate_spaces(void);
bool space_manager_query_active_space(FILE *rsp);
bool space_manager_query_spaces_for_window(FILE *rsp, struct window *window);
Expand Down Expand Up @@ -69,8 +79,8 @@ void space_manager_remove_window_from_space(uint64_t sid, struct window *window)
void space_manager_add_window_to_space(uint64_t sid, struct window *window);
void space_manager_focus_space(uint64_t sid);
void space_manager_move_space_after_space(uint64_t src_sid, uint64_t dst_sid, bool focus);
void space_manager_move_space_to_display(struct space_manager *sm, uint64_t sid, uint32_t did);
void space_manager_destroy_space(uint64_t 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);
void space_manager_assign_process_to_space(pid_t pid, uint64_t sid);
void space_manager_assign_process_to_all_spaces(pid_t pid);
Expand Down

0 comments on commit 9b6b8e2

Please sign in to comment.