From 2802ca7264b1196856004dcc495e50af39b98724 Mon Sep 17 00:00:00 2001 From: tokyo4j Date: Fri, 18 Jul 2025 18:47:39 +0900 Subject: [PATCH 1/2] Drop cosmic-workspace and use wlroots impl of ext-workspace-v1 --- include/labwc.h | 9 +- .../protocols/cosmic-workspaces-internal.h | 24 - include/protocols/cosmic-workspaces.h | 94 --- include/protocols/ext-workspace-internal.h | 25 - include/protocols/ext-workspace.h | 109 --- include/protocols/transaction-addon.h | 84 -- include/workspaces.h | 15 +- protocols/cosmic-workspace-unstable-v1.xml | 364 --------- protocols/meson.build | 1 - src/meson.build | 1 - src/output.c | 11 +- .../cosmic_workspaces/cosmic-workspaces.c | 717 ---------------- src/protocols/cosmic_workspaces/meson.build | 4 - src/protocols/cosmic_workspaces/output.c | 174 ---- src/protocols/ext-workspace/ext-workspace.c | 762 ------------------ src/protocols/ext-workspace/meson.build | 4 - src/protocols/ext-workspace/output.c | 174 ---- src/protocols/meson.build | 6 - src/protocols/transaction-addon.c | 70 -- src/server.c | 1 - src/workspaces.c | 94 +-- 21 files changed, 46 insertions(+), 2697 deletions(-) delete mode 100644 include/protocols/cosmic-workspaces-internal.h delete mode 100644 include/protocols/cosmic-workspaces.h delete mode 100644 include/protocols/ext-workspace-internal.h delete mode 100644 include/protocols/ext-workspace.h delete mode 100644 include/protocols/transaction-addon.h delete mode 100644 protocols/cosmic-workspace-unstable-v1.xml delete mode 100644 src/protocols/cosmic_workspaces/cosmic-workspaces.c delete mode 100644 src/protocols/cosmic_workspaces/meson.build delete mode 100644 src/protocols/cosmic_workspaces/output.c delete mode 100644 src/protocols/ext-workspace/ext-workspace.c delete mode 100644 src/protocols/ext-workspace/meson.build delete mode 100644 src/protocols/ext-workspace/output.c delete mode 100644 src/protocols/meson.build delete mode 100644 src/protocols/transaction-addon.c diff --git a/include/labwc.h b/include/labwc.h index c4848a11..f4d163f6 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -247,13 +247,14 @@ struct server { struct wl_list all; /* struct workspace.link */ struct workspace *current; struct workspace *last; - struct lab_cosmic_workspace_manager *cosmic_manager; - struct lab_cosmic_workspace_group *cosmic_group; - struct lab_ext_workspace_manager *ext_manager; - struct lab_ext_workspace_group *ext_group; + struct wlr_ext_workspace_manager_v1 *ext_manager; + struct wlr_ext_workspace_group_handle_v1 *ext_group; struct { struct wl_listener layout_output_added; } on; + struct { + struct wl_listener commit; + } on_ext_manager; } workspaces; struct wl_list outputs; diff --git a/include/protocols/cosmic-workspaces-internal.h b/include/protocols/cosmic-workspaces-internal.h deleted file mode 100644 index 50c7e75b..00000000 --- a/include/protocols/cosmic-workspaces-internal.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -#ifndef LABWC_PROTOCOLS_COSMIC_WORKSPACES_INTERNAL_H -#define LABWC_PROTOCOLS_COSMIC_WORKSPACES_INTERNAL_H - -struct lab_cosmic_workspace; -struct lab_cosmic_workspace_group; -struct lab_cosmic_workspace_manager; - -enum pending_change { - /* group events */ - CW_PENDING_WS_CREATE = 1 << 0, - - /* ws events*/ - CW_PENDING_WS_ACTIVATE = 1 << 1, - CW_PENDING_WS_DEACTIVATE = 1 << 2, - CW_PENDING_WS_REMOVE = 1 << 3, -}; - -void cosmic_group_output_send_initial_state(struct lab_cosmic_workspace_group *group, - struct wl_resource *group_resource); - -void cosmic_manager_schedule_done_event(struct lab_cosmic_workspace_manager *manager); - -#endif /* LABWC_PROTOCOLS_COSMIC_WORKSPACES_INTERNAL_H */ diff --git a/include/protocols/cosmic-workspaces.h b/include/protocols/cosmic-workspaces.h deleted file mode 100644 index 8776bfad..00000000 --- a/include/protocols/cosmic-workspaces.h +++ /dev/null @@ -1,94 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -#ifndef LABWC_PROTOCOLS_COSMIC_WORKSPACES_H -#define LABWC_PROTOCOLS_COSMIC_WORKSPACES_H - -#include -#include - -struct wlr_output; - -struct lab_cosmic_workspace_manager { - struct wl_global *global; - struct wl_list groups; - uint32_t caps; - struct wl_event_source *idle_source; - struct wl_event_loop *event_loop; - - struct { - struct wl_listener display_destroy; - } on; - - struct wl_list resources; -}; - -struct lab_cosmic_workspace_group { - struct lab_cosmic_workspace_manager *manager; - struct wl_list workspaces; - struct wl_array capabilities; - struct { - struct wl_signal create_workspace; - struct wl_signal destroy; - } events; - - struct wl_list link; - struct wl_list outputs; - struct wl_list resources; -}; - -struct lab_cosmic_workspace { - struct lab_cosmic_workspace_group *group; - char *name; - struct wl_array coordinates; - struct wl_array capabilities; - uint32_t state; /* enum lab_cosmic_workspace_state */ - uint32_t state_pending; /* enum lab_cosmic_workspace_state */ - - struct { - struct wl_signal activate; - struct wl_signal deactivate; - struct wl_signal remove; - struct wl_signal destroy; - } events; - - struct wl_list link; - struct wl_list resources; -}; - -enum lab_cosmic_workspace_caps { - CW_CAP_NONE = 0, - CW_CAP_GRP_ALL = 0x000000ff, - CW_CAP_WS_ALL = 0x0000ff00, - - /* group caps */ - CW_CAP_GRP_WS_CREATE = 1 << 0, - - /* workspace caps */ - CW_CAP_WS_ACTIVATE = 1 << 8, - CW_CAP_WS_DEACTIVATE = 1 << 9, - CW_CAP_WS_REMOVE = 1 << 10, -}; - -struct lab_cosmic_workspace_manager *lab_cosmic_workspace_manager_create( - struct wl_display *display, uint32_t caps, uint32_t version); - -struct lab_cosmic_workspace_group *lab_cosmic_workspace_group_create( - struct lab_cosmic_workspace_manager *manager); - -void lab_cosmic_workspace_group_output_enter( - struct lab_cosmic_workspace_group *group, struct wlr_output *output); - -void lab_cosmic_workspace_group_output_leave( - - struct lab_cosmic_workspace_group *group, struct wlr_output *output); -void lab_cosmic_workspace_group_destroy(struct lab_cosmic_workspace_group *group); - -struct lab_cosmic_workspace *lab_cosmic_workspace_create(struct lab_cosmic_workspace_group *group); -void lab_cosmic_workspace_set_name(struct lab_cosmic_workspace *workspace, const char *name); -void lab_cosmic_workspace_set_active(struct lab_cosmic_workspace *workspace, bool enabled); -void lab_cosmic_workspace_set_urgent(struct lab_cosmic_workspace *workspace, bool enabled); -void lab_cosmic_workspace_set_hidden(struct lab_cosmic_workspace *workspace, bool enabled); -void lab_cosmic_workspace_set_coordinates(struct lab_cosmic_workspace *workspace, - struct wl_array *coordinates); -void lab_cosmic_workspace_destroy(struct lab_cosmic_workspace *workspace); - -#endif /* LABWC_PROTOCOLS_COSMIC_WORKSPACES_H */ diff --git a/include/protocols/ext-workspace-internal.h b/include/protocols/ext-workspace-internal.h deleted file mode 100644 index c5e7575f..00000000 --- a/include/protocols/ext-workspace-internal.h +++ /dev/null @@ -1,25 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -#ifndef LABWC_PROTOCOLS_EXT_WORKSPACES_INTERNAL_H -#define LABWC_PROTOCOLS_EXT_WORKSPACES_INTERNAL_H - -struct wl_resource; -struct lab_ext_workspace_group; -struct lab_ext_workspace_manager; - -enum pending_ext_workspaces_change { - /* group events */ - WS_PENDING_WS_CREATE = 1 << 0, - - /* ws events*/ - WS_PENDING_WS_ACTIVATE = 1 << 1, - WS_PENDING_WS_DEACTIVATE = 1 << 2, - WS_PENDING_WS_REMOVE = 1 << 3, - WS_PENDING_WS_ASSIGN = 1 << 4, -}; - -void ext_group_output_send_initial_state(struct lab_ext_workspace_group *group, - struct wl_resource *group_resource); - -void ext_manager_schedule_done_event(struct lab_ext_workspace_manager *manager); - -#endif /* LABWC_PROTOCOLS_EXT_WORKSPACES_INTERNAL_H */ diff --git a/include/protocols/ext-workspace.h b/include/protocols/ext-workspace.h deleted file mode 100644 index cc422ac5..00000000 --- a/include/protocols/ext-workspace.h +++ /dev/null @@ -1,109 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -#ifndef LABWC_PROTOCOLS_EXT_WORKSPACES_H -#define LABWC_PROTOCOLS_EXT_WORKSPACES_H - -#include -#include - -struct wlr_output; - -struct lab_ext_workspace_manager { - struct wl_global *global; - struct wl_list groups; - struct wl_list workspaces; - uint32_t caps; - struct wl_event_source *idle_source; - struct wl_event_loop *event_loop; - - struct { - struct wl_listener display_destroy; - } on; - - struct wl_list resources; -}; - -struct lab_ext_workspace_group { - struct lab_ext_workspace_manager *manager; - uint32_t capabilities; - struct { - struct wl_signal create_workspace; - struct wl_signal destroy; - } events; - - struct wl_list link; - struct wl_list outputs; - struct wl_list resources; -}; - -struct lab_ext_workspace { - struct lab_ext_workspace_manager *manager; - struct lab_ext_workspace_group *group; - char *id; - char *name; - struct wl_array coordinates; - uint32_t capabilities; - uint32_t state; /* enum lab_ext_workspace_state */ - uint32_t state_pending; /* enum lab_ext_workspace_state */ - - struct { - struct wl_signal activate; - struct wl_signal deactivate; - struct wl_signal remove; - struct wl_signal assign; - struct wl_signal destroy; - } events; - - struct wl_list link; - struct wl_list resources; -}; - -enum lab_ext_workspace_caps { - WS_CAP_NONE = 0, - WS_CAP_GRP_ALL = 0x0000ffff, - WS_CAP_WS_ALL = 0xffff0000, - - /* group caps */ - WS_CAP_GRP_WS_CREATE = 1 << 0, - - /* workspace caps */ - WS_CAP_WS_ACTIVATE = 1 << 16, - WS_CAP_WS_DEACTIVATE = 1 << 17, - WS_CAP_WS_REMOVE = 1 << 18, - WS_CAP_WS_ASSIGN = 1 << 19, -}; - -struct lab_ext_workspace_manager *lab_ext_workspace_manager_create( - struct wl_display *display, uint32_t caps, uint32_t version); - -struct lab_ext_workspace_group *lab_ext_workspace_group_create( - struct lab_ext_workspace_manager *manager); - -void lab_ext_workspace_group_output_enter( - struct lab_ext_workspace_group *group, struct wlr_output *output); - -void lab_ext_workspace_group_output_leave( - struct lab_ext_workspace_group *group, struct wlr_output *output); - -void lab_ext_workspace_group_destroy(struct lab_ext_workspace_group *group); - -/* Create a new workspace, id may be NULL */ -struct lab_ext_workspace *lab_ext_workspace_create( - struct lab_ext_workspace_manager *manager, const char *id); - -void lab_ext_workspace_assign_to_group(struct lab_ext_workspace *workspace, - struct lab_ext_workspace_group *group); - -void lab_ext_workspace_set_name(struct lab_ext_workspace *workspace, const char *name); - -void lab_ext_workspace_set_active(struct lab_ext_workspace *workspace, bool enabled); - -void lab_ext_workspace_set_urgent(struct lab_ext_workspace *workspace, bool enabled); - -void lab_ext_workspace_set_hidden(struct lab_ext_workspace *workspace, bool enabled); - -void lab_ext_workspace_set_coordinates(struct lab_ext_workspace *workspace, - struct wl_array *coordinates); - -void lab_ext_workspace_destroy(struct lab_ext_workspace *workspace); - -#endif /* LABWC_PROTOCOLS_EXT_WORKSPACES_H */ diff --git a/include/protocols/transaction-addon.h b/include/protocols/transaction-addon.h deleted file mode 100644 index 2c40b3dd..00000000 --- a/include/protocols/transaction-addon.h +++ /dev/null @@ -1,84 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -#ifndef LABWC_PROTOCOLS_TRANSACTION_ADDON_H -#define LABWC_PROTOCOLS_TRANSACTION_ADDON_H - -#include - -struct lab_transaction_op { - uint32_t change; - void *src; - void *data; - - struct { - struct wl_signal destroy; - } events; - - // Private - struct wl_list link; -}; - -struct lab_transaction_session_context { - int ref_count; - struct wl_list transaction_ops; -}; - -struct lab_wl_resource_addon { - struct lab_transaction_session_context *ctx; - void *data; -}; - -/* - * Creates a new addon which can be attached to a wl_resource via - * wl_resource_set_user_data() and retrieved via wl_resource_get_user_data(). - * - * Usually the ctx argument should be addon->ctx of the parent wl_resource. - * If it is NULL it will be created automatically which can be used for top - * level wl_resources (when a client binds a wl_global from the registry). - * - * The context refcount is increased by one after this call. - */ -struct lab_wl_resource_addon *lab_resource_addon_create( - struct lab_transaction_session_context *ctx); - -/* - * A generic transaction operation attached to - * a session context transaction operation list. - * - * All arguments other than the context are user defined. - * Use of an enum for pending_change is suggested. - * - * The client is responsible for eventually freeing the data - * passed in the void *src and *data arguments by listening - * to the events.destroy signal. The transaction operations can be - * looped through by using lab_transaction_for_each(trans_op, ctx). - */ -struct lab_transaction_op *lab_transaction_op_add( - struct lab_transaction_session_context *ctx, - uint32_t pending_change, void *src, void *data); - -/* - * Removes the transaction operation from the ctx list and frees it. - * - * Does *not* free any passed in src or data arguments. - * Use the events.destroy signal for that if necessary. - */ -void lab_transaction_op_destroy(struct lab_transaction_op *transaction_op); - -/* - * Destroys the addon. - * - * The context refcount is decreased by one. If it reaches - * zero the context will be free'd alongside the addon itself. - * If the context is destroyed all pending transaction operations - * are destroyed as well. - */ -void lab_resource_addon_destroy(struct lab_wl_resource_addon *addon); - -/* Convenience wrappers for looping through the pending transaction ops of a ctx */ -#define lab_transaction_for_each(transaction_op, ctx) \ - wl_list_for_each(transaction_op, &(ctx)->transaction_ops, link) - -#define lab_transaction_for_each_safe(trans_op, trans_op_tmp, ctx) \ - wl_list_for_each_safe(trans_op, trans_op_tmp, &(ctx)->transaction_ops, link) - -#endif /* LABWC_PROTOCOLS_TRANSACTIONS_ADDON_H */ diff --git a/include/workspaces.h b/include/workspaces.h index f5543548..f0e5d419 100644 --- a/include/workspaces.h +++ b/include/workspaces.h @@ -21,20 +21,7 @@ struct workspace { char *name; struct wlr_scene_tree *tree; - struct lab_cosmic_workspace *cosmic_workspace; - struct { - struct wl_listener activate; - struct wl_listener deactivate; - struct wl_listener remove; - } on_cosmic; - - struct lab_ext_workspace *ext_workspace; - struct { - struct wl_listener activate; - struct wl_listener deactivate; - struct wl_listener assign; - struct wl_listener remove; - } on_ext; + struct wlr_ext_workspace_handle_v1 *ext_workspace; }; void workspaces_init(struct server *server); diff --git a/protocols/cosmic-workspace-unstable-v1.xml b/protocols/cosmic-workspace-unstable-v1.xml deleted file mode 100644 index 76adedd9..00000000 --- a/protocols/cosmic-workspace-unstable-v1.xml +++ /dev/null @@ -1,364 +0,0 @@ - - - - Copyright © 2019 Christopher Billington - Copyright © 2020 Ilia Bozhinov - Copyright © 2022 Victoria Brekenfeld - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that copyright notice and this permission - notice appear in supporting documentation, and that the name of - the copyright holders not be used in advertising or publicity - pertaining to distribution of the software without specific, - written prior permission. The copyright holders make no - representations about the suitability of this software for any - purpose. It is provided "as is" without express or implied - warranty. - - THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - THIS SOFTWARE. - - - - - Workspaces, also called virtual desktops, are groups of surfaces. A - compositor with a concept of workspaces may only show some such groups of - surfaces (those of 'active' workspaces) at a time. 'Activating' a - workspace is a request for the compositor to display that workspace's - surfaces as normal, whereas the compositor may hide or otherwise - de-emphasise surfaces that are associated only with 'inactive' workspaces. - Workspaces are grouped by which sets of outputs they correspond to, and - may contain surfaces only from those outputs. In this way, it is possible - for each output to have its own set of workspaces, or for all outputs (or - any other arbitrary grouping) to share workspaces. Compositors may - optionally conceptually arrange each group of workspaces in an - N-dimensional grid. - - The purpose of this protocol is to enable the creation of taskbars and - docks by providing them with a list of workspaces and their properties, - and allowing them to activate and deactivate workspaces. - - After a client binds the zcosmic_workspace_manager_v1, each workspace will be - sent via the workspace event. - - - - - This event is emitted whenever a new workspace group has been created. - - All initial details of the workspace group (workspaces, outputs) will be - sent immediately after this event via the corresponding events in - zcosmic_workspace_group_handle_v1. - - - - - - - The client must send this request after it has finished sending other - requests. The compositor must process a series of requests preceding a - commit request atomically. - - This allows changes to the workspace properties to be seen as atomic, - even if they happen via multiple events, and even if they involve - multiple zcosmic_workspace_handle_v1 objects, for example, deactivating one - workspace and activating another. - - - - - - This event is sent after all changes in all workspace groups have been - sent. - - This allows changes to one or more zcosmic_workspace_group_handle_v1 - properties and zcosmic_workspace_handle_v1 properties to be seen as atomic, - even if they happen via multiple events. - In particular, an output moving from one workspace group to - another sends an output_enter event and an output_leave event to the two - zcosmic_workspace_group_handle_v1 objects in question. The compositor sends - the done event only after updating the output information in both - workspace groups. - - - - - - This event indicates that the compositor is done sending events to the - zcosmic_workspace_manager_v1. The server will destroy the object - immediately after sending this request, so it will become invalid and - the client should free any resources associated with it. - - - - - - Indicates the client no longer wishes to receive events for new - workspace groups. However the compositor may emit further workspace - events, until the finished event is emitted. - - The client must not send any more requests after this one. - - - - - - - A zcosmic_workspace_group_handle_v1 object represents a a workspace group - that is assigned a set of outputs and contains a number of workspaces. - - The set of outputs assigned to the workspace group is conveyed to the client via - output_enter and output_leave events, and its workspaces are conveyed with - workspace events. - - For example, a compositor which has a set of workspaces for each output may - advertise a workspace group (and its workspaces) per output, whereas a compositor - where a workspace spans all outputs may advertise a single workspace group for all - outputs. - - - - - - - - - This event advertises the capabilities supported by the compositor. If - a capability isn't supported, clients should hide or disable the UI - elements that expose this functionality. For instance, if the - compositor doesn't advertise support for creating workspaces, a button - triggering the create_workspace request should not be displayed. - - The compositor will ignore requests it doesn't support. For instance, - a compositor which doesn't advertise support for creating workspaces will ignore - create_workspace requests. - - Compositors must send this event once after creation of an - zcosmic_workspace_group_handle_v1 . When the capabilities change, compositors - must send this event again. - - The capabilities are sent as an array of 32-bit unsigned integers in - native endianness. - - - - - - - This event is emitted whenever an output is assigned to the workspace - group. - - - - - - - This event is emitted whenever an output is removed from the workspace - group. - - - - - - - This event is emitted whenever a new workspace has been created. - A workspace can only be a member of a single workspace group and cannot - be re-assigned. - - All initial details of the workspace (name, coordinates, state) will - be sent immediately after this event via the corresponding events in - zcosmic_workspace_handle_v1. - - - - - - - This event means the zcosmic_workspace_group_handle_v1 has been destroyed. - It is guaranteed there won't be any more events for this - zcosmic_workspace_group_handle_v1. The zext_workspace_group_handle_v1 becomes - inert so any requests will be ignored except the destroy request. - - The compositor must remove all workspaces belonging to a workspace group - before removing the workspace group. - - - - - - Request that the compositor create a new workspace with the given name. - - There is no guarantee that the compositor will create a new workspace, - or that the created workspace will have the provided name. - - - - - - - Destroys the zcosmic_workspace_group_handle_v1 object. - - This request should be called either when the client does not want to - use the workspace object any more or after the remove event to finalize - the destruction of the object. - - - - - - - A zcosmic_workspace_handle_v1 object represents a a workspace that handles a - group of surfaces. - - Each workspace has a name, conveyed to the client with the name event; a - list of states, conveyed to the client with the state event; and - optionally a set of coordinates, conveyed to the client with the - coordinates event. The client may request that the compositor activate or - deactivate the workspace. - - Each workspace can belong to only a single workspace group. - Depepending on the compositor policy, there might be workspaces with - the same name in different workspace groups, but these workspaces are still - separate (e.g. one of them might be active while the other is not). - - - - - This event is emitted immediately after the zcosmic_workspace_handle_v1 is - created and whenever the name of the workspace changes. - - - - - - - This event is used to organize workspaces into an N-dimensional grid - within a workspace group, and if supported, is emitted immediately after - the zcosmic_workspace_handle_v1 is created and whenever the coordinates of - the workspace change. Compositors may not send this event if they do not - conceptually arrange workspaces in this way. If compositors simply - number workspaces, without any geometric interpretation, they may send - 1D coordinates, which clients should not interpret as implying any - geometry. Sending an empty array means that the compositor no longer - orders the workspace geometrically. - - Coordinates have an arbitrary number of dimensions N with an uint32 - position along each dimension. By convention if N > 1, the first - dimension is X, the second Y, the third Z, and so on. The compositor may - chose to utilize these events for a more novel workspace layout - convention, however. No guarantee is made about the grid being filled or - bounded; there may be a workspace at coordinate 1 and another at - coordinate 1000 and none in between. Within a workspace group, however, - workspaces must have unique coordinates of equal dimensionality. - - - - - - - This event is emitted immediately after the zcosmic_workspace_handle_v1 is - created and each time the workspace state changes, either because of a - compositor action or because of a request in this protocol. - - - - - - - The different states that a workspace can have. - - - - - - - The workspace is not visible in its workspace group, and clients - attempting to visualize the compositor workspace state should not - display such workspaces. - - - - - - - - - - - - - This event advertises the capabilities supported by the compositor. If - a capability isn't supported, clients should hide or disable the UI - elements that expose this functionality. For instance, if the - compositor doesn't advertise support for removing workspaces, a button - triggering the remove request should not be displayed. - - The compositor will ignore requests it doesn't support. For instance, - a compositor which doesn't advertise support for remove will ignore - remove requests. - - Compositors must send this event once after creation of an - zcosmic_workspace_handle_v1 . When the capabilities change, compositors - must send this event again. - - The capabilities are sent as an array of 32-bit unsigned integers in - native endianness. - - - - - - - This event means the zcosmic_workspace_handle_v1 has been destroyed. It is - guaranteed there won't be any more events for this - zcosmic_workspace_handle_v1. The zext_workspace_handle_v1 becomes inert so - any requests will be ignored except the destroy request. - - - - - - Destroys the zcosmic_workspace_handle_v1 object. - - This request should be called either when the client does not want to - use the workspace object any more or after the remove event to finalize - the destruction of the object. - - - - - - Request that this workspace be activated. - - There is no guarantee the workspace will be actually activated, and - behaviour may be compositor-dependent. For example, activating a - workspace may or may not deactivate all other workspaces in the same - group. - - - - - - Request that this workspace be deactivated. - - There is no guarantee the workspace will be actually deactivated. - - - - - - Request that this workspace be removed. - - There is no guarantee the workspace will be actually removed. - - - - diff --git a/protocols/meson.build b/protocols/meson.build index 67c0d3d2..f360210e 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -25,7 +25,6 @@ server_protocols = [ wl_protocol_dir / 'staging/ext-workspace/ext-workspace-v1.xml', wl_protocol_dir / 'staging/ext-image-capture-source/ext-image-capture-source-v1.xml', wl_protocol_dir / 'staging/ext-image-copy-capture/ext-image-copy-capture-v1.xml', - 'cosmic-workspace-unstable-v1.xml', 'wlr-layer-shell-unstable-v1.xml', 'wlr-output-power-management-unstable-v1.xml', ] diff --git a/src/meson.build b/src/meson.build index a9afdc4f..40ec3170 100644 --- a/src/meson.build +++ b/src/meson.build @@ -55,6 +55,5 @@ subdir('foreign-toplevel') subdir('img') subdir('input') subdir('menu') -subdir('protocols') subdir('scaled-buffer') subdir('ssd') diff --git a/src/output.c b/src/output.c index d25d2736..9447af65 100644 --- a/src/output.c +++ b/src/output.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -31,8 +32,6 @@ #include "node.h" #include "output-state.h" #include "output-virtual.h" -#include "protocols/cosmic-workspaces.h" -#include "protocols/ext-workspace.h" #include "regions.h" #include "session-lock.h" #include "view.h" @@ -281,9 +280,7 @@ add_output_to_layout(struct server *server, struct output *output) layout_output, output->scene_output); } - lab_cosmic_workspace_group_output_enter( - server->workspaces.cosmic_group, output->wlr_output); - lab_ext_workspace_group_output_enter( + wlr_ext_workspace_group_handle_v1_output_enter( server->workspaces.ext_group, output->wlr_output); /* (Re-)create regions from config */ @@ -728,9 +725,7 @@ output_config_apply(struct server *server, } else if (was_in_layout) { regions_evacuate_output(output); - lab_cosmic_workspace_group_output_leave( - server->workspaces.cosmic_group, output->wlr_output); - lab_ext_workspace_group_output_leave( + wlr_ext_workspace_group_handle_v1_output_leave( server->workspaces.ext_group, output->wlr_output); /* diff --git a/src/protocols/cosmic_workspaces/cosmic-workspaces.c b/src/protocols/cosmic_workspaces/cosmic-workspaces.c deleted file mode 100644 index d12611cb..00000000 --- a/src/protocols/cosmic_workspaces/cosmic-workspaces.c +++ /dev/null @@ -1,717 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -#include -#include -#include "common/array.h" -#include "common/mem.h" -#include "common/list.h" -#include "cosmic-workspace-unstable-v1-protocol.h" -#include "protocols/cosmic-workspaces.h" -#include "protocols/cosmic-workspaces-internal.h" -#include "protocols/transaction-addon.h" - -/* - * .--------------------. - * | TODO | - * |--------------------| - * | - prevent empty | - * | done events | - * | - go through xml | - * | and verify impl | - * | - assert pub API | - * `--------------------´ - * - */ - -/* Only used within an assert() */ -#ifndef NDEBUG - #define COSMIC_WORKSPACE_V1_VERSION 1 -#endif - -/* These are just *waaay* too long */ -#define ZCOSMIC_CAP_WS_CREATE \ - ZCOSMIC_WORKSPACE_GROUP_HANDLE_V1_ZCOSMIC_WORKSPACE_GROUP_CAPABILITIES_V1_CREATE_WORKSPACE -#define ZCOSMIC_CAP_WS_ACTIVATE \ - ZCOSMIC_WORKSPACE_HANDLE_V1_ZCOSMIC_WORKSPACE_CAPABILITIES_V1_ACTIVATE -#define ZCOSMIC_CAP_WS_DEACTIVATE \ - ZCOSMIC_WORKSPACE_HANDLE_V1_ZCOSMIC_WORKSPACE_CAPABILITIES_V1_DEACTIVATE -#define ZCOSMIC_CAP_WS_REMOVE \ - ZCOSMIC_WORKSPACE_HANDLE_V1_ZCOSMIC_WORKSPACE_CAPABILITIES_V1_REMOVE - -enum workspace_state { - CW_WS_STATE_ACTIVE = 1 << 0, - CW_WS_STATE_URGENT = 1 << 1, - CW_WS_STATE_HIDDEN = 1 << 2, - - /* - * Set when creating a new workspace so we - * don't end up having to send the state twice. - */ - CW_WS_STATE_INVALID = 1 << 31, -}; - -struct ws_create_workspace_event { - char *name; - struct { - struct wl_listener transaction_op_destroy; - } on; -}; - -static void -add_caps(struct wl_array *caps_arr, uint32_t caps) -{ - if (caps == CW_CAP_NONE) { - return; - } - if (caps & CW_CAP_GRP_WS_CREATE) { - array_add(caps_arr, ZCOSMIC_CAP_WS_CREATE); - } - if (caps & CW_CAP_WS_ACTIVATE) { - array_add(caps_arr, ZCOSMIC_CAP_WS_ACTIVATE); - } - if (caps & CW_CAP_WS_DEACTIVATE) { - array_add(caps_arr, ZCOSMIC_CAP_WS_DEACTIVATE); - } - if (caps & CW_CAP_WS_REMOVE) { - array_add(caps_arr, ZCOSMIC_CAP_WS_REMOVE); - } -} - -/* Workspace */ -static void -workspace_handle_destroy(struct wl_client *client, struct wl_resource *resource) -{ - wl_resource_destroy(resource); -} - -static void -workspace_handle_activate(struct wl_client *client, struct wl_resource *resource) -{ - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (!addon) { - /* workspace was destroyed from the compositor side */ - return; - } - struct lab_cosmic_workspace *workspace = addon->data; - lab_transaction_op_add(addon->ctx, CW_PENDING_WS_ACTIVATE, - workspace, /*data*/ NULL); -} - -static void -workspace_handle_deactivate(struct wl_client *client, struct wl_resource *resource) -{ - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (!addon) { - /* Workspace was destroyed from the compositor side */ - return; - } - struct lab_cosmic_workspace *workspace = addon->data; - lab_transaction_op_add(addon->ctx, CW_PENDING_WS_DEACTIVATE, - workspace, /*data*/ NULL); -} - -static void -workspace_handle_remove(struct wl_client *client, struct wl_resource *resource) -{ - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (!addon) { - /* workspace was destroyed from the compositor side */ - return; - } - struct lab_cosmic_workspace *workspace = addon->data; - lab_transaction_op_add(addon->ctx, CW_PENDING_WS_REMOVE, - workspace, /*data*/ NULL); -} - -static const struct zcosmic_workspace_handle_v1_interface workspace_impl = { - .destroy = workspace_handle_destroy, - .activate = workspace_handle_activate, - .deactivate = workspace_handle_deactivate, - .remove = workspace_handle_remove, -}; - -static void -workspace_instance_resource_destroy(struct wl_resource *resource) -{ - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (addon) { - lab_resource_addon_destroy(addon); - wl_resource_set_user_data(resource, NULL); - } - - wl_list_remove(wl_resource_get_link(resource)); -} - -static struct wl_resource * -workspace_resource_create(struct lab_cosmic_workspace *workspace, - struct wl_resource *group_resource, struct lab_transaction_session_context *ctx) -{ - struct wl_client *client = wl_resource_get_client(group_resource); - struct wl_resource *resource = wl_resource_create(client, - &zcosmic_workspace_handle_v1_interface, - wl_resource_get_version(group_resource), 0); - if (!resource) { - wl_client_post_no_memory(client); - return NULL; - } - - struct lab_wl_resource_addon *addon = lab_resource_addon_create(ctx); - addon->data = workspace; - - wl_resource_set_implementation(resource, &workspace_impl, addon, - workspace_instance_resource_destroy); - - wl_list_insert(&workspace->resources, wl_resource_get_link(resource)); - return resource; -} - -/* Workspace internal helpers */ -static void -workspace_send_state(struct lab_cosmic_workspace *workspace, struct wl_resource *target) -{ - struct wl_array state; - wl_array_init(&state); - - if (workspace->state & CW_WS_STATE_ACTIVE) { - array_add(&state, ZCOSMIC_WORKSPACE_HANDLE_V1_STATE_ACTIVE); - } - if (workspace->state & CW_WS_STATE_URGENT) { - array_add(&state, ZCOSMIC_WORKSPACE_HANDLE_V1_STATE_URGENT); - } - if (workspace->state & CW_WS_STATE_HIDDEN) { - array_add(&state, ZCOSMIC_WORKSPACE_HANDLE_V1_STATE_HIDDEN); - } - - if (target) { - zcosmic_workspace_handle_v1_send_state(target, &state); - } else { - struct wl_resource *resource; - wl_resource_for_each(resource, &workspace->resources) { - zcosmic_workspace_handle_v1_send_state(resource, &state); - } - } - - wl_array_release(&state); -} - -static void -workspace_send_initial_state(struct lab_cosmic_workspace *workspace, struct wl_resource *resource) -{ - zcosmic_workspace_handle_v1_send_capabilities(resource, &workspace->capabilities); - if (workspace->coordinates.size > 0) { - zcosmic_workspace_handle_v1_send_coordinates(resource, &workspace->coordinates); - } - if (workspace->name) { - zcosmic_workspace_handle_v1_send_name(resource, workspace->name); - } -} - -static void -workspace_set_state(struct lab_cosmic_workspace *workspace, - enum workspace_state state, bool enabled) -{ - if (!!(workspace->state_pending & state) == enabled) { - return; - } - - if (enabled) { - workspace->state_pending |= state; - } else { - workspace->state_pending &= ~state; - } - cosmic_manager_schedule_done_event(workspace->group->manager); -} - -/* Group */ -static void -ws_create_workspace_handle_transaction_op_destroy(struct wl_listener *listener, void *data) -{ - struct ws_create_workspace_event *ev = - wl_container_of(listener, ev, on.transaction_op_destroy); - wl_list_remove(&ev->on.transaction_op_destroy.link); - free(ev->name); - free(ev); -} - -static void -group_handle_create_workspace(struct wl_client *client, - struct wl_resource *resource, const char *name) -{ - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (!addon) { - return; - } - - struct lab_cosmic_workspace_group *group = addon->data; - struct ws_create_workspace_event *ev = znew(*ev); - ev->name = xstrdup(name); - - struct lab_transaction_op *transaction_op = lab_transaction_op_add( - addon->ctx, CW_PENDING_WS_CREATE, group, ev); - - ev->on.transaction_op_destroy.notify = - ws_create_workspace_handle_transaction_op_destroy; - wl_signal_add(&transaction_op->events.destroy, &ev->on.transaction_op_destroy); -} - -static void -group_handle_destroy(struct wl_client *client, struct wl_resource *resource) -{ - wl_resource_destroy(resource); -} - -static const struct zcosmic_workspace_group_handle_v1_interface group_impl = { - .create_workspace = group_handle_create_workspace, - .destroy = group_handle_destroy, -}; - -static void -group_instance_resource_destroy(struct wl_resource *resource) -{ - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (addon) { - lab_resource_addon_destroy(addon); - wl_resource_set_user_data(resource, NULL); - } - wl_list_remove(wl_resource_get_link(resource)); -} - -static struct wl_resource * -group_resource_create(struct lab_cosmic_workspace_group *group, - struct wl_resource *manager_resource, struct lab_transaction_session_context *ctx) -{ - struct wl_client *client = wl_resource_get_client(manager_resource); - struct wl_resource *resource = wl_resource_create(client, - &zcosmic_workspace_group_handle_v1_interface, - wl_resource_get_version(manager_resource), 0); - if (!resource) { - wl_client_post_no_memory(client); - return NULL; - } - - struct lab_wl_resource_addon *addon = lab_resource_addon_create(ctx); - addon->data = group; - - wl_resource_set_implementation(resource, &group_impl, addon, - group_instance_resource_destroy); - - wl_list_insert(&group->resources, wl_resource_get_link(resource)); - return resource; -} - -/* Group internal helpers */ -static void -group_send_state(struct lab_cosmic_workspace_group *group, struct wl_resource *resource) -{ - zcosmic_workspace_group_handle_v1_send_capabilities( - resource, &group->capabilities); - - cosmic_group_output_send_initial_state(group, resource); -} - -/* Manager itself */ -static void -manager_handle_commit(struct wl_client *client, struct wl_resource *resource) -{ - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (!addon) { - return; - } - - struct lab_cosmic_workspace *workspace; - struct lab_cosmic_workspace_group *group; - struct lab_transaction_op *trans_op, *trans_op_tmp; - lab_transaction_for_each_safe(trans_op, trans_op_tmp, addon->ctx) { - switch (trans_op->change) { - case CW_PENDING_WS_CREATE: { - group = trans_op->src; - struct ws_create_workspace_event *ev = trans_op->data; - wl_signal_emit_mutable(&group->events.create_workspace, ev->name); - break; - } - case CW_PENDING_WS_ACTIVATE: - workspace = trans_op->src; - wl_signal_emit_mutable(&workspace->events.activate, NULL); - break; - case CW_PENDING_WS_DEACTIVATE: - workspace = trans_op->src; - wl_signal_emit_mutable(&workspace->events.deactivate, NULL); - break; - case CW_PENDING_WS_REMOVE: - workspace = trans_op->src; - wl_signal_emit_mutable(&workspace->events.remove, NULL); - break; - default: - wlr_log(WLR_ERROR, "Invalid transaction state: %u", trans_op->change); - } - - lab_transaction_op_destroy(trans_op); - } -} - -static void -manager_handle_stop(struct wl_client *client, struct wl_resource *resource) -{ - zcosmic_workspace_manager_v1_send_finished(resource); - wl_resource_destroy(resource); -} - -static const struct zcosmic_workspace_manager_v1_interface manager_impl = { - .commit = manager_handle_commit, - .stop = manager_handle_stop, -}; - -static void -manager_instance_resource_destroy(struct wl_resource *resource) -{ - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (addon) { - lab_resource_addon_destroy(addon); - wl_resource_set_user_data(resource, NULL); - } - - wl_list_remove(wl_resource_get_link(resource)); -} - -static void -manager_handle_bind(struct wl_client *client, void *data, - uint32_t version, uint32_t id) -{ - struct lab_cosmic_workspace_manager *manager = data; - struct wl_resource *resource = wl_resource_create(client, - &zcosmic_workspace_manager_v1_interface, - version, id); - if (!resource) { - wl_client_post_no_memory(client); - return; - } - - struct lab_wl_resource_addon *addon = - lab_resource_addon_create(/* session context*/ NULL); - addon->data = manager; - - wl_resource_set_implementation(resource, &manager_impl, - addon, manager_instance_resource_destroy); - - wl_list_insert(&manager->resources, wl_resource_get_link(resource)); - - struct lab_cosmic_workspace *workspace; - struct lab_cosmic_workspace_group *group; - wl_list_for_each(group, &manager->groups, link) { - /* Create group resource */ - struct wl_resource *group_resource = - group_resource_create(group, resource, addon->ctx); - zcosmic_workspace_manager_v1_send_workspace_group(resource, group_resource); - group_send_state(group, group_resource); - - /* Create workspace resource */ - wl_list_for_each(workspace, &group->workspaces, link) { - struct wl_resource *workspace_resource = - workspace_resource_create(workspace, group_resource, addon->ctx); - zcosmic_workspace_group_handle_v1_send_workspace( - group_resource, workspace_resource); - workspace_send_initial_state(workspace, workspace_resource); - /* Send the current workspace state manually */ - workspace_send_state(workspace, workspace_resource); - } - } - zcosmic_workspace_manager_v1_send_done(resource); -} - -static void -manager_handle_display_destroy(struct wl_listener *listener, void *data) -{ - struct lab_cosmic_workspace_manager *manager = - wl_container_of(listener, manager, on.display_destroy); - - struct lab_cosmic_workspace_group *group, *tmp; - wl_list_for_each_safe(group, tmp, &manager->groups, link) { - lab_cosmic_workspace_group_destroy(group); - } - - if (manager->idle_source) { - wl_event_source_remove(manager->idle_source); - } - - wl_list_remove(&manager->on.display_destroy.link); - wl_global_destroy(manager->global); - free(manager); -} - -/* Manager internal helpers */ -static void -manager_idle_send_done(void *data) -{ - struct lab_cosmic_workspace_manager *manager = data; - - struct lab_cosmic_workspace *workspace; - struct lab_cosmic_workspace_group *group; - wl_list_for_each(group, &manager->groups, link) { - wl_list_for_each(workspace, &group->workspaces, link) { - if (workspace->state != workspace->state_pending) { - workspace->state = workspace->state_pending; - workspace_send_state(workspace, /*target*/ NULL); - } - } - } - - struct wl_resource *resource; - wl_resource_for_each(resource, &manager->resources) { - zcosmic_workspace_manager_v1_send_done(resource); - } - manager->idle_source = NULL; -} - -/* Internal API */ -void -cosmic_manager_schedule_done_event(struct lab_cosmic_workspace_manager *manager) -{ - if (manager->idle_source) { - return; - } - if (!manager->event_loop) { - return; - } - manager->idle_source = wl_event_loop_add_idle( - manager->event_loop, manager_idle_send_done, manager); -} - -/* Public API */ -struct lab_cosmic_workspace_manager * -lab_cosmic_workspace_manager_create(struct wl_display *display, uint32_t caps, uint32_t version) -{ - assert(version <= COSMIC_WORKSPACE_V1_VERSION); - - struct lab_cosmic_workspace_manager *manager = znew(*manager); - manager->global = wl_global_create(display, - &zcosmic_workspace_manager_v1_interface, - version, manager, manager_handle_bind); - - if (!manager->global) { - free(manager); - return NULL; - } - - manager->caps = caps; - manager->event_loop = wl_display_get_event_loop(display); - - manager->on.display_destroy.notify = manager_handle_display_destroy; - wl_display_add_destroy_listener(display, &manager->on.display_destroy); - - wl_list_init(&manager->groups); - wl_list_init(&manager->resources); - return manager; -} - -struct lab_cosmic_workspace_group * -lab_cosmic_workspace_group_create(struct lab_cosmic_workspace_manager *manager) -{ - assert(manager); - - struct lab_cosmic_workspace_group *group = znew(*group); - group->manager = manager; - - wl_array_init(&group->capabilities); - add_caps(&group->capabilities, manager->caps & CW_CAP_GRP_ALL); - - wl_list_init(&group->outputs); - wl_list_init(&group->resources); - wl_list_init(&group->workspaces); - wl_signal_init(&group->events.create_workspace); - wl_signal_init(&group->events.destroy); - - wl_list_append(&manager->groups, &group->link); - - struct wl_resource *resource, *tmp; - wl_resource_for_each_safe(resource, tmp, &manager->resources) { - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - assert(addon && addon->ctx); - struct wl_resource *group_resource = - group_resource_create(group, resource, addon->ctx); - zcosmic_workspace_manager_v1_send_workspace_group(resource, group_resource); - group_send_state(group, group_resource); - } - cosmic_manager_schedule_done_event(manager); - - return group; -} - -void -lab_cosmic_workspace_group_destroy(struct lab_cosmic_workspace_group *group) -{ - if (!group) { - return; - } - wl_signal_emit_mutable(&group->events.destroy, NULL); - - struct lab_cosmic_workspace *ws, *ws_tmp; - wl_list_for_each_safe(ws, ws_tmp, &group->workspaces, link) { - lab_cosmic_workspace_destroy(ws); - } - - struct wl_resource *resource, *res_tmp; - wl_resource_for_each_safe(resource, res_tmp, &group->resources) { - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (addon) { - lab_resource_addon_destroy(addon); - wl_resource_set_user_data(resource, NULL); - } - zcosmic_workspace_group_handle_v1_send_remove(resource); - wl_list_remove(wl_resource_get_link(resource)); - wl_list_init(wl_resource_get_link(resource)); - } - - /* Cancel pending transaction operations involving this group */ - struct lab_transaction_op *trans_op, *trans_op_tmp; - wl_resource_for_each(resource, &group->manager->resources) { - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (!addon) { - continue; - } - lab_transaction_for_each_safe(trans_op, trans_op_tmp, addon->ctx) { - if (trans_op->src == group) { - lab_transaction_op_destroy(trans_op); - } - } - } - - wl_list_remove(&group->link); - wl_array_release(&group->capabilities); - free(group); -} - -struct lab_cosmic_workspace * -lab_cosmic_workspace_create(struct lab_cosmic_workspace_group *group) -{ - assert(group); - - struct lab_cosmic_workspace *workspace = znew(*workspace); - workspace->group = group; - /* - * Ensures we are sending workspace->state_pending on the done event, - * regardless if the compositor has changed any state in between here - * and the scheduled done event or not. - * - * Without this we might have to send the state twice, first here and - * then again in the scheduled done event when there were any changes. - */ - workspace->state = CW_WS_STATE_INVALID; - - wl_array_init(&workspace->capabilities); - add_caps(&workspace->capabilities, group->manager->caps & CW_CAP_WS_ALL); - - wl_list_init(&workspace->resources); - wl_array_init(&workspace->coordinates); - wl_signal_init(&workspace->events.activate); - wl_signal_init(&workspace->events.deactivate); - wl_signal_init(&workspace->events.remove); - wl_signal_init(&workspace->events.destroy); - - wl_list_append(&group->workspaces, &workspace->link); - - /* Notify clients */ - struct wl_resource *group_resource; - wl_resource_for_each(group_resource, &group->resources) { - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(group_resource); - assert(addon && addon->ctx); - struct wl_resource *workspace_resource = - workspace_resource_create(workspace, group_resource, addon->ctx); - zcosmic_workspace_group_handle_v1_send_workspace( - group_resource, workspace_resource); - workspace_send_initial_state(workspace, workspace_resource); - } - cosmic_manager_schedule_done_event(group->manager); - - return workspace; -} - -void -lab_cosmic_workspace_set_name(struct lab_cosmic_workspace *workspace, const char *name) -{ - assert(workspace); - assert(name); - - if (!workspace->name || strcmp(workspace->name, name)) { - free(workspace->name); - workspace->name = xstrdup(name); - struct wl_resource *resource; - wl_resource_for_each(resource, &workspace->resources) { - zcosmic_workspace_handle_v1_send_name(resource, workspace->name); - } - } - cosmic_manager_schedule_done_event(workspace->group->manager); -} - -void -lab_cosmic_workspace_set_active(struct lab_cosmic_workspace *workspace, bool enabled) -{ - workspace_set_state(workspace, CW_WS_STATE_ACTIVE, enabled); -} - -void -lab_cosmic_workspace_set_urgent(struct lab_cosmic_workspace *workspace, bool enabled) -{ - workspace_set_state(workspace, CW_WS_STATE_URGENT, enabled); -} - -void -lab_cosmic_workspace_set_hidden(struct lab_cosmic_workspace *workspace, bool enabled) -{ - workspace_set_state(workspace, CW_WS_STATE_HIDDEN, enabled); -} - -void -lab_cosmic_workspace_set_coordinates(struct lab_cosmic_workspace *workspace, - struct wl_array *coordinates) -{ - wl_array_release(&workspace->coordinates); - wl_array_init(&workspace->coordinates); - wl_array_copy(&workspace->coordinates, coordinates); - - struct wl_resource *resource; - wl_resource_for_each(resource, &workspace->resources) { - zcosmic_workspace_handle_v1_send_coordinates(resource, &workspace->coordinates); - } - cosmic_manager_schedule_done_event(workspace->group->manager); -} - -void -lab_cosmic_workspace_destroy(struct lab_cosmic_workspace *workspace) -{ - if (!workspace) { - return; - } - wl_signal_emit_mutable(&workspace->events.destroy, NULL); - - struct wl_resource *resource, *tmp; - wl_resource_for_each_safe(resource, tmp, &workspace->resources) { - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (addon) { - lab_resource_addon_destroy(addon); - wl_resource_set_user_data(resource, NULL); - } - zcosmic_workspace_handle_v1_send_remove(resource); - wl_list_remove(wl_resource_get_link(resource)); - wl_list_init(wl_resource_get_link(resource)); - } - cosmic_manager_schedule_done_event(workspace->group->manager); - - /* Cancel pending transaction operations involving this workspace */ - struct lab_transaction_op *trans_op, *trans_op_tmp; - wl_resource_for_each(resource, &workspace->group->manager->resources) { - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (!addon) { - continue; - } - lab_transaction_for_each_safe(trans_op, trans_op_tmp, addon->ctx) { - if (trans_op->src == workspace) { - lab_transaction_op_destroy(trans_op); - } - } - } - - wl_list_remove(&workspace->link); - wl_array_release(&workspace->coordinates); - wl_array_release(&workspace->capabilities); - zfree(workspace->name); - free(workspace); -} diff --git a/src/protocols/cosmic_workspaces/meson.build b/src/protocols/cosmic_workspaces/meson.build deleted file mode 100644 index 31ce18b8..00000000 --- a/src/protocols/cosmic_workspaces/meson.build +++ /dev/null @@ -1,4 +0,0 @@ -labwc_sources += files( - 'cosmic-workspaces.c', - 'output.c', -) diff --git a/src/protocols/cosmic_workspaces/output.c b/src/protocols/cosmic_workspaces/output.c deleted file mode 100644 index 1e170e85..00000000 --- a/src/protocols/cosmic_workspaces/output.c +++ /dev/null @@ -1,174 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -#include -#include -#include -#include "common/mem.h" -#include "cosmic-workspace-unstable-v1-protocol.h" -#include "protocols/cosmic-workspaces.h" -#include "protocols/cosmic-workspaces-internal.h" - -struct group_output { - struct wlr_output *wlr_output; - struct lab_cosmic_workspace_group *group; - struct { - struct wl_listener group_destroy; - struct wl_listener output_bind; - struct wl_listener output_destroy; - } on; - - struct wl_list link; -}; - -/* Internal helpers */ -static void -group_output_send_event(struct wl_list *group_resources, struct wl_list *output_resources, - void (*notifier)(struct wl_resource *group, struct wl_resource *output)) -{ - struct wl_client *client; - struct wl_resource *group_resource, *output_resource; - wl_resource_for_each(group_resource, group_resources) { - client = wl_resource_get_client(group_resource); - wl_resource_for_each(output_resource, output_resources) { - if (wl_resource_get_client(output_resource) == client) { - notifier(group_resource, output_resource); - } - } - } -} - -static void -group_output_destroy(struct group_output *group_output) -{ - group_output_send_event( - &group_output->group->resources, - &group_output->wlr_output->resources, - zcosmic_workspace_group_handle_v1_send_output_leave); - - cosmic_manager_schedule_done_event(group_output->group->manager); - - wl_list_remove(&group_output->link); - wl_list_remove(&group_output->on.group_destroy.link); - wl_list_remove(&group_output->on.output_bind.link); - wl_list_remove(&group_output->on.output_destroy.link); - free(group_output); -} - -/* Event handlers */ -static void -handle_output_bind(struct wl_listener *listener, void *data) -{ - struct group_output *group_output = - wl_container_of(listener, group_output, on.output_bind); - - struct wlr_output_event_bind *event = data; - struct wl_client *client = wl_resource_get_client(event->resource); - - bool sent = false; - struct wl_resource *group_resource; - wl_resource_for_each(group_resource, &group_output->group->resources) { - if (wl_resource_get_client(group_resource) == client) { - zcosmic_workspace_group_handle_v1_send_output_enter( - group_resource, event->resource); - sent = true; - } - } - if (!sent) { - return; - } - - struct wl_resource *manager_resource; - struct wl_list *manager_resources = &group_output->group->manager->resources; - wl_resource_for_each(manager_resource, manager_resources) { - if (wl_resource_get_client(manager_resource) == client) { - zcosmic_workspace_manager_v1_send_done(manager_resource); - } - } -} - -static void -handle_output_destroy(struct wl_listener *listener, void *data) -{ - struct group_output *group_output = - wl_container_of(listener, group_output, on.output_destroy); - group_output_destroy(group_output); -} - -static void -handle_group_destroy(struct wl_listener *listener, void *data) -{ - struct group_output *group_output = - wl_container_of(listener, group_output, on.group_destroy); - group_output_destroy(group_output); -} - -/* Internal API*/ -void -cosmic_group_output_send_initial_state(struct lab_cosmic_workspace_group *group, - struct wl_resource *group_resource) -{ - struct group_output *group_output; - struct wl_resource *output_resource; - struct wl_client *client = wl_resource_get_client(group_resource); - wl_list_for_each(group_output, &group->outputs, link) { - wl_resource_for_each(output_resource, &group_output->wlr_output->resources) { - if (wl_resource_get_client(output_resource) == client) { - zcosmic_workspace_group_handle_v1_send_output_enter( - group_resource, output_resource); - } - } - } -} - -/* Public API */ -void -lab_cosmic_workspace_group_output_enter(struct lab_cosmic_workspace_group *group, - struct wlr_output *wlr_output) -{ - struct group_output *group_output; - wl_list_for_each(group_output, &group->outputs, link) { - if (group_output->wlr_output == wlr_output) { - return; - } - } - group_output = znew(*group_output); - group_output->wlr_output = wlr_output; - group_output->group = group; - - group_output->on.group_destroy.notify = handle_group_destroy; - wl_signal_add(&group->events.destroy, &group_output->on.group_destroy); - - group_output->on.output_bind.notify = handle_output_bind; - wl_signal_add(&wlr_output->events.bind, &group_output->on.output_bind); - - group_output->on.output_destroy.notify = handle_output_destroy; - wl_signal_add(&wlr_output->events.destroy, &group_output->on.output_destroy); - - wl_list_insert(&group->outputs, &group_output->link); - - group_output_send_event( - &group_output->group->resources, - &group_output->wlr_output->resources, - zcosmic_workspace_group_handle_v1_send_output_enter); - - cosmic_manager_schedule_done_event(group->manager); -} - -void -lab_cosmic_workspace_group_output_leave(struct lab_cosmic_workspace_group *group, - struct wlr_output *wlr_output) -{ - struct group_output *tmp; - struct group_output *group_output = NULL; - wl_list_for_each(tmp, &group->outputs, link) { - if (tmp->wlr_output == wlr_output) { - group_output = tmp; - break; - } - } - if (!group_output) { - wlr_log(WLR_ERROR, "output %s was never entered", wlr_output->name); - return; - } - - group_output_destroy(group_output); -} diff --git a/src/protocols/ext-workspace/ext-workspace.c b/src/protocols/ext-workspace/ext-workspace.c deleted file mode 100644 index 30875811..00000000 --- a/src/protocols/ext-workspace/ext-workspace.c +++ /dev/null @@ -1,762 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -#include -#include -#include "common/mem.h" -#include "common/list.h" -#include "ext-workspace-v1-protocol.h" -#include "protocols/ext-workspace.h" -#include "protocols/ext-workspace-internal.h" -#include "protocols/transaction-addon.h" - -/* - * .--------------------. - * | TODO | - * |--------------------| - * | - go through xml | - * | and verify impl | - * | - assert pub API | - * `--------------------´ - * - */ - -/* Only used within an assert() */ -#ifndef NDEBUG - #define EXT_WORKSPACE_V1_VERSION 1 -#endif - -/* - * Set when creating a new workspace state so we - * don't end up having to send the state twice. - */ -#define WS_STATE_INVALID 0xffffffff - -struct ws_create_workspace_event { - char *name; - struct { - struct wl_listener transaction_op_destroy; - } on; -}; - -/* Workspace */ -static void -workspace_handle_destroy(struct wl_client *client, struct wl_resource *resource) -{ - wl_resource_destroy(resource); -} - -static void -workspace_handle_activate(struct wl_client *client, struct wl_resource *resource) -{ - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (!addon) { - /* Workspace was destroyed from the compositor side */ - return; - } - struct lab_ext_workspace *workspace = addon->data; - lab_transaction_op_add(addon->ctx, WS_PENDING_WS_ACTIVATE, - workspace, /*data*/ NULL); -} - -static void -workspace_handle_deactivate(struct wl_client *client, struct wl_resource *resource) -{ - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (!addon) { - /* Workspace was destroyed from the compositor side */ - return; - } - struct lab_ext_workspace *workspace = addon->data; - lab_transaction_op_add(addon->ctx, WS_PENDING_WS_DEACTIVATE, - workspace, /*data*/ NULL); -} - -static void -workspace_handle_assign(struct wl_client *client, struct wl_resource *resource, - struct wl_resource *new_group_resource) -{ - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (!addon) { - /* Workspace was destroyed from the compositor side */ - return; - } - struct lab_ext_workspace *workspace = addon->data; - struct lab_wl_resource_addon *grp_addon = - wl_resource_get_user_data(new_group_resource); - if (!grp_addon) { - /* Group was destroyed from the compositor side */ - return; - } - struct lab_ext_workspace_group *new_grp = grp_addon->data; - lab_transaction_op_add(addon->ctx, WS_PENDING_WS_ASSIGN, workspace, new_grp); -} - -static void -workspace_handle_remove(struct wl_client *client, struct wl_resource *resource) -{ - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (!addon) { - /* Workspace was destroyed from the compositor side */ - return; - } - struct lab_ext_workspace *workspace = addon->data; - lab_transaction_op_add(addon->ctx, WS_PENDING_WS_REMOVE, - workspace, /*data*/ NULL); -} - -static const struct ext_workspace_handle_v1_interface workspace_impl = { - .destroy = workspace_handle_destroy, - .activate = workspace_handle_activate, - .deactivate = workspace_handle_deactivate, - .assign = workspace_handle_assign, - .remove = workspace_handle_remove, -}; - -static void -workspace_instance_resource_destroy(struct wl_resource *resource) -{ - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (addon) { - lab_resource_addon_destroy(addon); - wl_resource_set_user_data(resource, NULL); - } - - wl_list_remove(wl_resource_get_link(resource)); -} - -static struct wl_resource * -workspace_resource_create(struct lab_ext_workspace *workspace, - struct wl_resource *manager_resource, - struct lab_transaction_session_context *ctx) -{ - struct wl_client *client = wl_resource_get_client(manager_resource); - struct wl_resource *resource = wl_resource_create(client, - &ext_workspace_handle_v1_interface, - wl_resource_get_version(manager_resource), 0); - if (!resource) { - wl_client_post_no_memory(client); - return NULL; - } - - struct lab_wl_resource_addon *addon = lab_resource_addon_create(ctx); - addon->data = workspace; - - wl_resource_set_implementation(resource, &workspace_impl, addon, - workspace_instance_resource_destroy); - - wl_list_insert(&workspace->resources, wl_resource_get_link(resource)); - return resource; -} - -/* Workspace internal helpers */ -static void -workspace_send_state(struct lab_ext_workspace *workspace, struct wl_resource *target) -{ - if (target) { - ext_workspace_handle_v1_send_state(target, workspace->state); - } else { - struct wl_resource *resource; - wl_resource_for_each(resource, &workspace->resources) { - ext_workspace_handle_v1_send_state(resource, workspace->state); - } - } -} - -static void -workspace_send_initial_state(struct lab_ext_workspace *workspace, struct wl_resource *resource) -{ - ext_workspace_handle_v1_send_capabilities(resource, workspace->capabilities); - if (workspace->coordinates.size > 0) { - ext_workspace_handle_v1_send_coordinates(resource, &workspace->coordinates); - } - if (workspace->name) { - ext_workspace_handle_v1_send_name(resource, workspace->name); - } - if (workspace->id) { - ext_workspace_handle_v1_send_id(resource, workspace->id); - } -} - -static void -workspace_set_state(struct lab_ext_workspace *workspace, - enum ext_workspace_handle_v1_state state, bool enabled) -{ - if (!!(workspace->state_pending & state) == enabled) { - return; - } - - if (enabled) { - workspace->state_pending |= state; - } else { - workspace->state_pending &= ~state; - } - ext_manager_schedule_done_event(workspace->manager); -} - -/* Group */ -static void -ws_create_workspace_handle_transaction_op_destroy(struct wl_listener *listener, void *data) -{ - struct ws_create_workspace_event *ev = - wl_container_of(listener, ev, on.transaction_op_destroy); - wl_list_remove(&ev->on.transaction_op_destroy.link); - free(ev->name); - free(ev); -} - -static void -group_handle_create_workspace(struct wl_client *client, - struct wl_resource *resource, const char *name) -{ - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (!addon) { - return; - } - - struct lab_ext_workspace_group *group = addon->data; - struct ws_create_workspace_event *ev = znew(*ev); - ev->name = xstrdup(name); - - struct lab_transaction_op *transaction_op = lab_transaction_op_add( - addon->ctx, WS_PENDING_WS_CREATE, group, ev); - - ev->on.transaction_op_destroy.notify = - ws_create_workspace_handle_transaction_op_destroy; - wl_signal_add(&transaction_op->events.destroy, &ev->on.transaction_op_destroy); -} - -static void -group_handle_destroy(struct wl_client *client, struct wl_resource *resource) -{ - wl_resource_destroy(resource); -} - -static const struct ext_workspace_group_handle_v1_interface group_impl = { - .create_workspace = group_handle_create_workspace, - .destroy = group_handle_destroy, -}; - -static void -group_instance_resource_destroy(struct wl_resource *resource) -{ - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (addon) { - lab_resource_addon_destroy(addon); - wl_resource_set_user_data(resource, NULL); - } - wl_list_remove(wl_resource_get_link(resource)); -} - -static struct wl_resource * -group_resource_create(struct lab_ext_workspace_group *group, - struct wl_resource *manager_resource, struct lab_transaction_session_context *ctx) -{ - struct wl_client *client = wl_resource_get_client(manager_resource); - struct wl_resource *resource = wl_resource_create(client, - &ext_workspace_group_handle_v1_interface, - wl_resource_get_version(manager_resource), 0); - if (!resource) { - wl_client_post_no_memory(client); - return NULL; - } - - struct lab_wl_resource_addon *addon = lab_resource_addon_create(ctx); - addon->data = group; - - wl_resource_set_implementation(resource, &group_impl, addon, - group_instance_resource_destroy); - - wl_list_insert(&group->resources, wl_resource_get_link(resource)); - return resource; -} - -/* Group internal helpers */ -static void -group_send_state(struct lab_ext_workspace_group *group, struct wl_resource *resource) -{ - ext_workspace_group_handle_v1_send_capabilities( - resource, group->capabilities); - - ext_group_output_send_initial_state(group, resource); -} - -/* Manager itself */ -static void -manager_handle_commit(struct wl_client *client, struct wl_resource *resource) -{ - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (!addon) { - return; - } - - struct lab_ext_workspace *workspace; - struct lab_ext_workspace_group *group; - struct lab_transaction_op *trans_op, *trans_op_tmp; - lab_transaction_for_each_safe(trans_op, trans_op_tmp, addon->ctx) { - switch (trans_op->change) { - case WS_PENDING_WS_CREATE: { - group = trans_op->src; - struct ws_create_workspace_event *ev = trans_op->data; - wl_signal_emit_mutable(&group->events.create_workspace, ev->name); - break; - } - case WS_PENDING_WS_ACTIVATE: - workspace = trans_op->src; - wl_signal_emit_mutable(&workspace->events.activate, NULL); - break; - case WS_PENDING_WS_DEACTIVATE: - workspace = trans_op->src; - wl_signal_emit_mutable(&workspace->events.deactivate, NULL); - break; - case WS_PENDING_WS_REMOVE: - workspace = trans_op->src; - wl_signal_emit_mutable(&workspace->events.remove, NULL); - break; - case WS_PENDING_WS_ASSIGN: - workspace = trans_op->src; - wl_signal_emit_mutable(&workspace->events.assign, trans_op->data); - break; - default: - wlr_log(WLR_ERROR, "Invalid transaction state: %u", trans_op->change); - } - - lab_transaction_op_destroy(trans_op); - } -} - -static void -manager_handle_stop(struct wl_client *client, struct wl_resource *resource) -{ - ext_workspace_manager_v1_send_finished(resource); - wl_resource_destroy(resource); -} - -static const struct ext_workspace_manager_v1_interface manager_impl = { - .commit = manager_handle_commit, - .stop = manager_handle_stop, -}; - -static void -manager_instance_resource_destroy(struct wl_resource *resource) -{ - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - if (addon) { - lab_resource_addon_destroy(addon); - wl_resource_set_user_data(resource, NULL); - } - wl_list_remove(wl_resource_get_link(resource)); -} - -static void -manager_handle_bind(struct wl_client *client, void *data, - uint32_t version, uint32_t id) -{ - struct lab_ext_workspace_manager *manager = data; - struct wl_resource *manager_resource = wl_resource_create(client, - &ext_workspace_manager_v1_interface, - version, id); - if (!manager_resource) { - wl_client_post_no_memory(client); - return; - } - - struct lab_wl_resource_addon *addon = - lab_resource_addon_create(/* session context*/ NULL); - addon->data = manager; - - wl_resource_set_implementation(manager_resource, &manager_impl, - addon, manager_instance_resource_destroy); - - wl_list_insert(&manager->resources, wl_resource_get_link(manager_resource)); - - struct lab_ext_workspace *workspace; - struct lab_ext_workspace_group *group; - wl_list_for_each(group, &manager->groups, link) { - /* Create group resource */ - struct wl_resource *group_resource = - group_resource_create(group, manager_resource, addon->ctx); - ext_workspace_manager_v1_send_workspace_group(manager_resource, group_resource); - group_send_state(group, group_resource); - wl_list_for_each(workspace, &manager->workspaces, link) { - if (workspace->group != group) { - continue; - } - /* Create workspace resource for the current group */ - struct wl_resource *workspace_resource = workspace_resource_create( - workspace, manager_resource, addon->ctx); - ext_workspace_manager_v1_send_workspace( - manager_resource, workspace_resource); - workspace_send_initial_state(workspace, workspace_resource); - workspace_send_state(workspace, workspace_resource); - ext_workspace_group_handle_v1_send_workspace_enter( - group_resource, workspace_resource); - } - } - - /* Create workspace resource for workspaces not belonging to any group */ - wl_list_for_each(workspace, &manager->workspaces, link) { - if (workspace->group) { - continue; - } - struct wl_resource *workspace_resource = - workspace_resource_create(workspace, manager_resource, addon->ctx); - ext_workspace_manager_v1_send_workspace(manager_resource, workspace_resource); - workspace_send_initial_state(workspace, workspace_resource); - workspace_send_state(workspace, workspace_resource); - } - ext_workspace_manager_v1_send_done(manager_resource); -} - -static void -manager_handle_display_destroy(struct wl_listener *listener, void *data) -{ - struct lab_ext_workspace_manager *manager = - wl_container_of(listener, manager, on.display_destroy); - - struct lab_ext_workspace_group *group, *tmp; - wl_list_for_each_safe(group, tmp, &manager->groups, link) { - lab_ext_workspace_group_destroy(group); - } - - struct lab_ext_workspace *ws, *ws_tmp; - wl_list_for_each_safe(ws, ws_tmp, &manager->workspaces, link) { - lab_ext_workspace_destroy(ws); - } - - if (manager->idle_source) { - wl_event_source_remove(manager->idle_source); - } - - wl_list_remove(&manager->on.display_destroy.link); - wl_global_destroy(manager->global); - free(manager); -} - -/* Manager internal helpers */ -static void -manager_idle_send_done(void *data) -{ - struct lab_ext_workspace_manager *manager = data; - - struct lab_ext_workspace *workspace; - wl_list_for_each(workspace, &manager->workspaces, link) { - if (workspace->state != workspace->state_pending) { - workspace->state = workspace->state_pending; - workspace_send_state(workspace, /*target*/ NULL); - } - } - - struct wl_resource *resource; - wl_resource_for_each(resource, &manager->resources) { - ext_workspace_manager_v1_send_done(resource); - } - manager->idle_source = NULL; -} - -/* Internal API */ -void -ext_manager_schedule_done_event(struct lab_ext_workspace_manager *manager) -{ - if (manager->idle_source) { - return; - } - if (!manager->event_loop) { - return; - } - manager->idle_source = wl_event_loop_add_idle( - manager->event_loop, manager_idle_send_done, manager); -} - -static void -send_group_workspace_event(struct lab_ext_workspace_group *group, - struct lab_ext_workspace *workspace, - void (*fn)(struct wl_resource *grp_res, struct wl_resource *ws_res)) -{ - struct lab_wl_resource_addon *workspace_addon, *group_addon; - struct wl_resource *workspace_resource, *group_resource; - wl_resource_for_each(workspace_resource, &workspace->resources) { - workspace_addon = wl_resource_get_user_data(workspace_resource); - wl_resource_for_each(group_resource, &group->resources) { - group_addon = wl_resource_get_user_data(group_resource); - if (group_addon->ctx != workspace_addon->ctx) { - continue; - } - fn(group_resource, workspace_resource); - break; - } - } -} - -/* Public API */ -struct lab_ext_workspace_manager * -lab_ext_workspace_manager_create(struct wl_display *display, uint32_t caps, uint32_t version) -{ - assert(display); - assert(version <= EXT_WORKSPACE_V1_VERSION); - - struct lab_ext_workspace_manager *manager = znew(*manager); - manager->global = wl_global_create(display, - &ext_workspace_manager_v1_interface, - version, manager, manager_handle_bind); - - if (!manager->global) { - free(manager); - return NULL; - } - - manager->caps = caps; - manager->event_loop = wl_display_get_event_loop(display); - - manager->on.display_destroy.notify = manager_handle_display_destroy; - wl_display_add_destroy_listener(display, &manager->on.display_destroy); - - wl_list_init(&manager->groups); - wl_list_init(&manager->workspaces); - wl_list_init(&manager->resources); - return manager; -} - -struct lab_ext_workspace_group * -lab_ext_workspace_group_create(struct lab_ext_workspace_manager *manager) -{ - assert(manager); - - struct lab_ext_workspace_group *group = znew(*group); - group->manager = manager; - group->capabilities = manager->caps & WS_CAP_GRP_ALL; - - wl_list_init(&group->outputs); - wl_list_init(&group->resources); - wl_signal_init(&group->events.create_workspace); - wl_signal_init(&group->events.destroy); - - wl_list_append(&manager->groups, &group->link); - - struct wl_resource *resource, *tmp; - wl_resource_for_each_safe(resource, tmp, &manager->resources) { - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - assert(addon && addon->ctx); - struct wl_resource *group_resource = - group_resource_create(group, resource, addon->ctx); - ext_workspace_manager_v1_send_workspace_group(resource, group_resource); - group_send_state(group, group_resource); - } - ext_manager_schedule_done_event(manager); - - return group; -} - -void -lab_ext_workspace_group_destroy(struct lab_ext_workspace_group *group) -{ - assert(group); - wl_signal_emit_mutable(&group->events.destroy, NULL); - - struct lab_ext_workspace *workspace; - wl_list_for_each(workspace, &group->manager->workspaces, link) { - if (workspace->group == group) { - send_group_workspace_event(group, workspace, - ext_workspace_group_handle_v1_send_workspace_leave); - workspace->group = NULL; - } - } - - struct wl_resource *resource, *res_tmp; - wl_resource_for_each_safe(resource, res_tmp, &group->resources) { - ext_workspace_group_handle_v1_send_removed(resource); - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - lab_resource_addon_destroy(addon); - wl_resource_set_user_data(resource, NULL); - wl_list_remove(wl_resource_get_link(resource)); - wl_list_init(wl_resource_get_link(resource)); - } - - /* Cancel pending transaction ops involving this group */ - struct lab_transaction_op *trans_op, *trans_op_tmp; - wl_resource_for_each(resource, &group->manager->resources) { - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - lab_transaction_for_each_safe(trans_op, trans_op_tmp, addon->ctx) { - if (trans_op->src == group || trans_op->data == group) { - lab_transaction_op_destroy(trans_op); - } - } - } - - ext_manager_schedule_done_event(group->manager); - - wl_list_remove(&group->link); - free(group); -} - -struct lab_ext_workspace * -lab_ext_workspace_create(struct lab_ext_workspace_manager *manager, const char *id) -{ - assert(manager); - - struct lab_ext_workspace *workspace = znew(*workspace); - /* - * Ensures we are sending workspace->state_pending on the done event, - * regardless if the compositor has changed any state in between here - * and the scheduled done event or not. - * - * Without this we might have to send the state twice, first here and - * then again in the scheduled done event when there were any changes. - */ - workspace->state = WS_STATE_INVALID; - workspace->capabilities = (manager->caps & WS_CAP_WS_ALL) >> 16; - workspace->manager = manager; - if (id) { - workspace->id = xstrdup(id); - } - - wl_list_init(&workspace->resources); - wl_array_init(&workspace->coordinates); - wl_signal_init(&workspace->events.activate); - wl_signal_init(&workspace->events.deactivate); - wl_signal_init(&workspace->events.remove); - wl_signal_init(&workspace->events.assign); - wl_signal_init(&workspace->events.destroy); - - wl_list_append(&manager->workspaces, &workspace->link); - - /* Notify clients */ - struct lab_wl_resource_addon *manager_addon; - struct wl_resource *manager_resource, *workspace_resource; - wl_resource_for_each(manager_resource, &manager->resources) { - manager_addon = wl_resource_get_user_data(manager_resource); - workspace_resource = workspace_resource_create( - workspace, manager_resource, manager_addon->ctx); - ext_workspace_manager_v1_send_workspace( - manager_resource, workspace_resource); - workspace_send_initial_state(workspace, workspace_resource); - } - - ext_manager_schedule_done_event(manager); - - return workspace; -} - -void -lab_ext_workspace_assign_to_group(struct lab_ext_workspace *workspace, - struct lab_ext_workspace_group *group) -{ - assert(workspace); - - if (workspace->group == group) { - return; - } - - if (workspace->group) { - /* Send leave event for the old group */ - send_group_workspace_event(workspace->group, workspace, - ext_workspace_group_handle_v1_send_workspace_leave); - ext_manager_schedule_done_event(workspace->manager); - } - workspace->group = group; - - if (!group) { - return; - } - - /* Send enter event for the new group */ - send_group_workspace_event(group, workspace, - ext_workspace_group_handle_v1_send_workspace_enter); - ext_manager_schedule_done_event(workspace->manager); -} - -void -lab_ext_workspace_set_name(struct lab_ext_workspace *workspace, const char *name) -{ - assert(workspace); - assert(name); - - if (!workspace->name || strcmp(workspace->name, name)) { - free(workspace->name); - workspace->name = xstrdup(name); - struct wl_resource *resource; - wl_resource_for_each(resource, &workspace->resources) { - ext_workspace_handle_v1_send_name(resource, workspace->name); - } - } - ext_manager_schedule_done_event(workspace->manager); -} - -void -lab_ext_workspace_set_active(struct lab_ext_workspace *workspace, bool enabled) -{ - assert(workspace); - workspace_set_state(workspace, EXT_WORKSPACE_HANDLE_V1_STATE_ACTIVE, enabled); -} - -void -lab_ext_workspace_set_urgent(struct lab_ext_workspace *workspace, bool enabled) -{ - assert(workspace); - workspace_set_state(workspace, EXT_WORKSPACE_HANDLE_V1_STATE_URGENT, enabled); -} - -void -lab_ext_workspace_set_hidden(struct lab_ext_workspace *workspace, bool enabled) -{ - assert(workspace); - workspace_set_state(workspace, EXT_WORKSPACE_HANDLE_V1_STATE_HIDDEN, enabled); -} - -void -lab_ext_workspace_set_coordinates(struct lab_ext_workspace *workspace, - struct wl_array *coordinates) -{ - assert(workspace); - assert(coordinates); - - wl_array_release(&workspace->coordinates); - wl_array_init(&workspace->coordinates); - wl_array_copy(&workspace->coordinates, coordinates); - - struct wl_resource *resource; - wl_resource_for_each(resource, &workspace->resources) { - ext_workspace_handle_v1_send_coordinates(resource, &workspace->coordinates); - } - ext_manager_schedule_done_event(workspace->manager); -} - -void -lab_ext_workspace_destroy(struct lab_ext_workspace *workspace) -{ - assert(workspace); - - wl_signal_emit_mutable(&workspace->events.destroy, NULL); - - if (workspace->group) { - send_group_workspace_event(workspace->group, workspace, - ext_workspace_group_handle_v1_send_workspace_leave); - } - - struct wl_resource *ws_res, *ws_tmp; - wl_resource_for_each_safe(ws_res, ws_tmp, &workspace->resources) { - ext_workspace_handle_v1_send_removed(ws_res); - struct lab_wl_resource_addon *ws_addon = wl_resource_get_user_data(ws_res); - lab_resource_addon_destroy(ws_addon); - wl_resource_set_user_data(ws_res, NULL); - wl_list_remove(wl_resource_get_link(ws_res)); - wl_list_init(wl_resource_get_link(ws_res)); - } - ext_manager_schedule_done_event(workspace->manager); - - /* Cancel pending transaction ops involving this workspace */ - struct wl_resource *resource; - struct lab_transaction_op *trans_op, *trans_op_tmp; - wl_resource_for_each(resource, &workspace->manager->resources) { - struct lab_wl_resource_addon *addon = wl_resource_get_user_data(resource); - lab_transaction_for_each_safe(trans_op, trans_op_tmp, addon->ctx) { - if (trans_op->src == workspace) { - lab_transaction_op_destroy(trans_op); - } - } - } - - wl_list_remove(&workspace->link); - wl_array_release(&workspace->coordinates); - zfree(workspace->id); - zfree(workspace->name); - free(workspace); -} diff --git a/src/protocols/ext-workspace/meson.build b/src/protocols/ext-workspace/meson.build deleted file mode 100644 index e781d13a..00000000 --- a/src/protocols/ext-workspace/meson.build +++ /dev/null @@ -1,4 +0,0 @@ -labwc_sources += files( - 'ext-workspace.c', - 'output.c', -) diff --git a/src/protocols/ext-workspace/output.c b/src/protocols/ext-workspace/output.c deleted file mode 100644 index 0d6a2a44..00000000 --- a/src/protocols/ext-workspace/output.c +++ /dev/null @@ -1,174 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -#include -#include -#include -#include "common/mem.h" -#include "ext-workspace-v1-protocol.h" -#include "protocols/ext-workspace.h" -#include "protocols/ext-workspace-internal.h" - -struct group_output { - struct wlr_output *wlr_output; - struct lab_ext_workspace_group *group; - struct { - struct wl_listener group_destroy; - struct wl_listener output_bind; - struct wl_listener output_destroy; - } on; - - struct wl_list link; -}; - -/* Internal helpers */ -static void -group_output_send_event(struct wl_list *group_resources, struct wl_list *output_resources, - void (*notifier)(struct wl_resource *group, struct wl_resource *output)) -{ - struct wl_client *client; - struct wl_resource *group_resource, *output_resource; - wl_resource_for_each(group_resource, group_resources) { - client = wl_resource_get_client(group_resource); - wl_resource_for_each(output_resource, output_resources) { - if (wl_resource_get_client(output_resource) == client) { - notifier(group_resource, output_resource); - } - } - } -} - -static void -group_output_destroy(struct group_output *group_output) -{ - group_output_send_event( - &group_output->group->resources, - &group_output->wlr_output->resources, - ext_workspace_group_handle_v1_send_output_leave); - - ext_manager_schedule_done_event(group_output->group->manager); - - wl_list_remove(&group_output->link); - wl_list_remove(&group_output->on.group_destroy.link); - wl_list_remove(&group_output->on.output_bind.link); - wl_list_remove(&group_output->on.output_destroy.link); - free(group_output); -} - -/* Event handlers */ -static void -handle_output_bind(struct wl_listener *listener, void *data) -{ - struct group_output *group_output = - wl_container_of(listener, group_output, on.output_bind); - - struct wlr_output_event_bind *event = data; - struct wl_client *client = wl_resource_get_client(event->resource); - - bool sent = false; - struct wl_resource *group_resource; - wl_resource_for_each(group_resource, &group_output->group->resources) { - if (wl_resource_get_client(group_resource) == client) { - ext_workspace_group_handle_v1_send_output_enter( - group_resource, event->resource); - sent = true; - } - } - if (!sent) { - return; - } - - struct wl_resource *manager_resource; - struct wl_list *manager_resources = &group_output->group->manager->resources; - wl_resource_for_each(manager_resource, manager_resources) { - if (wl_resource_get_client(manager_resource) == client) { - ext_workspace_manager_v1_send_done(manager_resource); - } - } -} - -static void -handle_output_destroy(struct wl_listener *listener, void *data) -{ - struct group_output *group_output = - wl_container_of(listener, group_output, on.output_destroy); - group_output_destroy(group_output); -} - -static void -handle_group_destroy(struct wl_listener *listener, void *data) -{ - struct group_output *group_output = - wl_container_of(listener, group_output, on.group_destroy); - group_output_destroy(group_output); -} - -/* Internal API*/ -void -ext_group_output_send_initial_state(struct lab_ext_workspace_group *group, - struct wl_resource *group_resource) -{ - struct group_output *group_output; - struct wl_resource *output_resource; - struct wl_client *client = wl_resource_get_client(group_resource); - wl_list_for_each(group_output, &group->outputs, link) { - wl_resource_for_each(output_resource, &group_output->wlr_output->resources) { - if (wl_resource_get_client(output_resource) == client) { - ext_workspace_group_handle_v1_send_output_enter( - group_resource, output_resource); - } - } - } -} - -/* Public API */ -void -lab_ext_workspace_group_output_enter(struct lab_ext_workspace_group *group, - struct wlr_output *wlr_output) -{ - struct group_output *group_output; - wl_list_for_each(group_output, &group->outputs, link) { - if (group_output->wlr_output == wlr_output) { - return; - } - } - group_output = znew(*group_output); - group_output->wlr_output = wlr_output; - group_output->group = group; - - group_output->on.group_destroy.notify = handle_group_destroy; - wl_signal_add(&group->events.destroy, &group_output->on.group_destroy); - - group_output->on.output_bind.notify = handle_output_bind; - wl_signal_add(&wlr_output->events.bind, &group_output->on.output_bind); - - group_output->on.output_destroy.notify = handle_output_destroy; - wl_signal_add(&wlr_output->events.destroy, &group_output->on.output_destroy); - - wl_list_insert(&group->outputs, &group_output->link); - - group_output_send_event( - &group_output->group->resources, - &group_output->wlr_output->resources, - ext_workspace_group_handle_v1_send_output_enter); - - ext_manager_schedule_done_event(group->manager); -} - -void -lab_ext_workspace_group_output_leave(struct lab_ext_workspace_group *group, - struct wlr_output *wlr_output) -{ - struct group_output *tmp; - struct group_output *group_output = NULL; - wl_list_for_each(tmp, &group->outputs, link) { - if (tmp->wlr_output == wlr_output) { - group_output = tmp; - break; - } - } - if (!group_output) { - wlr_log(WLR_ERROR, "output %s was never entered", wlr_output->name); - return; - } - - group_output_destroy(group_output); -} diff --git a/src/protocols/meson.build b/src/protocols/meson.build deleted file mode 100644 index d9d17bf5..00000000 --- a/src/protocols/meson.build +++ /dev/null @@ -1,6 +0,0 @@ -labwc_sources += files( - 'transaction-addon.c', -) - -subdir('cosmic_workspaces') -subdir('ext-workspace') diff --git a/src/protocols/transaction-addon.c b/src/protocols/transaction-addon.c deleted file mode 100644 index 808a2096..00000000 --- a/src/protocols/transaction-addon.c +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -#include "protocols/transaction-addon.h" -#include -#include -#include "common/list.h" -#include "common/mem.h" - -void -lab_transaction_op_destroy(struct lab_transaction_op *trans_op) -{ - wl_signal_emit_mutable(&trans_op->events.destroy, trans_op); - wl_list_remove(&trans_op->link); - free(trans_op); -} - -static void -transaction_destroy(struct wl_list *list) -{ - struct lab_transaction_op *trans_op, *trans_op_tmp; - wl_list_for_each_safe(trans_op, trans_op_tmp, list, link) { - lab_transaction_op_destroy(trans_op); - } -} - -void -lab_resource_addon_destroy(struct lab_wl_resource_addon *addon) -{ - assert(addon); - assert(addon->ctx); - - addon->ctx->ref_count--; - assert(addon->ctx->ref_count >= 0); - - if (!addon->ctx->ref_count) { - transaction_destroy(&addon->ctx->transaction_ops); - free(addon->ctx); - } - - free(addon); -} - -struct lab_wl_resource_addon * -lab_resource_addon_create(struct lab_transaction_session_context *ctx) -{ - struct lab_wl_resource_addon *addon = znew(*addon); - if (!ctx) { - ctx = znew(*ctx); - wl_list_init(&ctx->transaction_ops); - } - addon->ctx = ctx; - addon->ctx->ref_count++; - return addon; -} - -struct lab_transaction_op * -lab_transaction_op_add(struct lab_transaction_session_context *ctx, - uint32_t pending_change, void *src, void *data) -{ - assert(ctx); - - struct lab_transaction_op *trans_op = znew(*trans_op); - trans_op->change = pending_change; - trans_op->src = src; - trans_op->data = data; - - wl_signal_init(&trans_op->events.destroy); - wl_list_append(&ctx->transaction_ops, &trans_op->link); - - return trans_op; -} diff --git a/src/server.c b/src/server.c index 76a69fa0..14a05c13 100644 --- a/src/server.c +++ b/src/server.c @@ -223,7 +223,6 @@ protocol_is_privileged(const struct wl_interface *iface) "zwlr_data_control_manager_v1", "wp_security_context_manager_v1", "ext_idle_notifier_v1", - "zcosmic_workspace_manager_v1", "zwlr_foreign_toplevel_manager_v1", "ext_foreign_toplevel_list_v1", "ext_session_lock_manager_v1", diff --git a/src/workspaces.c b/src/workspaces.c index 7b0b8e96..fb338036 100644 --- a/src/workspaces.c +++ b/src/workspaces.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include "buffer.h" @@ -19,12 +20,9 @@ #include "input/keyboard.h" #include "labwc.h" #include "output.h" -#include "protocols/cosmic-workspaces.h" -#include "protocols/ext-workspace.h" #include "theme.h" #include "view.h" -#define COSMIC_WORKSPACES_VERSION 1 #define EXT_WORKSPACES_VERSION 1 /* Internal helpers */ @@ -211,20 +209,23 @@ workspace_find_by_name(struct server *server, const char *name) /* cosmic workspace handlers */ static void -handle_cosmic_workspace_activate(struct wl_listener *listener, void *data) +handle_ext_workspace_commit(struct wl_listener *listener, void *data) { - struct workspace *workspace = wl_container_of(listener, workspace, on_cosmic.activate); - workspaces_switch_to(workspace, /* update_focus */ true); - wlr_log(WLR_INFO, "cosmic activating workspace %s", workspace->name); -} + struct server *server = wl_container_of(listener, server, + workspaces.on_ext_manager.commit); + struct wlr_ext_workspace_v1_commit_event *event = data; -/* ext workspace handlers */ -static void -handle_ext_workspace_activate(struct wl_listener *listener, void *data) -{ - struct workspace *workspace = wl_container_of(listener, workspace, on_ext.activate); - workspaces_switch_to(workspace, /* update_focus */ true); - wlr_log(WLR_INFO, "ext activating workspace %s", workspace->name); + struct wlr_ext_workspace_v1_request *req; + wl_list_for_each(req, event->requests, link) { + if (req->type == WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE) { + struct wlr_ext_workspace_v1_request_activate *activate_req = + (struct wlr_ext_workspace_v1_request_activate *)req; + struct workspace *workspace = activate_req->workspace->data; + + workspaces_switch_to(workspace, /* update_focus */ true); + wlr_log(WLR_INFO, "ext activating workspace %s", workspace->name); + } + } } /* Internal API */ @@ -238,23 +239,13 @@ add_workspace(struct server *server, const char *name) wl_list_append(&server->workspaces.all, &workspace->link); 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); - - workspace->on_cosmic.activate.notify = handle_cosmic_workspace_activate; - wl_signal_add(&workspace->cosmic_workspace->events.activate, - &workspace->on_cosmic.activate); - - /* ext */ - workspace->ext_workspace = lab_ext_workspace_create( - 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); - - workspace->on_ext.activate.notify = handle_ext_workspace_activate; - wl_signal_add(&workspace->ext_workspace->events.activate, - &workspace->on_ext.activate); + workspace->ext_workspace = wlr_ext_workspace_handle_v1_create( + server->workspaces.ext_manager, /*id*/ NULL, + EXT_WORKSPACE_HANDLE_V1_WORKSPACE_CAPABILITIES_ACTIVATE); + workspace->ext_workspace->data = workspace; + wlr_ext_workspace_handle_v1_set_group( + workspace->ext_workspace, server->workspaces.ext_group); + wlr_ext_workspace_handle_v1_set_name(workspace->ext_workspace, name); } static struct workspace * @@ -397,19 +388,16 @@ _osd_show(struct server *server) void workspaces_init(struct server *server) { - server->workspaces.cosmic_manager = lab_cosmic_workspace_manager_create( - server->wl_display, /* capabilities */ CW_CAP_WS_ACTIVATE, - COSMIC_WORKSPACES_VERSION); + server->workspaces.ext_manager = wlr_ext_workspace_manager_v1_create( + server->wl_display, EXT_WORKSPACES_VERSION); - server->workspaces.ext_manager = lab_ext_workspace_manager_create( - server->wl_display, /* capabilities */ WS_CAP_WS_ACTIVATE, - EXT_WORKSPACES_VERSION); + server->workspaces.ext_group = wlr_ext_workspace_group_handle_v1_create( + server->workspaces.ext_manager, /*caps*/ 0); - server->workspaces.cosmic_group = lab_cosmic_workspace_group_create( - server->workspaces.cosmic_manager); - - server->workspaces.ext_group = lab_ext_workspace_group_create( - server->workspaces.ext_manager); + server->workspaces.on_ext_manager.commit.notify = + handle_ext_workspace_commit; + wl_signal_add(&server->workspaces.ext_manager->events.commit, + &server->workspaces.on_ext_manager.commit); wl_list_init(&server->workspaces.all); @@ -436,8 +424,7 @@ workspaces_init(struct server *server) 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); + wlr_ext_workspace_handle_v1_set_active(initial->ext_workspace, true); } /* @@ -458,9 +445,7 @@ workspaces_switch_to(struct workspace *target, bool update_focus) wlr_scene_node_set_enabled( &server->workspaces.current->tree->node, false); - lab_cosmic_workspace_set_active( - server->workspaces.current->cosmic_workspace, false); - lab_ext_workspace_set_active( + wlr_ext_workspace_handle_v1_set_active( server->workspaces.current->ext_workspace, false); /* Move Omnipresent views to new workspace */ @@ -517,8 +502,7 @@ workspaces_switch_to(struct workspace *target, bool update_focus) /* Ensure that only currently visible fullscreen windows hide the top layer */ desktop_update_top_layer_visibility(server); - lab_cosmic_workspace_set_active(target->cosmic_workspace, true); - lab_ext_workspace_set_active(target->ext_workspace, true); + wlr_ext_workspace_handle_v1_set_active(target->ext_workspace, true); } void @@ -572,11 +556,8 @@ destroy_workspace(struct workspace *workspace) wlr_scene_node_destroy(&workspace->tree->node); zfree(workspace->name); wl_list_remove(&workspace->link); - wl_list_remove(&workspace->on_cosmic.activate.link); - wl_list_remove(&workspace->on_ext.activate.link); - lab_cosmic_workspace_destroy(workspace->cosmic_workspace); - lab_ext_workspace_destroy(workspace->ext_workspace); + wlr_ext_workspace_handle_v1_destroy(workspace->ext_workspace); free(workspace); } @@ -611,9 +592,7 @@ workspaces_reconfigure(struct server *server) actual_workspace->name, configured_workspace->name); free(actual_workspace->name); actual_workspace->name = xstrdup(configured_workspace->name); - lab_cosmic_workspace_set_name( - actual_workspace->cosmic_workspace, actual_workspace->name); - lab_ext_workspace_set_name( + wlr_ext_workspace_handle_v1_set_name( actual_workspace->ext_workspace, actual_workspace->name); } actual_workspace_link = actual_workspace_link->next; @@ -663,4 +642,5 @@ workspaces_destroy(struct server *server) destroy_workspace(workspace); } assert(wl_list_empty(&server->workspaces.all)); + wl_list_remove(&server->workspaces.on_ext_manager.commit.link); } From 4c1260a924df1c5abf523517684dcaf867bfa3bf Mon Sep 17 00:00:00 2001 From: tokyo4j Date: Tue, 27 Jan 2026 01:09:47 +0900 Subject: [PATCH 2/2] [fixup] update to use union --- src/workspaces.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/workspaces.c b/src/workspaces.c index fb338036..faae9582 100644 --- a/src/workspaces.c +++ b/src/workspaces.c @@ -218,9 +218,7 @@ handle_ext_workspace_commit(struct wl_listener *listener, void *data) struct wlr_ext_workspace_v1_request *req; wl_list_for_each(req, event->requests, link) { if (req->type == WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE) { - struct wlr_ext_workspace_v1_request_activate *activate_req = - (struct wlr_ext_workspace_v1_request_activate *)req; - struct workspace *workspace = activate_req->workspace->data; + struct workspace *workspace = req->activate.workspace->data; workspaces_switch_to(workspace, /* update_focus */ true); wlr_log(WLR_INFO, "ext activating workspace %s", workspace->name);