From: Matthias Kruk Date: Tue, 18 May 2021 23:52:30 +0000 (+0900) Subject: workspace: Add functions for managing clients in workspaces X-Git-Url: https://git.corax.cc/?a=commitdiff_plain;h=b2f2a3224c38d9353022eef840aa27ff951c1a75;p=mwm workspace: Add functions for managing clients in workspaces This commit adds functions to add and remove clients from workspaces, arrange clients according to the monitor's layout function, and to shift client positions within the workspace. --- diff --git a/workspace.c b/workspace.c index 3174c42..00fa0b5 100644 --- a/workspace.c +++ b/workspace.c @@ -1,15 +1,22 @@ #include #include +#include #include #include "workspace.h" +#include "monitor.h" #include "client.h" #include "loop.h" +#include "common.h" + +struct monitor; struct workspace { struct loop *clients; struct client *focused; + struct monitor *viewer; int number; + int needs_redraw; }; int workspace_new(const int number, struct workspace **workspace) @@ -49,21 +56,300 @@ int workspace_free(struct workspace **workspace) return(0); } -int workspace_add_client(struct workspace *workspace, struct client *client) +int workspace_get_number(struct workspace *workspace) +{ + if(!workspace) { + return(-EINVAL); + } + + return(workspace->number); +} + +int workspace_attach_client(struct workspace *workspace, struct client *client) { if(!workspace || !client) { return(-EINVAL); } - return(loop_append(&workspace->clients, client)); + if(loop_append(&workspace->clients, client) < 0) { + return(-ENOMEM); + } + + client_set_workspace(client, workspace); + + if(!workspace_get_focused_client(workspace)) { + workspace_focus_client(workspace, client); + } + + workspace_needs_redraw(workspace); + + return(0); } -int workspace_remove_client(struct workspace *workspace, struct client *client) +int workspace_detach_client(struct workspace *workspace, struct client *client) { + int err; + +#if MWM_DEBUG + printf("%s(%p, %p)\n", __func__, (void*)workspace, (void*)client); +#endif /* MWM_DEBUG */ + if(!workspace || !client) { return(-EINVAL); } - return(loop_remove(&workspace->clients, client)); + err = loop_remove(&workspace->clients, client); + + if(err < 0) { + return(err); + } + + if(workspace_get_focused_client(workspace) == client) { + struct client *first; + + if(loop_get_first(&workspace->clients, (void**)&first) < 0) { + first = NULL; + } + + workspace_focus_client(workspace, first); + } + + workspace_needs_redraw(workspace); + + return(0); +} + +int workspace_find_client(struct workspace *workspace, + int (*cmp)(struct client*, void*), + void *data, struct client **client) +{ + if(!workspace) { + return(-EINVAL); + } + + return(loop_find(&workspace->clients, (int(*)(void*,void*))cmp, + data, (void**)client)); +} + +int workspace_set_viewer(struct workspace *workspace, struct monitor *viewer) +{ + if(!workspace) { + return(-EINVAL); + } + + workspace->viewer = viewer; + return(0); +} + +struct monitor* workspace_get_viewer(struct workspace *workspace) +{ + return(workspace->viewer); +} + +int workspace_focus_client(struct workspace *workspace, struct client *client) +{ + if(!workspace) { + return(-EINVAL); + } + + workspace->focused = client; + return(0); +} + +struct client* workspace_get_focused_client(struct workspace *workspace) +{ + return(workspace->focused); +} + +int workspace_foreach_client(struct workspace *workspace, + int (*func)(struct workspace*, struct client*, void*), + void *data) +{ + loop_iter_t first; + loop_iter_t cur; + + if(!workspace || !func) { + return(-EINVAL); + } + + first = loop_get_iter(&workspace->clients); + + if(!first) { + return(0); + } + + cur = first; + + do { + struct client *client; + + client = (struct client*)loop_iter_get_data(cur); + + if(func(workspace, client, data) < 0) { + break; + } + + cur = loop_iter_get_next(cur); + } while(cur != first); + + return(0); +} + +int workspace_redraw(struct workspace *workspace) +{ + loop_iter_t first; + loop_iter_t cur; + + if(!workspace) { + return(-EINVAL); + } + + first = loop_get_iter(&workspace->clients); + + if(first) { + cur = first; + + do { + struct client *client; + + client = (struct client*)loop_iter_get_data(cur); + client_redraw(client); + + cur = loop_iter_get_next(cur); + } while(cur != first); + } + + workspace->needs_redraw = 0; + + return(0); +} + +int workspace_needs_redraw(struct workspace *workspace) +{ + if(!workspace) { + return(-EINVAL); + } + + workspace->needs_redraw = 1; + + if(workspace->viewer) { + monitor_needs_redraw(workspace->viewer); + } + + return(0); +} + +int workspace_arrange(struct workspace *workspace, + int (*arrange)(struct workspace*, struct client*, int, void*), + void *data) +{ + int unarranged_clients; + loop_iter_t first; + loop_iter_t cur; + + unarranged_clients = loop_get_length(&workspace->clients); + first = loop_get_iter(&workspace->clients); + + if(!first) { + return(0); + } + + cur = first; + + do { + struct client *client; + + client = (struct client*)loop_iter_get_data(cur); + + arrange(workspace, client, unarranged_clients, data); + + unarranged_clients--; + loop_iter_inc(cur); + } while(cur != first); + + return(0); +} + +int _increase_if_tiled(struct workspace *workspace, struct client *client, void *data) +{ + int *count; + + if(!workspace || !client || !data) { + return(-EINVAL); + } + + count = (int*)data; + + if(client_is_tiled(client)) { + (*count)++; + } + + return(0); +} + +int workspace_count_tiled_clients(struct workspace *workspace) +{ + int count; + + count = 0; + + workspace_foreach_client(workspace, _increase_if_tiled, &count); + + return(count); +} + +int workspace_shift_focus(struct workspace *workspace, int dir) +{ + struct client *new_focus; + + if(!workspace || dir == 0) { + return(-EINVAL); + } + + if(dir > 0) { + if(loop_get_next(&workspace->clients, workspace->focused, + (void**)&new_focus) < 0) { + return(-EFAULT); + } + } else { + if(loop_get_prev(&workspace->clients, workspace->focused, + (void**)&new_focus) < 0) { + return(-EFAULT); + } + } + + workspace_focus_client(workspace, new_focus); + workspace_needs_redraw(workspace); + + return(0); +} + +int workspace_shift_client(struct workspace *workspace, struct client *client, int dir) +{ + struct client *shift; + int err; + +#if MWM_DEBUG + printf("%s(%p, %p, %d)\n", __func__, (void*)workspace, (void*)client, dir); +#endif /* MWM_DEBUG */ + + if(!workspace || dir == 0) { + return(-EINVAL); + } + + shift = client ? client : workspace->focused; + + if(!shift) { + return(-ENOENT); + } + + err = (dir > 0) ? loop_shift_forwards(&workspace->clients, shift) : + loop_shift_backwards(&workspace->clients, shift); + + if(!err) { + workspace_needs_redraw(workspace); + } + + return(0); } diff --git a/workspace.h b/workspace.h index dabf011..baf32c6 100644 --- a/workspace.h +++ b/workspace.h @@ -2,14 +2,42 @@ #define MWM_WORKSPACE_H 1 struct client; +struct monitor; struct workspace; int workspace_new(const int number, struct workspace **workspace); int workspace_free(struct workspace **workspace); +int workspace_get_number(struct workspace *workspace); -int workspace_add_client(struct workspace *workspace, - struct client *client); -int workspace_remove_client(struct workspace *workspace, +int workspace_attach_client(struct workspace *workspace, struct client *client); +int workspace_detach_client(struct workspace *workspace, + struct client *client); + +int workspace_find_client(struct workspace *workspace, + int (*cmp)(struct client*, void*), + void *data, struct client **client); + +int workspace_focus_client(struct workspace *workspace, + struct client *client); +struct client* workspace_get_focused_client(struct workspace *workspace); + +int workspace_set_viewer(struct workspace *workspace, struct monitor *viewer); +struct monitor* workspace_get_viewer(struct workspace *workspace); + +int workspace_arrange(struct workspace *workspace, + int (*func)(struct workspace*, struct client*, int, void*), + void *data); + +int workspace_count_tiled_clients(struct workspace *workspace); +int workspace_foreach_client(struct workspace *workspace, + int (*func)(struct workspace*, struct client*, void*), + void *data); + +int workspace_needs_redraw(struct workspace *workspace); +int workspace_redraw(struct workspace *workspace); + +int workspace_shift_focus(struct workspace *workspace, int dir); +int workspace_shift_client(struct workspace *workspace, struct client *client, int dir); #endif /* MWM_WORKSPACE_H */