]> git.corax.cc Git - mwm/commitdiff
workspace: Add functions for managing clients in workspaces
authorMatthias Kruk <m@m10k.eu>
Tue, 18 May 2021 23:52:30 +0000 (08:52 +0900)
committerMatthias Kruk <m@m10k.eu>
Tue, 18 May 2021 23:52:30 +0000 (08:52 +0900)
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.

workspace.c
workspace.h

index 3174c42f079788b9d5f0ccd542ef3d99f0fe2f40..00fa0b57a3e4c5fbd76d6a34b900d5ec36789239 100644 (file)
@@ -1,15 +1,22 @@
 #include <stdlib.h>
 #include <string.h>
+#include <stdio.h>
 #include <errno.h>
 #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);
 }
index dabf011e703307f1c4dbc924b7ad888bd56d92ad..baf32c64e9498fa97f16de55c499d634f3cf1008 100644 (file)
@@ -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 */