Skip to content

Commit

Permalink
Merge pull request #57 from migueldeoleiros/feature/window-master-toggle
Browse files Browse the repository at this point in the history
Implement master toggle command
  • Loading branch information
migueldeoleiros authored Nov 18, 2024
2 parents 9cb3781 + 0850b41 commit 05ea3c2
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 6 deletions.
58 changes: 56 additions & 2 deletions src/commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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},
Expand Down Expand Up @@ -255,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);
Expand Down Expand Up @@ -289,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\"}");
Expand All @@ -310,6 +313,57 @@ 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 *toplevel_id = tokens[0];

toplevel = get_toplevel(server, toplevel_id);

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\": \"no window found\"}");
}

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
Expand Down
52 changes: 49 additions & 3 deletions src/toplevel.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -108,13 +133,34 @@ 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)
return toplevel;
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) {
Expand Down Expand Up @@ -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);
}

Expand Down
29 changes: 29 additions & 0 deletions src/toplevel.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/workspace.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit 05ea3c2

Please sign in to comment.