From ee57f6de958170ce09bd4c8906edf8d21de60ac6 Mon Sep 17 00:00:00 2001 From: Bruce Leidl Date: Mon, 6 May 2024 18:15:38 -0400 Subject: [PATCH] Implement 'detached' workspace context There is always at least one workspace context which is the context that is currently being used by the GNOME desktop. If no running realm is associated with this context then we consider this context to be 'detached' and store it so that the next time a context is needed to attach to a running realm, this 'detached' context will be used rather than asking mutter to create a new fresh context. --- src/shell-realm-tracker.c | 2 +- src/shell-realms.c | 55 +++++++++++++++++++++++++++++++++------ 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/shell-realm-tracker.c b/src/shell-realm-tracker.c index 5c9ffaada..25c5ac09c 100644 --- a/src/shell-realm-tracker.c +++ b/src/shell-realm-tracker.c @@ -175,7 +175,6 @@ request_realm_state_finish (GObject *object, GAsyncResult *result, gpointer data realm_state_process_elements (self, response); g_variant_unref (response); - subscribe_bus_signals (self); } static void @@ -301,6 +300,7 @@ on_realm_manager_appeared (GDBusConnection *connection, const gchar *name, const g_warning("Realm tracker already has a connection in on_realm_manager_appeared()"); } + subscribe_bus_signals (self); request_realm_state (self); } diff --git a/src/shell-realms.c b/src/shell-realms.c index de0b87558..4561fe340 100644 --- a/src/shell-realms.c +++ b/src/shell-realms.c @@ -12,6 +12,7 @@ struct _ShellRealms { GList *running_realms; ShellRealmItem *current_realm; ShellRealmsWindowFrames *frames; + MetaWorkspaceContext *detached_context; }; G_DEFINE_TYPE (ShellRealms, shell_realms, G_TYPE_OBJECT); @@ -111,7 +112,6 @@ shell_realms_realm_by_window (ShellRealms *realms, MetaWindow *window) { ShellRealmItem *realm = NULL; gchar *realm_name = realm_name_from_window_pid (realms, window); - // g_warning("shell_realms_realm_by_window() realm_name=%s", realm_name); if (realm_name && g_strcmp0 (CITADEL_REALM_TAG, realm_name)) { realm = shell_realms_realm_by_name (realms, realm_name); } @@ -249,6 +249,7 @@ shell_realms_set_current_item (ShellRealms *realms, ShellRealmItem *item) shell_realm_item_set_current_flag (item, TRUE); realms->current_realm = item; + g_object_notify (realms, "current-realm"); } /* @@ -282,13 +283,16 @@ shell_realms_add_realm_item (ShellRealms *realms, } static void -remove_workspace_context (ShellRealmItem *realm) +remove_workspace_context (ShellRealms *realms, ShellRealmItem *realm) { MetaWorkspaceContext *context = shell_realm_item_get_context (realm); if (context) { + guint id = meta_workspace_context_id (context); shell_realm_item_set_context (realm, NULL); if (!meta_workspace_context_is_current (context)) { meta_workspace_context_remove (context); + } else { + realms->detached_context = context; } } } @@ -330,6 +334,12 @@ acquire_active_workspace_context (ShellRealms *realms, ShellRealmItem *realm) return; } + if (realms->detached_context == active_context) { + shell_realm_item_set_context(realm, realms->detached_context); + realms->detached_context = NULL; + return; + } + ShellRealmItem *other_realm = find_realm_with_context (realms, active_context); if (other_realm) { @@ -365,12 +375,19 @@ acquire_workspace_context (ShellRealms *realms, ShellRealmItem *realm) return; } + if (realms->detached_context) { + guint id = meta_workspace_context_id(realms->detached_context); + shell_realm_item_set_context(realm, realms->detached_context); + realms->detached_context = NULL; + return; + } + MetaDisplay *display = shell_global_get_display(shell_global_get()); MetaWorkspaceManager *workspace_manager = meta_display_get_workspace_manager(display); MetaWorkspaceContext *context = meta_workspace_context_new(workspace_manager); + guint id = meta_workspace_context_id(context); shell_realm_item_set_context(realm, context); - } void @@ -387,6 +404,8 @@ shell_realms_process_list_realm (ShellRealms *realms, } ShellRealmItem *item = shell_realms_add_realm_item (realms, realm_name, description, namespace, status); + gboolean running = shell_realm_item_is_running(item); + gboolean current = shell_realm_item_is_current(item); shell_realms_update_running_list_for_item (realms, item); shell_realm_item_set_tagged (item, TRUE); @@ -399,7 +418,7 @@ shell_realms_process_list_realm (ShellRealms *realms, } if (!shell_realm_item_is_running (item) && shell_realm_item_get_context (item) != NULL) { - remove_workspace_context (item); + remove_workspace_context (realms, item); } } @@ -434,7 +453,7 @@ shell_realms_remove_untagged (ShellRealms *realms) ShellRealmItem *item = value; if (!shell_realm_item_is_tagged (item)) { shell_realms_remove_running_realm (realms, item); - remove_workspace_context (item); + remove_workspace_context (realms, item); g_hash_table_iter_remove (&iter); } } @@ -478,12 +497,29 @@ activate_workspace_context (ShellRealmItem *realm) void shell_realms_on_realm_current (ShellRealms *realms, const gchar *realm_name) { + if (strlen(realm_name) == 0) { + g_warning("on_realm_current(NULL)"); + if(realms->current_realm) { + shell_realm_item_set_current_flag (realms->current_realm, FALSE); + realms->current_realm = NULL; + } + return; + } + ShellRealmItem *item = shell_realms_realm_by_name (realms, realm_name); if (item && realms->current_realm != item) { shell_realms_set_current_item (realms, item); shell_realms_update_running_list_for_item (realms, item); + activate_workspace_context (item); + + // If we really did switch to another context and we have a detached context saved, then + // now it can be removed which will move any windows on the detached context to the newly switched context. + if (realms->detached_context && shell_realm_item_get_context(item) != NULL) { + meta_workspace_context_remove(realms->detached_context); + realms->detached_context = NULL; + } g_signal_emit (realms, shell_realms_signals[REALM_CONTEXT_SWITCHED], 0); } } @@ -494,7 +530,7 @@ shell_realms_on_realm_stopped (ShellRealms *realms, const gchar *realm_name) ShellRealmItem *item = shell_realms_realm_by_name (realms, realm_name); if (item) { shell_realm_item_set_running_flag (item, FALSE); - remove_workspace_context (item); + remove_workspace_context (realms, item); shell_realms_remove_running_realm (realms, item); } } @@ -505,7 +541,7 @@ shell_realms_on_realm_removed (ShellRealms *realms, const gchar *realm_name) ShellRealmItem *item = shell_realms_realm_by_name (realms, realm_name); if (item) { shell_realm_item_set_running_flag (item, FALSE); - remove_workspace_context (item); + remove_workspace_context (realms, item); shell_realms_remove_running_realm (realms, item); g_hash_table_remove (realms->realms, realm_name); @@ -545,10 +581,13 @@ shell_realms_get_default(void) static void shell_realms_init(ShellRealms *realms) { + MetaDisplay *display = shell_global_get_display(shell_global_get()); + MetaWorkspaceManager *workspace_manager = meta_display_get_workspace_manager(display); + realms->realms = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); realms->running_realms = NULL; realms->current_realm = NULL; - realms->frames = shell_realms_window_frames_new (realms); + realms->detached_context = meta_workspace_manager_active_context(workspace_manager); } static void