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.
This commit is contained in:
Bruce Leidl 2024-05-06 18:15:38 -04:00
parent d9ba3fbc7f
commit c5277c949a
2 changed files with 48 additions and 9 deletions

View File

@ -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);
}

View File

@ -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