From 64aec6ff5d7c6efc6a128ab84e2468e64e6e4c28 Mon Sep 17 00:00:00 2001 From: Cameron Scott McCreery Date: Mon, 22 Dec 2025 16:17:43 -0500 Subject: [PATCH] workspaces: add config option for initial workspace selection --- docs/labwc-config.5.scd | 5 +++ docs/rc.xml.all | 1 + include/config/rcxml.h | 1 + src/config/rcxml.c | 3 ++ src/workspaces.c | 83 +++++++++++++++++++++++++++-------------- 5 files changed, 64 insertions(+), 29 deletions(-) diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd index 1c2a4af6..85363354 100644 --- a/docs/labwc-config.5.scd +++ b/docs/labwc-config.5.scd @@ -575,6 +575,11 @@ extending outward from the snapped edge. is 1. The number attribute is optional. If the number attribute is specified, names.name is not required. +** + Define the initial starting workspace. This must match one of the names + defined in or must be an index equal to or lower than . + If not set, the first workspace is used. + ** Define the timeout after which to hide the workspace OSD. A setting of 0 disables the OSD. Default is 1000 ms. diff --git a/docs/rc.xml.all b/docs/rc.xml.all index ea4e30ac..a99aa997 100644 --- a/docs/rc.xml.all +++ b/docs/rc.xml.all @@ -175,6 +175,7 @@ Workspaces can be configured like this: 1000 + Workspace 1 Workspace 1 Workspace 2 diff --git a/include/config/rcxml.h b/include/config/rcxml.h index 65b07172..8fd11aa0 100644 --- a/include/config/rcxml.h +++ b/include/config/rcxml.h @@ -168,6 +168,7 @@ struct rcxml { struct { int popuptime; int min_nr_workspaces; + char *initial_workspace_name; char *prefix; struct wl_list workspaces; /* struct workspace.link */ } workspace_config; diff --git a/src/config/rcxml.c b/src/config/rcxml.c index 68c1135a..60e709f2 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -1308,6 +1308,8 @@ entry(xmlNode *node, char *nodename, char *content) wl_list_append(&rc.workspace_config.workspaces, &workspace->link); } else if (!strcasecmp(nodename, "popupTime.desktops")) { rc.workspace_config.popuptime = atoi(content); + } else if (!strcasecmp(nodename, "initial.desktops")) { + xstrdup_replace(rc.workspace_config.initial_workspace_name, content); } else if (!strcasecmp(nodename, "number.desktops")) { rc.workspace_config.min_nr_workspaces = MAX(1, atoi(content)); } else if (!strcasecmp(nodename, "popupShow.resize")) { @@ -1963,6 +1965,7 @@ rcxml_finish(void) zfree(rc.icon_theme_name); zfree(rc.fallback_app_icon_name); zfree(rc.workspace_config.prefix); + zfree(rc.workspace_config.initial_workspace_name); zfree(rc.tablet.output_name); zfree(rc.window_switcher.osd.thumbnail_label_format); diff --git a/src/workspaces.c b/src/workspaces.c index f56d170a..7b0b8e96 100644 --- a/src/workspaces.c +++ b/src/workspaces.c @@ -182,6 +182,33 @@ _osd_update(struct server *server) } } +static struct workspace * +workspace_find_by_name(struct server *server, const char *name) +{ + struct workspace *workspace; + + /* by index */ + size_t parsed_index = parse_workspace_index(name); + if (parsed_index) { + size_t index = 0; + wl_list_for_each(workspace, &server->workspaces.all, link) { + if (parsed_index == ++index) { + return workspace; + } + } + } + + /* by name */ + wl_list_for_each(workspace, &server->workspaces.all, link) { + if (!strcmp(workspace->name, name)) { + return workspace; + } + } + + wlr_log(WLR_ERROR, "Workspace '%s' not found", name); + return NULL; +} + /* cosmic workspace handlers */ static void handle_cosmic_workspace_activate(struct wl_listener *listener, void *data) @@ -209,18 +236,11 @@ add_workspace(struct server *server, const char *name) workspace->name = xstrdup(name); workspace->tree = wlr_scene_tree_create(server->view_tree); wl_list_append(&server->workspaces.all, &workspace->link); - if (!server->workspaces.current) { - server->workspaces.current = workspace; - } else { - wlr_scene_node_set_enabled(&workspace->tree->node, false); - } - - bool active = server->workspaces.current == workspace; + wlr_scene_node_set_enabled(&workspace->tree->node, false); /* cosmic */ workspace->cosmic_workspace = lab_cosmic_workspace_create(server->workspaces.cosmic_group); lab_cosmic_workspace_set_name(workspace->cosmic_workspace, name); - lab_cosmic_workspace_set_active(workspace->cosmic_workspace, active); workspace->on_cosmic.activate.notify = handle_cosmic_workspace_activate; wl_signal_add(&workspace->cosmic_workspace->events.activate, @@ -231,7 +251,6 @@ add_workspace(struct server *server, const char *name) server->workspaces.ext_manager, /*id*/ NULL); lab_ext_workspace_assign_to_group(workspace->ext_workspace, server->workspaces.ext_group); lab_ext_workspace_set_name(workspace->ext_workspace, name); - lab_ext_workspace_set_active(workspace->ext_workspace, active); workspace->on_ext.activate.notify = handle_ext_workspace_activate; wl_signal_add(&workspace->ext_workspace->events.activate, @@ -398,6 +417,27 @@ workspaces_init(struct server *server) wl_list_for_each(conf, &rc.workspace_config.workspaces, link) { add_workspace(server, conf->name); } + + /* + * After adding workspaces, check if there is an initial workspace + * selected and set that as the initial workspace. + */ + char *initial_name = rc.workspace_config.initial_workspace_name; + struct workspace *initial = NULL; + struct workspace *first = wl_container_of( + server->workspaces.all.next, first, link); + + if (initial_name) { + initial = workspace_find_by_name(server, initial_name); + } + if (!initial) { + initial = first; + } + + server->workspaces.current = initial; + wlr_scene_node_set_enabled(&initial->tree->node, true); + lab_cosmic_workspace_set_active(initial->cosmic_workspace, true); + lab_ext_workspace_set_active(initial->ext_workspace, true); } /* @@ -507,21 +547,13 @@ workspaces_find(struct workspace *anchor, const char *name, bool wrap) if (!name) { return NULL; } - size_t index = 0; - struct workspace *target; - size_t wants_index = parse_workspace_index(name); - struct wl_list *workspaces = &anchor->server->workspaces.all; + struct server *server = anchor->server; + struct wl_list *workspaces = &server->workspaces.all; - if (wants_index) { - wl_list_for_each(target, workspaces, link) { - if (wants_index == ++index) { - return target; - } - } - } else if (!strcasecmp(name, "current")) { + if (!strcasecmp(name, "current")) { return anchor; } else if (!strcasecmp(name, "last")) { - return anchor->server->workspaces.last; + return server->workspaces.last; } else if (!strcasecmp(name, "left")) { return get_prev(anchor, workspaces, wrap); } else if (!strcasecmp(name, "right")) { @@ -530,15 +562,8 @@ workspaces_find(struct workspace *anchor, const char *name, bool wrap) return get_prev_occupied(anchor, workspaces, wrap); } else if (!strcasecmp(name, "right-occupied")) { return get_next_occupied(anchor, workspaces, wrap); - } else { - wl_list_for_each(target, workspaces, link) { - if (!strcasecmp(target->name, name)) { - return target; - } - } } - wlr_log(WLR_ERROR, "Workspace '%s' not found", name); - return NULL; + return workspace_find_by_name(server, name); } static void