]> git.mdlowis.com Git - proto/labwc.git/commitdiff
workspaces: Wire up workspaces
authorConsolatis <35009135+Consolatis@users.noreply.github.com>
Wed, 15 Jun 2022 00:02:50 +0000 (02:02 +0200)
committerConsolatis <35009135+Consolatis@users.noreply.github.com>
Wed, 15 Jun 2022 20:26:21 +0000 (22:26 +0200)
src/desktop.c
src/keyboard.c
src/osd.c
src/server.c
src/view.c
src/xdg.c
src/xwayland.c

index 9e16465e5a496e453c264b2dccef8d331367fdef..b19cd4bef5bae67ae1f3a0d8c13d35f97c609720 100644 (file)
@@ -6,6 +6,7 @@
 #include "node.h"
 #include "ssd.h"
 #include "common/scene-helpers.h"
+#include "workspaces.h"
 
 static void
 move_to_front(struct view *view)
@@ -162,73 +163,80 @@ isfocusable(struct view *view)
        return (view->mapped || view->minimized);
 }
 
-static bool
-has_focusable_view(struct wl_list *wl_list)
+static struct wl_list *
+get_prev_item(struct wl_list *item)
 {
-       struct view *view;
-       wl_list_for_each (view, wl_list, link) {
-               if (isfocusable(view)) {
-                       return true;
-               }
-       }
-       return false;
+       return item->prev;
+}
+
+static struct wl_list *
+get_next_item(struct wl_list *item)
+{
+       return item->next;
 }
 
 static struct view *
 first_view(struct server *server)
 {
-       struct view *view;
-       view = wl_container_of(server->views.next, view, link);
-       return view;
+       struct wlr_scene_node *node;
+       struct wl_list *list_head =
+               &server->workspace_current->tree->children;
+       wl_list_for_each_reverse(node, list_head, link) {
+               return node_view_from_node(node);
+       }
+       return NULL;
 }
 
 struct view *
-desktop_cycle_view(struct server *server, struct view *current,
+desktop_cycle_view(struct server *server, struct view *start_view,
                enum lab_cycle_dir dir)
 {
-       if (!has_focusable_view(&server->views)) {
+       struct view *view = start_view ? start_view : first_view(server);
+       if (!view) {
                return NULL;
        }
+       start_view = view;
+       struct wlr_scene_node *node = &view->scene_tree->node;
 
-       struct view *view = current ? current : first_view(server);
-       if (dir == LAB_CYCLE_DIR_FORWARD) {
-               /* Replacement for wl_list_for_each_from() */
-               do {
-                       view = wl_container_of(view->link.next, view, link);
-               } while (&view->link == &server->views || !isfocusable(view));
-       } else if (dir == LAB_CYCLE_DIR_BACKWARD) {
-               do {
-                       view = wl_container_of(view->link.prev, view, link);
-               } while (&view->link == &server->views || !isfocusable(view));
-       }
-       return view;
-}
+       assert(node->parent);
+       struct wl_list *list_head = &node->parent->children;
+       struct wl_list *list_item = &node->link;
+       struct wl_list *(*iter)(struct wl_list *);
 
-static bool
-has_mapped_view(struct wl_list *wl_list)
-{
-       struct view *view;
-       wl_list_for_each (view, wl_list, link) {
-               if (view->mapped) {
-                       return true;
+       /* Scene nodes are ordered like last node == displayed topmost */
+       iter = dir == LAB_CYCLE_DIR_FORWARD ? get_prev_item : get_next_item;
+
+       do {
+               list_item = iter(list_item);
+               if (list_item == list_head) {
+                       /* Start / End of list reached. Roll over */
+                       list_item = iter(list_item);
                }
-       }
-       return false;
+               node = wl_container_of(list_item, node, link);
+               view = node_view_from_node(node);
+               if (isfocusable(view)) {
+                       return view;
+               }
+       } while (view != start_view);
+
+       /* No focusable views found, including the one we started with */
+       return NULL;
 }
 
 static struct view *
 topmost_mapped_view(struct server *server)
 {
-       if (!has_mapped_view(&server->views)) {
-               return NULL;
+       struct view *view;
+       struct wl_list *node_list;
+       struct wlr_scene_node *node;
+       node_list = &server->workspace_current->tree->children;
+       wl_list_for_each_reverse(node, node_list, link) {
+               view = node_view_from_node(node);
+               if (view->mapped) {
+                       return view;
+               }
        }
-
-       /* start from tail of server->views */
-       struct view *view = wl_container_of(server->views.prev, view, link);
-       do {
-               view = wl_container_of(view->link.next, view, link);
-       } while (&view->link == &server->views || !view->mapped);
-       return view;
+       return NULL;
 }
 
 struct view *
index d6049f8817699e83cc32dbe51a7206af83d603e2..e754d5f6bfc680d119bc173588edccab0a713631 100644 (file)
@@ -5,6 +5,7 @@
 #include "buffer.h"
 #include "key-state.h"
 #include "labwc.h"
+#include "workspaces.h"
 
 static void
 change_vt(struct server *server, unsigned int vt)
@@ -38,17 +39,23 @@ keyboard_modifiers_notify(struct wl_listener *listener, void *data)
        struct seat *seat = wl_container_of(listener, seat, keyboard_modifiers);
        struct server *server = seat->server;
 
-       if (server->cycle_view) {
+       if (server->cycle_view || seat->workspace_osd_shown_by_modifier) {
                struct wlr_keyboard_key_event *event = data;
                struct wlr_keyboard *keyboard = &seat->keyboard_group->keyboard;
+
                if (event->state == WL_KEYBOARD_KEY_STATE_RELEASED
                                && !keyboard_any_modifiers_pressed(keyboard))  {
-                       /* end cycle */
-                       desktop_focus_and_activate_view(&server->seat,
-                               server->cycle_view);
-                       desktop_move_to_front(server->cycle_view);
-                       server->cycle_view = NULL;
-                       osd_finish(server);
+                       if (server->cycle_view) {
+                               /* end cycle */
+                               desktop_focus_and_activate_view(&server->seat,
+                                       server->cycle_view);
+                               desktop_move_to_front(server->cycle_view);
+                               server->cycle_view = NULL;
+                               osd_finish(server);
+                       }
+                       if (seat->workspace_osd_shown_by_modifier) {
+                               workspaces_osd_hide(seat);
+                       }
                }
        }
 
index 38803a16370efae9dc804900e82a1cfde465f17e..646feb92f7c669b9c13eff3dc71d394c01a4668b 100644 (file)
--- a/src/osd.c
+++ b/src/osd.c
@@ -10,6 +10,8 @@
 #include "config/rcxml.h"
 #include "labwc.h"
 #include "theme.h"
+#include "node.h"
+#include "workspaces.h"
 
 #define OSD_ITEM_HEIGHT (20)
 #define OSD_ITEM_WIDTH (600)
@@ -78,11 +80,13 @@ get_formatted_app_id(struct view *view)
 }
 
 static int
-get_osd_height(struct wl_list *views)
+get_osd_height(struct wl_list *node_list)
 {
        int height = 0;
        struct view *view;
-       wl_list_for_each(view, views, link) {
+       struct wlr_scene_node *node;
+       wl_list_for_each(node, node_list, link) {
+               view = node_view_from_node(node);
                if (!isfocusable(view)) {
                        continue;
                }
@@ -115,21 +119,32 @@ osd_finish(struct server *server)
 void
 osd_update(struct server *server)
 {
-       if (wl_list_empty(&server->views)) {
+       struct wl_list *node_list =
+               &server->workspace_current->tree->children;
+
+       if (wl_list_empty(node_list)) {
                osd_finish(server);
                return;
        }
 
        struct theme *theme = server->theme;
+       bool show_workspace = wl_list_length(&rc.workspace_config.workspaces) > 1;
 
        struct buf buf;
        buf_init(&buf);
+
+       struct view *view;
        struct output *output;
+       struct wlr_scene_node *node;
        wl_list_for_each(output, &server->outputs, link) {
                destroy_osd_nodes(output);
                float scale = output->wlr_output->scale;
-               int w = (OSD_ITEM_WIDTH + (2 * OSD_BORDER_WIDTH));
-               int h = get_osd_height(&server->views);
+               int w = OSD_ITEM_WIDTH + (2 * OSD_BORDER_WIDTH);
+               int h = get_osd_height(node_list);
+               if (show_workspace) {
+                       /* workspace indicator */
+                       h += OSD_ITEM_HEIGHT;
+               }
 
                if (output->osd_buffer) {
                        wlr_buffer_drop(&output->osd_buffer->base);
@@ -148,10 +163,16 @@ osd_update(struct server *server)
                set_source(cairo, theme->osd_border_color);
                draw_border(cairo, w, h, theme->osd_border_width);
 
-               /* highlight current window */
                int y = OSD_BORDER_WIDTH;
-               struct view *view;
-               wl_list_for_each(view, &server->views, link) {
+
+               if (show_workspace) {
+                       /* workspace indicator */
+                       y += OSD_ITEM_HEIGHT;
+               }
+
+               /* highlight current window */
+               wl_list_for_each_reverse(node, node_list, link) {
+                       view = node_view_from_node(node);
                        if (!isfocusable(view)) {
                                continue;
                        }
@@ -179,7 +200,6 @@ osd_update(struct server *server)
                pango_font_description_set_family(desc, font.name);
                pango_font_description_set_size(desc, font.size * PANGO_SCALE);
                pango_layout_set_font_description(layout, desc);
-               pango_font_description_free(desc);
 
                PangoTabArray *tabs = pango_tab_array_new_with_positions(2, TRUE,
                        PANGO_TAB_LEFT, OSD_TAB1, PANGO_TAB_LEFT, OSD_TAB2);
@@ -189,9 +209,28 @@ osd_update(struct server *server)
                pango_cairo_update_layout(cairo, layout);
 
                y = OSD_BORDER_WIDTH;
-               y += (OSD_ITEM_HEIGHT - font_height(&font)) / 2;
 
-               wl_list_for_each(view, &server->views, link) {
+               /* Center text entries on the y axis */
+               int y_offset = (OSD_ITEM_HEIGHT - font_height(&font)) / 2;
+               y += y_offset;
+
+               if (show_workspace) {
+                       /* Center workspace indicator on the x axis */
+                       int x = font_width(&font, server->workspace_current->name);
+                       x = (OSD_ITEM_WIDTH - x) / 2;
+                       cairo_move_to(cairo, x, y);
+                       pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD);
+                       pango_layout_set_font_description(layout, desc);
+                       pango_layout_set_text(layout, server->workspace_current->name, -1);
+                       pango_cairo_show_layout(cairo, layout);
+                       pango_font_description_set_weight(desc, PANGO_WEIGHT_NORMAL);
+                       pango_layout_set_font_description(layout, desc);
+                       y += OSD_ITEM_HEIGHT;
+               }
+               pango_font_description_free(desc);
+
+               wl_list_for_each_reverse(node, node_list, link) {
+                       view = node_view_from_node(node);
                        if (!isfocusable(view)) {
                                continue;
                        }
index 7ad7c427756efed0969897274d9b7a8d0c1d8c77..9f6ad07801ac43b62e4d4ed37bcce0bba54ed868 100644 (file)
@@ -18,6 +18,7 @@
 #include "menu/menu.h"
 #include "ssd.h"
 #include "theme.h"
+#include "workspaces.h"
 
 #define LAB_XDG_SHELL_VERSION (2)
 
@@ -181,6 +182,7 @@ server_init(struct server *server)
                event_loop, SIGINT, handle_sigterm, server->wl_display);
        sigterm_source = wl_event_loop_add_signal(
                event_loop, SIGTERM, handle_sigterm, server->wl_display);
+       server->wl_event_loop = event_loop;
 
        /*
         * The backend is a feature which abstracts the underlying input and
@@ -245,6 +247,8 @@ server_init(struct server *server)
 #endif
        server->menu_tree = wlr_scene_tree_create(&server->scene->tree);
 
+       workspaces_init(server);
+
        output_init(server);
 
        /*
@@ -452,7 +456,7 @@ server_start(struct server *server)
 void
 server_finish(struct server *server)
 {
-/* TODO: clean up various scene_tree nodes */
+
 #if HAVE_XWAYLAND
        wlr_xwayland_destroy(server->xwayland);
 #endif
@@ -465,4 +469,7 @@ server_finish(struct server *server)
        wlr_output_layout_destroy(server->output_layout);
 
        wl_display_destroy(server->wl_display);
+
+       /* TODO: clean up various scene_tree nodes */
+       workspaces_destroy(server);
 }
index e11610bc1c2e38f57e694778fb4074f1fb3e113e..e82dd6d387df74e1ecb30f8c5ed080fcebd1742d 100644 (file)
@@ -6,6 +6,7 @@
 #include "labwc.h"
 #include "ssd.h"
 #include "menu/menu.h"
+#include "workspaces.h"
 
 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
 
@@ -336,8 +337,8 @@ void
 view_toggle_always_on_top(struct view *view)
 {
        if (is_always_on_top(view)) {
-               wlr_scene_node_reparent(&view->scene_tree->node,
-                       view->server->view_tree);
+               view->workspace = view->server->workspace_current;
+               wlr_scene_node_reparent(&view->scene_tree->node, view->workspace->tree);
        } else {
                wlr_scene_node_reparent(&view->scene_tree->node,
                        view->server->view_tree_always_on_top);
index 162a6d41ed78fd9ddcc9a17c348a74f460ac79a8..611691c63927c5ddce44f7522250b2615f977a32 100644 (file)
--- a/src/xdg.c
+++ b/src/xdg.c
@@ -3,6 +3,7 @@
 #include "labwc.h"
 #include "node.h"
 #include "ssd.h"
+#include "workspaces.h"
 
 static void
 handle_new_xdg_popup(struct wl_listener *listener, void *data)
@@ -374,7 +375,8 @@ xdg_surface_new(struct wl_listener *listener, void *data)
        view->impl = &xdg_toplevel_view_impl;
        view->xdg_surface = xdg_surface;
 
-       view->scene_tree = wlr_scene_tree_create(view->server->view_tree);
+       view->workspace = server->workspace_current;
+       view->scene_tree = wlr_scene_tree_create(view->workspace->tree);
        wlr_scene_node_set_enabled(&view->scene_tree->node, false);
 
        struct wlr_scene_tree *tree = wlr_scene_xdg_surface_create(
index 2790852d6d0e44e0299230a97e159819b1dfe27d..334dd3b2f2bd7320bc1b54d30e664744ed797f3e 100644 (file)
@@ -3,6 +3,7 @@
 #include "labwc.h"
 #include "node.h"
 #include "ssd.h"
+#include "workspaces.h"
 
 static void
 handle_commit(struct wl_listener *listener, void *data)
@@ -434,7 +435,8 @@ xwayland_surface_new(struct wl_listener *listener, void *data)
        view->impl = &xwl_view_impl;
        view->xwayland_surface = xsurface;
 
-       view->scene_tree = wlr_scene_tree_create(view->server->view_tree);
+       view->workspace = server->workspace_current;
+       view->scene_tree = wlr_scene_tree_create(view->workspace->tree);
        node_descriptor_create(&view->scene_tree->node,
                LAB_NODE_DESC_VIEW, view);
        xsurface->data = view;