From 699379c47867ab560455abdac4dde945fa614bbe Mon Sep 17 00:00:00 2001 From: migueldeoleiros Date: Wed, 13 Nov 2024 17:47:09 +0100 Subject: [PATCH 1/2] feat: base working master toggle command --- src/commands.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/commands.c b/src/commands.c index d2bbb91..4e9258e 100644 --- a/src/commands.c +++ b/src/commands.c @@ -46,6 +46,8 @@ void window_kill_command(char *tokens[], int ntokens, char *response, struct turtile_context *context); void window_move_to_command(char *tokens[], int ntokens, char *response, struct turtile_context *context); +void window_master_toggle_command(char *tokens[], int ntokens, char *response, + struct turtile_context *context); void workspace_command(char *tokens[], int ntokens, char *response, struct turtile_context *context); void workspace_list_command(char *tokens[], int ntokens, char *response, @@ -67,6 +69,7 @@ static command_t commands[] = { {"window", "cycle", window_cycle_command}, {"window", "kill", window_kill_command}, {"window", "move-to", window_move_to_command}, + {"window", "mtoggle", window_master_toggle_command}, {"window", NULL, window_command}, {"workspace", "list", workspace_list_command}, {"workspace", "switch", workspace_switch_command}, @@ -310,6 +313,43 @@ void window_move_to_command(char *tokens[], int ntokens, char *response, } } +void window_master_toggle_command(char *tokens[], int ntokens, char *response, + struct turtile_context *context){ + // Set designated toplevel as master + struct turtile_server *server = context->server; + struct turtile_toplevel *toplevel; + + if(ntokens >= 1){ + char *new_toplevel_id = tokens[0]; + + wl_list_for_each(toplevel, &server->focus_toplevels, flink) { + if(strcmp(toplevel->id, new_toplevel_id) == 0){ + + wl_list_remove(&toplevel->link); + wl_list_insert(&server->toplevels, &toplevel->link); + server_redraw_windows(server); + + snprintf(response, MAX_MSG_SIZE, + "{\"success\": \"master: %s\"}", + toplevel->xdg_toplevel->title); + return; + } + } + snprintf(response, MAX_MSG_SIZE, + "{\"error\": \"window %s not found\"}", new_toplevel_id); + + } else{ + toplevel = get_first_toplevel(server); + + wl_list_remove(&toplevel->link); + wl_list_insert(&server->toplevels, &toplevel->link); + server_redraw_windows(server); + + snprintf(response, MAX_MSG_SIZE, + "{\"success\": \"master: %s\"}", toplevel->xdg_toplevel->title); + } +} + void workspace_command(char *tokens[], int ntokens, char *response, struct turtile_context *context){ // TODO: use this function as a help for the other workspace subcommands From 0850b41b7caca36c619b8ec4228ce77af5c794a6 Mon Sep 17 00:00:00 2001 From: migueldeoleiros Date: Mon, 18 Nov 2024 16:35:20 +0100 Subject: [PATCH 2/2] refactor: abstract master toggle command logic --- src/commands.c | 54 +++++++++++++++++++++++++++++++------------------ src/toplevel.c | 52 ++++++++++++++++++++++++++++++++++++++++++++--- src/toplevel.h | 29 ++++++++++++++++++++++++++ src/workspace.c | 2 +- 4 files changed, 113 insertions(+), 24 deletions(-) diff --git a/src/commands.c b/src/commands.c index 4e9258e..e482c4e 100644 --- a/src/commands.c +++ b/src/commands.c @@ -258,7 +258,7 @@ void window_kill_command(char *tokens[], int ntokens, char *response, "{\"error\": \"window %s not found\"}", new_toplevel_id); } else{ - toplevel = get_first_toplevel(server); + toplevel = get_first_focus_toplevel(server); kill_toplevel(toplevel); snprintf(response, MAX_MSG_SIZE, "{\"success\": \"kill: %s\"}", toplevel->xdg_toplevel->title); @@ -292,7 +292,7 @@ void window_move_to_command(char *tokens[], int ntokens, char *response, return; } } else { - toplevel_to_move = get_first_toplevel(server); + toplevel_to_move = get_first_focus_toplevel(server); if (!toplevel_to_move) { snprintf(response, MAX_MSG_SIZE, "{\"error\": \"no focused window to move\"}"); @@ -320,34 +320,48 @@ void window_master_toggle_command(char *tokens[], int ntokens, char *response, struct turtile_toplevel *toplevel; if(ntokens >= 1){ - char *new_toplevel_id = tokens[0]; + char *toplevel_id = tokens[0]; - wl_list_for_each(toplevel, &server->focus_toplevels, flink) { - if(strcmp(toplevel->id, new_toplevel_id) == 0){ + toplevel = get_toplevel(server, toplevel_id); - wl_list_remove(&toplevel->link); - wl_list_insert(&server->toplevels, &toplevel->link); - server_redraw_windows(server); + if(toplevel != NULL){ + set_master_toplevel(toplevel); + + snprintf(response, MAX_MSG_SIZE, + "{\"success\": \"master: %s\"}", + toplevel->xdg_toplevel->title); + return; + } else { + snprintf(response, MAX_MSG_SIZE, + "{\"error\": \"window %s not found\"}", toplevel_id); + return; + } + } else{ + toplevel = get_first_focus_toplevel(server); + if(toplevel == get_first_toplevel(server)){ + struct turtile_toplevel *next_toplevel = + get_next_focus_toplevel(server); + if(next_toplevel != NULL){ + set_master_toplevel(get_next_focus_toplevel(server)); snprintf(response, MAX_MSG_SIZE, "{\"success\": \"master: %s\"}", toplevel->xdg_toplevel->title); return; + } else { + snprintf(response, MAX_MSG_SIZE, + "{\"error\": \"the current window is already master\"}"); + return; } + } else if(toplevel != NULL) { + set_master_toplevel(toplevel); + snprintf(response, MAX_MSG_SIZE, + "{\"success\": \"master: %s\"}", + toplevel->xdg_toplevel->title); + return; } - snprintf(response, MAX_MSG_SIZE, - "{\"error\": \"window %s not found\"}", new_toplevel_id); - - } else{ - toplevel = get_first_toplevel(server); - - wl_list_remove(&toplevel->link); - wl_list_insert(&server->toplevels, &toplevel->link); - server_redraw_windows(server); - - snprintf(response, MAX_MSG_SIZE, - "{\"success\": \"master: %s\"}", toplevel->xdg_toplevel->title); } + snprintf(response, MAX_MSG_SIZE, "{\"error\": \"no window found\"}"); } void workspace_command(char *tokens[], int ntokens, char *response, diff --git a/src/toplevel.c b/src/toplevel.c index fe159fa..b5c955a 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -90,13 +90,38 @@ void kill_toplevel(struct turtile_toplevel *toplevel) { return; } - struct turtile_toplevel *next_toplevel = - wl_container_of(workspace_toplevels.next, next_toplevel, auxlink); + struct turtile_toplevel *next_toplevel = get_next_focus_toplevel(server); focus_toplevel(next_toplevel, next_toplevel->xdg_toplevel->base->surface); wlr_xdg_toplevel_send_close(toplevel->xdg_toplevel); } +void set_master_toplevel(struct turtile_toplevel *toplevel) { + struct turtile_server *server = toplevel->server; + + wl_list_remove(&toplevel->link); + wl_list_insert(&server->toplevels, &toplevel->link); + server_redraw_windows(server); +} + +void toggle_master_toplevel(struct turtile_toplevel *toplevel) { + struct turtile_server *server = toplevel->server; + + struct wl_list workspace_toplevels; + get_workspace_toplevels(server->active_workspace, &workspace_toplevels); + + if (wl_list_length(&workspace_toplevels) < 2) { + return; + } else if(get_first_toplevel(server) == toplevel){ + struct turtile_toplevel *next_toplevel = + wl_container_of(workspace_toplevels.next, next_toplevel, auxlink); + focus_toplevel(next_toplevel, next_toplevel->xdg_toplevel->base->surface); + toggle_master_toplevel(next_toplevel); + } else { + set_master_toplevel(toplevel); + } +} + struct turtile_toplevel *get_toplevel(struct turtile_server *server, char *id) { struct turtile_toplevel *toplevel; wl_list_for_each(toplevel, &server->toplevels, link) { @@ -108,6 +133,14 @@ struct turtile_toplevel *get_toplevel(struct turtile_server *server, char *id) { } struct turtile_toplevel *get_first_toplevel(struct turtile_server *server) { + struct turtile_toplevel *toplevel; + wl_list_for_each(toplevel, &server->toplevels, link) + if (toplevel->workspace == server->active_workspace) + return toplevel; + return NULL; +} + +struct turtile_toplevel *get_first_focus_toplevel(struct turtile_server *server) { struct turtile_toplevel *toplevel; wl_list_for_each(toplevel, &server->focus_toplevels, flink) if (toplevel->workspace == server->active_workspace) @@ -115,6 +148,19 @@ struct turtile_toplevel *get_first_toplevel(struct turtile_server *server) { return NULL; } +struct turtile_toplevel *get_next_focus_toplevel(struct turtile_server *server) { + struct wl_list workspace_toplevels; + get_workspace_toplevels(server->active_workspace, &workspace_toplevels); + + if (wl_list_length(&workspace_toplevels) < 2) { + return NULL; + } else { + struct turtile_toplevel *next_toplevel = + wl_container_of(workspace_toplevels.next, next_toplevel, auxlink); + return next_toplevel; + } +} + struct turtile_toplevel *desktop_toplevel_at( struct turtile_server *server, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { @@ -185,7 +231,7 @@ void xdg_toplevel_unmap(struct wl_listener *listener, void *data) { if (toplevel == toplevel->server->grabbed_toplevel) { reset_cursor_mode(toplevel->server); - struct turtile_toplevel *newfocus = get_first_toplevel(toplevel->server); + struct turtile_toplevel *newfocus = get_first_focus_toplevel(toplevel->server); focus_toplevel(newfocus, newfocus->xdg_toplevel->base->surface); } diff --git a/src/toplevel.h b/src/toplevel.h index ddb7bb6..799ece6 100644 --- a/src/toplevel.h +++ b/src/toplevel.h @@ -65,6 +65,13 @@ void focus_toplevel(struct turtile_toplevel *toplevel, */ void kill_toplevel(struct turtile_toplevel *toplevel); +/** + * Set given toplevel as master + * + * @param toplevel The turtile toplevel to set as master. + */ +void set_master_toplevel(struct turtile_toplevel *toplevel); + /** * Retrieves the toplevel with the given ID from the given server. * @@ -84,6 +91,28 @@ struct turtile_toplevel *get_toplevel(struct turtile_server *server, char *id); */ struct turtile_toplevel *get_first_toplevel(struct turtile_server *server); +/** + * Retrieves the first toplevel of the focus stack on the active workspace + * of the given server. + * If no such toplevel is found, NULL is returned. + + * @param server The turtile server to search for the toplevel on. + * @return A pointer to the first toplevel of the focus stack on the active + * workspace, or NULL if no such toplevel is found. + */ +struct turtile_toplevel *get_first_focus_toplevel(struct turtile_server *server); + +/** + * Retrieves the next toplevel of the focus stack on the active workspace + * of the given server. + * If no such toplevel is found, NULL is returned. + + * @param server The turtile server to search for the toplevel on. + * @return A pointer to the next toplevel of the focus stack on the active + * workspace, or NULL if no such toplevel is found. + */ +struct turtile_toplevel *get_next_focus_toplevel(struct turtile_server *server); + /** * Given a server, layout coordinates, and optional surface and position * pointers, this function returns the topmost node in the scene at the given diff --git a/src/workspace.c b/src/workspace.c index b287041..72c1e74 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -59,7 +59,7 @@ void switch_workspace(struct turtile_workspace *workspace){ struct turtile_server *server = workspace->server; server->active_workspace = workspace; - struct turtile_toplevel *newfocus = get_first_toplevel(server); + struct turtile_toplevel *newfocus = get_first_focus_toplevel(server); if(newfocus != NULL) focus_toplevel(newfocus, newfocus->xdg_toplevel->base->surface);