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 index 8776bfad..55f81469 100644 --- a/include/protocols/cosmic-workspaces.h +++ b/include/protocols/cosmic-workspaces.h @@ -78,8 +78,8 @@ 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); diff --git a/src/protocols/cosmic_workspaces/cosmic-workspaces.c b/src/protocols/cosmic_workspaces/cosmic-workspaces.c index b39e2d17..41d24605 100644 --- a/src/protocols/cosmic_workspaces/cosmic-workspaces.c +++ b/src/protocols/cosmic_workspaces/cosmic-workspaces.c @@ -7,7 +7,7 @@ #include "common/list.h" #include "cosmic-workspace-unstable-v1-protocol.h" #include "protocols/cosmic-workspaces.h" -#include "protocols/cosmic-workspaces-internal.h" +#include "protocols/output-tracker.h" #include "protocols/transaction-addon.h" /* @@ -50,6 +50,16 @@ enum workspace_state { CW_WS_STATE_INVALID = 1 << 31, }; +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, +}; + struct ws_create_workspace_event { char *name; struct { @@ -57,6 +67,8 @@ struct ws_create_workspace_event { } on; }; +static void cosmic_manager_schedule_done_event(struct lab_cosmic_workspace_manager *manager); + static void add_caps(struct wl_array *caps_arr, uint32_t caps) { @@ -306,7 +318,7 @@ group_send_state(struct lab_cosmic_workspace_group *group, struct wl_resource *r zcosmic_workspace_group_handle_v1_send_capabilities( resource, &group->capabilities); - cosmic_group_output_send_initial_state(group, resource); + output_tracker_send_initial_state_to_resource(group, resource); } /* Manager itself */ @@ -461,8 +473,7 @@ manager_idle_send_done(void *data) manager->idle_source = NULL; } -/* Internal API */ -void +static void cosmic_manager_schedule_done_event(struct lab_cosmic_workspace_manager *manager) { if (manager->idle_source) { @@ -475,6 +486,31 @@ cosmic_manager_schedule_done_event(struct lab_cosmic_workspace_manager *manager) manager->event_loop, manager_idle_send_done, manager); } +/* Output tracker */ +static void +handle_output_tracker_send_done(void *object, struct wl_client *client) +{ + struct lab_cosmic_workspace_group *group = object; + if (!client) { + cosmic_manager_schedule_done_event(group->manager); + return; + } + + struct wl_resource *manager_resource; + struct wl_list *manager_resources = &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 const struct output_tracker_impl output_tracker_impl = { + .send_output_enter = zcosmic_workspace_group_handle_v1_send_output_enter, + .send_output_leave = zcosmic_workspace_group_handle_v1_send_output_leave, + .send_done = handle_output_tracker_send_done, +}; + /* Public API */ struct lab_cosmic_workspace_manager * lab_cosmic_workspace_manager_create(struct wl_display *display, uint32_t caps, uint32_t version) @@ -535,6 +571,20 @@ lab_cosmic_workspace_group_create(struct lab_cosmic_workspace_manager *manager) return group; } +void +lab_cosmic_workspace_group_output_enter(struct lab_cosmic_workspace_group *group, + struct wlr_output *wlr_output) +{ + output_tracker_enter(group, &group->resources, wlr_output, &output_tracker_impl); +} + +void +lab_cosmic_workspace_group_output_leave(struct lab_cosmic_workspace_group *group, + struct wlr_output *wlr_output) +{ + output_tracker_leave(group, wlr_output); +} + void lab_cosmic_workspace_group_destroy(struct lab_cosmic_workspace_group *group) { @@ -543,6 +593,9 @@ lab_cosmic_workspace_group_destroy(struct lab_cosmic_workspace_group *group) } wl_signal_emit_mutable(&group->events.destroy, NULL); + /* Ensure output leave events are sent and tracker resources are destroyed */ + output_tracker_destroy(group); + struct lab_cosmic_workspace *ws, *ws_tmp; wl_list_for_each_safe(ws, ws_tmp, &group->workspaces, link) { lab_cosmic_workspace_destroy(ws); diff --git a/src/protocols/cosmic_workspaces/meson.build b/src/protocols/cosmic_workspaces/meson.build index 31ce18b8..3b704f95 100644 --- a/src/protocols/cosmic_workspaces/meson.build +++ b/src/protocols/cosmic_workspaces/meson.build @@ -1,4 +1,3 @@ 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); -}