Map windows to realms by calling realmsd pid lookup method

This commit is contained in:
Bruce Leidl 2022-09-19 10:13:41 -04:00
parent 3f794cbe00
commit 2f4a1ed647
13 changed files with 426 additions and 229 deletions

View File

@ -56,4 +56,3 @@ var RealmManager = class {
} }
}; };

View File

@ -17,10 +17,11 @@ function _windowAppId(window) {
function windowMenuDebugString(window) { function windowMenuDebugString(window) {
const id = _windowAppId(window); const id = _windowAppId(window);
const realm_name = windowRealmName(window); const realm_name = windowRealmName(window);
const realms = Shell.Realms.get_default();
if (!realm_name) { if (!realm_name) {
return id; return id;
} else if (window.is_on_foreign_workspace_context()) { } else if (realms.is_foreign_window(window)) {
return `${id} [${realm_name}]`; return `${id} [${realm_name}]`;
} else { } else {
return `${id} (${realm_name})`; return `${id} (${realm_name})`;

View File

@ -123,7 +123,7 @@ realm_name_from_application_id (const char *id)
} }
char * static char *
current_realm_name (gboolean name_only) current_realm_name (gboolean name_only)
{ {
gchar *link = NULL; gchar *link = NULL;
@ -399,6 +399,10 @@ shell_app_system_lookup_app (ShellAppSystem *self,
ShellApp *app; ShellApp *app;
GDesktopAppInfo *info; GDesktopAppInfo *info;
if (id == NULL) {
return NULL;
}
app = g_hash_table_lookup (priv->id_to_app, id); app = g_hash_table_lookup (priv->id_to_app, id);
if (app) if (app)
return app; return app;

View File

@ -8,16 +8,14 @@ struct _ShellRealmItem {
GObject parent; GObject parent;
char *realm_name; char *realm_name;
char *description; char *description;
char *namespace; guint64 namespace;
MetaWorkspaceContext *context; MetaWorkspaceContext *context;
guint8 status; ShellRealmItemStatus status;
gboolean tagged; gboolean tagged;
gboolean disposed;
}; };
G_DEFINE_TYPE (ShellRealmItem, shell_realm_item, G_TYPE_OBJECT); G_DEFINE_TYPE (ShellRealmItem, shell_realm_item, G_TYPE_OBJECT);
enum { enum {
PROP_0, PROP_0,
PROP_ITEM_REALM_NAME, PROP_ITEM_REALM_NAME,
@ -25,45 +23,45 @@ enum {
PROP_ITEM_NAMESPACE PROP_ITEM_NAMESPACE
}; };
#define REALM_STATUS_RUNNING 1
#define REALM_STATUS_CURRENT 2
#define REALM_STATUS_SYSTEM 4
static void static void
shell_realm_item_init(ShellRealmItem *item) shell_realm_item_init (ShellRealmItem *item)
{ {
} }
ShellRealmItem * ShellRealmItem *
shell_realm_item_new (const char *realm_name, const char *description, const char *namespace, guint8 status) shell_realm_item_new (const char *realm_name, const char *description, guint64 namespace, guint8 status)
{ {
ShellRealmItem *item = g_object_new (SHELL_TYPE_REALM_ITEM, NULL); ShellRealmItem *item = g_object_new (SHELL_TYPE_REALM_ITEM, NULL);
item->realm_name = g_strdup (realm_name); item->realm_name = g_strdup (realm_name);
item->description = g_strdup (description); item->description = g_strdup (description);
item->namespace = g_strdup (namespace); item->namespace = namespace;
item->status = status; item->status = status;
item->context = NULL; item->context = NULL;
item->tagged = FALSE; item->tagged = FALSE;
item->disposed = FALSE;
return item; return item;
} }
void /**
shell_realm_item_acquire_context (ShellRealmItem *item) * shell_realm_item_get_context:
* @item: A #ShellRealmItem instance
*
* Returns the #MetaWorkspaceContext associated with this realm if any.
*
* Returns: (transfer none) (nullable): a #MetaWorkspaceContext instance or
* %NULL if no context is associated with this realm.
*/
MetaWorkspaceContext *
shell_realm_item_get_context (ShellRealmItem *item)
{ {
if (item->context || item->disposed || shell_realm_item_is_system (item)) { return item->context;
return; }
}
if (!item->namespace || !shell_realm_item_is_running (item)) { void
g_warning ("ShellRealmItem: Cannot acquire workspace context for realm '%s' because not running or no namespace", item->realm_name); shell_realm_item_set_context (ShellRealmItem *item, MetaWorkspaceContext *context)
return; {
} item->context = context;
MetaDisplay *display = shell_global_get_display (shell_global_get());
MetaWorkspaceManager *workspace_manager = meta_display_get_workspace_manager (display);
item->context = meta_workspace_manager_context_for_namespace (workspace_manager, item->namespace);
} }
/** /**
@ -98,15 +96,12 @@ shell_realm_item_get_description (ShellRealmItem *item)
* shell_realm_item_get_namespace: * shell_realm_item_get_namespace:
* @item: A #ShellRealmItem instance * @item: A #ShellRealmItem instance
* *
* Returns: The namespace field for this realm or an empty string if no namespace is set * Returns: The namespace field for this realm or 0 if no namespace is set
*/ */
const char * guint64
shell_realm_item_get_namespace (ShellRealmItem *item) shell_realm_item_get_namespace (ShellRealmItem *item)
{ {
if (item->namespace) return item->namespace;
return item->namespace;
else
return "";
} }
/** /**
@ -119,10 +114,6 @@ shell_realm_item_get_namespace (ShellRealmItem *item)
guint guint
shell_realm_item_get_context_id (ShellRealmItem *item) shell_realm_item_get_context_id (ShellRealmItem *item)
{ {
if (shell_realm_item_is_running (item) && !item->context) {
shell_realm_item_acquire_context (item);
}
if (item->context) { if (item->context) {
return meta_workspace_context_id (item->context); return meta_workspace_context_id (item->context);
} else { } else {
@ -140,10 +131,6 @@ shell_realm_item_get_context_id (ShellRealmItem *item)
MetaWorkspace * MetaWorkspace *
shell_realm_item_get_active_workspace (ShellRealmItem *item) shell_realm_item_get_active_workspace (ShellRealmItem *item)
{ {
if (shell_realm_item_is_running (item) && !item->context) {
shell_realm_item_acquire_context (item);
}
if (item->context) { if (item->context) {
return meta_workspace_context_get_active_workspace (item->context); return meta_workspace_context_get_active_workspace (item->context);
} else { } else {
@ -151,23 +138,6 @@ shell_realm_item_get_active_workspace (ShellRealmItem *item)
} }
} }
/**
* shell_realm_item_activate_context:
* @item: A #ShellRealmItem instance for a running realm
*
* If a #MetaWorkspaceContext is associated with this realm
* set it as the active workspace context.
*/
void
shell_realm_item_activate_context (ShellRealmItem *item)
{
shell_realm_item_acquire_context (item);
if (item->context) {
meta_workspace_context_activate (item->context);
}
}
/** /**
* shell_realm_item_set_current: * shell_realm_item_set_current:
* @item: A #ShellRealmItem instance for a running realm * @item: A #ShellRealmItem instance for a running realm
@ -178,7 +148,7 @@ shell_realm_item_activate_context (ShellRealmItem *item)
*/ */
void void
shell_realm_item_set_current (ShellRealmItem *item) { shell_realm_item_set_current (ShellRealmItem *item) {
ShellRealmTracker *tracker = shell_realm_tracker_get_default(); ShellRealmTracker *tracker = shell_realm_tracker_get_default ();
if (item && item->realm_name) { if (item && item->realm_name) {
shell_realm_tracker_call_set_current (tracker, item->realm_name); shell_realm_tracker_call_set_current (tracker, item->realm_name);
} }
@ -195,8 +165,6 @@ shell_realm_item_set_current (ShellRealmItem *item) {
void void
shell_realm_item_move_window_to_context (ShellRealmItem *item, MetaWindow *window) shell_realm_item_move_window_to_context (ShellRealmItem *item, MetaWindow *window)
{ {
shell_realm_item_acquire_context (item);
if (item->context) { if (item->context) {
meta_workspace_context_move_window_to_context (item->context, window); meta_workspace_context_move_window_to_context (item->context, window);
} else { } else {
@ -204,20 +172,20 @@ shell_realm_item_move_window_to_context (ShellRealmItem *item, MetaWindow *windo
} }
} }
static gboolean gboolean
is_flag_set(guint8 status, guchar flag) shell_realm_is_flag_set(guint8 status, ShellRealmItemStatus flag)
{ {
return ((status & flag) != 0) ? TRUE : FALSE; return ((status & flag) != 0) ? TRUE : FALSE;
} }
static gboolean static gboolean
has_status_flag (ShellRealmItem *item, guchar flag) has_status_flag (ShellRealmItem *item, ShellRealmItemStatus flag)
{ {
return is_flag_set (item->status, flag); return shell_realm_is_flag_set (item->status, flag);
} }
static void static void
set_status_flag (ShellRealmItem *item, guint8 flag, gboolean value) set_status_flag (ShellRealmItem *item, ShellRealmItemStatus flag, gboolean value)
{ {
if (value) { if (value) {
item->status |= flag; item->status |= flag;
@ -235,7 +203,7 @@ set_status_flag (ShellRealmItem *item, guint8 flag, gboolean value)
gboolean gboolean
shell_realm_item_is_current (ShellRealmItem *item) shell_realm_item_is_current (ShellRealmItem *item)
{ {
return has_status_flag (item, REALM_STATUS_CURRENT); return has_status_flag (item, SHELL_REALM_ITEM_STATUS_CURRENT);
} }
/** /**
@ -247,7 +215,7 @@ shell_realm_item_is_current (ShellRealmItem *item)
gboolean gboolean
shell_realm_item_is_running (ShellRealmItem *item) shell_realm_item_is_running (ShellRealmItem *item)
{ {
return has_status_flag (item, REALM_STATUS_RUNNING); return has_status_flag (item, SHELL_REALM_ITEM_STATUS_RUNNING);
} }
/** /**
@ -259,27 +227,22 @@ shell_realm_item_is_running (ShellRealmItem *item)
gboolean gboolean
shell_realm_item_is_system (ShellRealmItem *item) shell_realm_item_is_system (ShellRealmItem *item)
{ {
return has_status_flag (item, REALM_STATUS_SYSTEM); return has_status_flag (item, SHELL_REALM_ITEM_STATUS_SYSTEM);
} }
void shell_realm_item_set_current_flag (ShellRealmItem *item, gboolean value) void shell_realm_item_set_current_flag (ShellRealmItem *item, gboolean value)
{ {
set_status_flag (item, REALM_STATUS_CURRENT, value); set_status_flag (item, SHELL_REALM_ITEM_STATUS_CURRENT, value);
} }
void shell_realm_item_set_running_flag (ShellRealmItem *item, gboolean value) void shell_realm_item_set_running_flag (ShellRealmItem *item, gboolean value)
{ {
set_status_flag (item, REALM_STATUS_RUNNING, value); set_status_flag (item, SHELL_REALM_ITEM_STATUS_RUNNING, value);
if (!value && item->context) {
meta_workspace_context_remove (item->context);
item->context = NULL;
}
} }
void shell_realm_item_update (ShellRealmItem *item, const char *realm_name, const char *namespace, guint8 status) void shell_realm_item_update (ShellRealmItem *item, const char *realm_name, guint64 namespace, guint8 status)
{ {
if (g_strcmp0 (item->realm_name, realm_name)) { if (g_strcmp0 (item->realm_name, realm_name)) {
g_message ("ShellRealmItem: Realm name changed from %s to %s", item->realm_name, realm_name); g_message ("ShellRealmItem: Realm name changed from %s to %s", item->realm_name, realm_name);
@ -287,23 +250,8 @@ void shell_realm_item_update (ShellRealmItem *item, const char *realm_name, cons
item->realm_name = g_strdup (realm_name); item->realm_name = g_strdup (realm_name);
} }
if (g_strcmp0 (item->namespace, namespace)) { item->namespace = namespace;
g_free(item->namespace); item->status = status;
item->namespace = g_strdup (namespace);
}
if (item->status != status) {
gboolean was_running = has_status_flag (item, REALM_STATUS_RUNNING);
gboolean is_running = is_flag_set (status, REALM_STATUS_RUNNING);
gboolean stopped = was_running && !is_running;
item->status = status;
if (stopped) {
meta_workspace_context_remove (item->context);
item->context = NULL;
}
}
} }
void void
@ -332,7 +280,7 @@ static void shell_realm_item_get_property (GObject *gobject,
g_value_set_string (value, shell_realm_item_get_description (item)); g_value_set_string (value, shell_realm_item_get_description (item));
break; break;
case PROP_ITEM_NAMESPACE: case PROP_ITEM_NAMESPACE:
g_value_set_string (value, shell_realm_item_get_namespace (item)); g_value_set_uint64 (value, shell_realm_item_get_namespace (item));
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
@ -347,7 +295,6 @@ static void shell_realm_item_dispose (GObject *object)
meta_workspace_context_remove (item->context); meta_workspace_context_remove (item->context);
item->context = NULL; item->context = NULL;
} }
item->disposed = TRUE;
G_OBJECT_CLASS(shell_realm_item_parent_class)->dispose (object); G_OBJECT_CLASS(shell_realm_item_parent_class)->dispose (object);
} }
@ -357,7 +304,6 @@ shell_realm_item_finalize (GObject *object)
ShellRealmItem *item = SHELL_REALM_ITEM (object); ShellRealmItem *item = SHELL_REALM_ITEM (object);
g_free (item->realm_name); g_free (item->realm_name);
g_free (item->description); g_free (item->description);
g_free (item->namespace);
G_OBJECT_CLASS(shell_realm_item_parent_class)->finalize (object); G_OBJECT_CLASS(shell_realm_item_parent_class)->finalize (object);
} }
@ -373,10 +319,10 @@ shell_realm_item_class_init (ShellRealmItemClass *klass)
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_ITEM_NAMESPACE, PROP_ITEM_NAMESPACE,
g_param_spec_string ("namespace", g_param_spec_uint64 ("namespace",
"Context Namespace", "Context Namespace",
"PID namespace of context", "PID namespace of context",
NULL, 0, UINT64_MAX, 0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_ITEM_REALM_NAME, PROP_ITEM_REALM_NAME,

View File

@ -7,26 +7,36 @@
#define SHELL_TYPE_REALM_ITEM (shell_realm_item_get_type()) #define SHELL_TYPE_REALM_ITEM (shell_realm_item_get_type())
G_DECLARE_FINAL_TYPE (ShellRealmItem, shell_realm_item, SHELL, REALM_ITEM, GObject) G_DECLARE_FINAL_TYPE (ShellRealmItem, shell_realm_item, SHELL, REALM_ITEM, GObject)
ShellRealmItem *shell_realm_item_new (const char *realm_name, const char *description, const char *namespace, guint8 status); typedef enum {
SHELL_REALM_ITEM_STATUS_RUNNING = 1 << 0,
SHELL_REALM_ITEM_STATUS_CURRENT = 1 << 1,
SHELL_REALM_ITEM_STATUS_SYSTEM = 1 << 2,
} ShellRealmItemStatus;
gboolean shell_realm_is_flag_set (guint8 status, ShellRealmItemStatus flag);
ShellRealmItem *shell_realm_item_new (const char *realm_name, const char *description, guint64 namespace, guint8 status);
const char *shell_realm_item_get_realm_name (ShellRealmItem *item); const char *shell_realm_item_get_realm_name (ShellRealmItem *item);
const char *shell_realm_item_get_description (ShellRealmItem *item); const char *shell_realm_item_get_description (ShellRealmItem *item);
const char *shell_realm_item_get_namespace (ShellRealmItem *item); guint64 shell_realm_item_get_namespace (ShellRealmItem *item);
guint shell_realm_item_get_context_id (ShellRealmItem *item); guint shell_realm_item_get_context_id (ShellRealmItem *item);
MetaWorkspaceContext *shell_realm_item_get_context (ShellRealmItem *item);
void shell_realm_item_set_context (ShellRealmItem *item, MetaWorkspaceContext *context);
MetaWorkspace *shell_realm_item_get_active_workspace (ShellRealmItem *item); MetaWorkspace *shell_realm_item_get_active_workspace (ShellRealmItem *item);
void shell_realm_item_update (ShellRealmItem *item, const char *realm_name, const char *namespace, guint8 status); void shell_realm_item_update (ShellRealmItem *item, const char *realm_name, guint64 namespace, guint8 status);
void shell_realm_item_set_current_flag (ShellRealmItem *item, gboolean value); void shell_realm_item_set_current_flag (ShellRealmItem *item, gboolean value);
void shell_realm_item_set_running_flag (ShellRealmItem *item, gboolean value); void shell_realm_item_set_running_flag (ShellRealmItem *item, gboolean value);
void shell_realm_item_activate_context (ShellRealmItem *item);
void shell_realm_item_set_current (ShellRealmItem *item); void shell_realm_item_set_current (ShellRealmItem *item);
void shell_realm_item_move_window_to_context (ShellRealmItem *item, MetaWindow *window); void shell_realm_item_move_window_to_context (ShellRealmItem *item, MetaWindow *window);
gboolean shell_realm_item_is_current(ShellRealmItem *item); gboolean shell_realm_item_is_current (ShellRealmItem *item);
gboolean shell_realm_item_is_running(ShellRealmItem *item); gboolean shell_realm_item_is_running (ShellRealmItem *item);
gboolean shell_realm_item_is_system(ShellRealmItem *item); gboolean shell_realm_item_is_system (ShellRealmItem *item);
void shell_realm_item_set_tagged (ShellRealmItem *item, gboolean is_tagged); void shell_realm_item_set_tagged (ShellRealmItem *item, gboolean is_tagged);
gboolean shell_realm_item_is_tagged (ShellRealmItem *item); gboolean shell_realm_item_is_tagged (ShellRealmItem *item);

View File

@ -7,6 +7,12 @@
#define REALMS_OBJECT_PATH "/com/subgraph/realms" #define REALMS_OBJECT_PATH "/com/subgraph/realms"
#define REALMS_MANAGER_INTERFACE "com.subgraph.realms.Manager" #define REALMS_MANAGER_INTERFACE "com.subgraph.realms.Manager"
enum {
REALM_PID_LOOKUP_UNKNOWN = 1,
REALM_PID_LOOKUP_REALM = 2,
REALM_PID_LOOKUP_CITADEL = 3,
};
struct _ShellRealmTracker { struct _ShellRealmTracker {
GObject parent; GObject parent;
GDBusConnection *dbus; GDBusConnection *dbus;
@ -43,12 +49,12 @@ on_realm_bus_signal(GDBusConnection *connection,
const gchar *realm_name = NULL; const gchar *realm_name = NULL;
const gchar *description = NULL; const gchar *description = NULL;
const gchar *namespace = NULL; guint64 namespace;
guint8 status = 0; guint8 status = 0;
if (g_str_equal (signal_name, "RealmStarted")) { if (g_str_equal (signal_name, "RealmStarted")) {
g_variant_get (parameters, "(&s&sy)", &realm_name, &namespace, &status); g_variant_get (parameters, "(&sty)", &realm_name, &namespace, &status);
shell_realms_on_realm_started (realms, realm_name, namespace, status); shell_realms_on_realm_started (realms, realm_name, namespace, status);
} else if (g_str_equal (signal_name, "RealmStopped")) { } else if (g_str_equal (signal_name, "RealmStopped")) {
@ -76,6 +82,50 @@ on_realm_bus_signal(GDBusConnection *connection,
} }
} }
static guint
bus_signal_subscribe (ShellRealmTracker *self, const gchar *signal_name)
{
g_assert(self->dbus);
return g_dbus_connection_signal_subscribe (self->dbus,
REALMS_BUS_NAME,
REALMS_MANAGER_INTERFACE,
signal_name,
REALMS_OBJECT_PATH,
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
on_realm_bus_signal,
self,
NULL);
}
static void
subscribe_bus_signals (ShellRealmTracker *self)
{
if (self->dbus) {
int idx = 0;
self->bus_signal_ids[idx++] = bus_signal_subscribe (self, "RealmStarted");
self->bus_signal_ids[idx++] = bus_signal_subscribe (self, "RealmStopped");
self->bus_signal_ids[idx++] = bus_signal_subscribe (self, "RealmCurrent");
self->bus_signal_ids[idx++] = bus_signal_subscribe (self, "RealmNew");
self->bus_signal_ids[idx++] = bus_signal_subscribe (self, "RealmRemoved");
g_assert(idx == NUM_BUS_SIGNAL_IDS);
}
}
static void
unsubscribe_signals (ShellRealmTracker *self)
{
for (int i = 0; i < NUM_BUS_SIGNAL_IDS; i++) {
if (self->bus_signal_ids[i]) {
if (self->dbus) {
g_dbus_connection_signal_unsubscribe (self->dbus, self->bus_signal_ids[i]);
}
self->bus_signal_ids[i] = 0;
}
}
}
static void static void
realm_state_process_elements (ShellRealmTracker *self, GVariant *response) realm_state_process_elements (ShellRealmTracker *self, GVariant *response)
{ {
@ -83,25 +133,26 @@ realm_state_process_elements (ShellRealmTracker *self, GVariant *response)
GVariantIter *iter = NULL; GVariantIter *iter = NULL;
const gchar *name = NULL; const gchar *name = NULL;
const gchar *description = NULL; const gchar *description = NULL;
const gchar *namespace = NULL; guint64 namespace = 0;
guchar status = 0; guchar status = 0;
ShellRealms *realms = shell_realms_get_default(); ShellRealms *realms = shell_realms_get_default ();
shell_realms_untag_all (realms); shell_realms_untag_all (realms);
g_variant_get(response, "(a(ssssy))", &iter); g_variant_get (response, "(a(sssty))", &iter);
// (name, desc, realmfs, namespace, status) // (name, desc, realmfs, namespace, status)
while (g_variant_iter_next(iter, "(&s&ss&sy)", &name, &description, NULL, &namespace, &status)) { while (g_variant_iter_next (iter, "(&s&ssty)", &name, &description, NULL, &namespace, &status)) {
shell_realms_update_realm (realms, name, description, namespace, status); shell_realms_process_list_realm (realms, name, description, namespace, status);
} }
shell_realms_remove_untagged (realms); shell_realms_remove_untagged (realms);
g_variant_iter_free(iter); shell_realms_update_contexts (realms);
g_variant_iter_free (iter);
} }
static void static void
request_realm_state_finish(GObject *object, GAsyncResult *result, gpointer data) request_realm_state_finish (GObject *object, GAsyncResult *result, gpointer data)
{ {
ShellRealmTracker *self = data; ShellRealmTracker *self = data;
@ -111,7 +162,7 @@ request_realm_state_finish(GObject *object, GAsyncResult *result, gpointer data)
if (!response) { if (!response) {
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
g_warning("MetaRealmDbus: Error calling 'List' bus method: %s", error->message); g_warning ("ShellRealmTracker: Error calling 'List' bus method: %s", error->message);
} }
g_clear_error (&error); g_clear_error (&error);
return; return;
@ -122,8 +173,9 @@ request_realm_state_finish(GObject *object, GAsyncResult *result, gpointer data)
return; return;
} }
realm_state_process_elements(self, response); realm_state_process_elements (self, response);
g_variant_unref(response); g_variant_unref (response);
subscribe_bus_signals (self);
} }
static void static void
@ -163,6 +215,26 @@ call_dbus_method (ShellRealmTracker *self, const gchar *method, GVariant *parame
user_data); user_data);
} }
static GVariant *
call_dbus_method_sync (ShellRealmTracker *self, const gchar *method, GVariant *parameters, const GVariantType *reply_type, GError **error)
{
if (!self->dbus) {
g_warning("ShellRealmTracker: call_dbus_method_sync (%s) called when no bus connection present", method);
return NULL;
}
return g_dbus_connection_call_sync (self->dbus,
REALMS_BUS_NAME,
REALMS_OBJECT_PATH,
REALMS_MANAGER_INTERFACE,
method,
parameters,
reply_type,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
error);
}
static void static void
request_realm_state(ShellRealmTracker *self) request_realm_state(ShellRealmTracker *self)
{ {
@ -175,49 +247,42 @@ shell_realm_tracker_call_set_current (ShellRealmTracker *self, const char *realm
call_dbus_method (self, "SetCurrent", g_variant_new("(s)", realm_name), set_realm_current_finish, NULL); call_dbus_method (self, "SetCurrent", g_variant_new("(s)", realm_name), set_realm_current_finish, NULL);
} }
gchar *
static void shell_realm_tracker_call_realm_from_citadel_pid (ShellRealmTracker *self, pid_t pid)
unsubscribe_signals (ShellRealmTracker *self)
{ {
for (int i = 0; i < NUM_BUS_SIGNAL_IDS; i++) { GError *error = NULL;
if (self->bus_signal_ids[i]) { GVariant *result;
if (self->dbus) {
g_dbus_connection_signal_unsubscribe(self->dbus, self->bus_signal_ids[i]); guint32 code = 0;
} gchar *realm_name = NULL;
self->bus_signal_ids[i] = 0; gchar *retval = NULL;
}
if (!self->dbus) {
return NULL;
} }
}
static guint result = call_dbus_method_sync (self, "RealmFromCitadelPid",
bus_signal_subscribe (ShellRealmTracker *self, const gchar *signal_name) g_variant_new("(u)", pid),
{ G_VARIANT_TYPE("(us)"),
g_assert(self->dbus); &error);
return g_dbus_connection_signal_subscribe(self->dbus, if (!result) {
REALMS_BUS_NAME, if (error != NULL) {
REALMS_MANAGER_INTERFACE, g_warning ("Error calling RealmCitadelFromPid(%d): %s", pid, error->message);
signal_name,
REALMS_OBJECT_PATH,
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
on_realm_bus_signal,
self,
NULL);
}
static void
subscribe_bus_signals (ShellRealmTracker *self)
{
if (self->dbus) {
int idx = 0;
self->bus_signal_ids[idx++] = bus_signal_subscribe(self, "RealmStarted");
self->bus_signal_ids[idx++] = bus_signal_subscribe(self, "RealmStopped");
self->bus_signal_ids[idx++] = bus_signal_subscribe(self, "RealmCurrent");
self->bus_signal_ids[idx++] = bus_signal_subscribe(self, "RealmNew");
self->bus_signal_ids[idx++] = bus_signal_subscribe(self, "RealmRemoved");
g_assert(idx == NUM_BUS_SIGNAL_IDS);
} }
return NULL;
}
g_variant_get (result, "(u&s)", &code, &realm_name);
// g_warning("Calling RealmFromCitadelPid(%u) -> (%d,'%s')", pid, code, realm_name);
if (code == REALM_PID_LOOKUP_REALM) {
retval = g_strdup (realm_name);
} else if (code == REALM_PID_LOOKUP_CITADEL) {
retval = g_strdup (CITADEL_REALM_TAG);
}
g_variant_unref (result);
return retval;
} }
static void static void
@ -231,8 +296,7 @@ on_realm_manager_appeared (GDBusConnection *connection, const gchar *name, const
} }
if (!self->dbus) { if (!self->dbus) {
self->dbus = g_object_ref(connection); self->dbus = g_object_ref (connection);
subscribe_bus_signals (self);
} else { } else {
g_warning("Realm tracker already has a connection in on_realm_manager_appeared()"); g_warning("Realm tracker already has a connection in on_realm_manager_appeared()");
} }
@ -240,7 +304,6 @@ on_realm_manager_appeared (GDBusConnection *connection, const gchar *name, const
request_realm_state (self); request_realm_state (self);
} }
static void static void
on_realm_manager_vanished (GDBusConnection *connection, const gchar *name, gpointer user_data) on_realm_manager_vanished (GDBusConnection *connection, const gchar *name, gpointer user_data)
{ {
@ -255,7 +318,7 @@ on_realm_manager_vanished (GDBusConnection *connection, const gchar *name, gpoin
g_clear_object (&self->dbus); g_clear_object (&self->dbus);
} }
unsubscribe_signals(self); unsubscribe_signals (self);
} }
/** /**
@ -273,7 +336,7 @@ shell_realm_tracker_get_default(void)
return instance; return instance;
} }
void shell_realm_tracker_start () void shell_realm_tracker_start (void)
{ {
ShellRealmTracker *tracker = shell_realm_tracker_get_default(); ShellRealmTracker *tracker = shell_realm_tracker_get_default();
@ -282,7 +345,7 @@ void shell_realm_tracker_start ()
return; return;
} }
tracker->realms_watch_id = g_bus_watch_name(G_BUS_TYPE_SYSTEM, tracker->realms_watch_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM,
REALMS_BUS_NAME, REALMS_BUS_NAME,
G_BUS_NAME_WATCHER_FLAGS_NONE, G_BUS_NAME_WATCHER_FLAGS_NONE,
on_realm_manager_appeared, on_realm_manager_appeared,
@ -305,6 +368,6 @@ shell_realm_tracker_destroy(ShellRealmTracker *self)
self->destroy_in_progress = TRUE; self->destroy_in_progress = TRUE;
// frees 'self' in destroy notifier // frees 'self' in destroy notifier
g_bus_unwatch_name(self->realms_watch_id); g_bus_unwatch_name (self->realms_watch_id);
} }

View File

@ -7,8 +7,10 @@
G_DECLARE_FINAL_TYPE (ShellRealmTracker, shell_realm_tracker, G_DECLARE_FINAL_TYPE (ShellRealmTracker, shell_realm_tracker,
SHELL, REALM_TRACKER, GObject) SHELL, REALM_TRACKER, GObject)
ShellRealmTracker *shell_realm_tracker_get_default(void); ShellRealmTracker *shell_realm_tracker_get_default (void);
void shell_realm_tracker_call_set_current (ShellRealmTracker *self, const char *realm_name); void shell_realm_tracker_call_set_current (ShellRealmTracker *self, const char *realm_name);
void shell_realm_tracker_start (); gchar *shell_realm_tracker_call_realm_from_citadel_pid (ShellRealmTracker *self, pid_t pid);
void shell_realm_tracker_start (void);
void shell_realm_tracker_destroy (ShellRealmTracker *self);
#endif /* __SHELL_REALM_TRACKER_H__ */ #endif /* __SHELL_REALM_TRACKER_H__ */

View File

@ -4,16 +4,18 @@
#include "shell-realms.h" #include "shell-realms.h"
#include "shell-realms-window-frames.h" #include "shell-realms-window-frames.h"
#define CITADEL_REALM_TAG "[CITADEL]"
void shell_realms_untag_all (ShellRealms *realms); void shell_realms_untag_all (ShellRealms *realms);
void shell_realms_remove_untagged (ShellRealms *realms); void shell_realms_remove_untagged (ShellRealms *realms);
void shell_realms_update_realm (ShellRealms *realms, void shell_realms_update_contexts (ShellRealms *realms);
const char *realm_name, void shell_realms_process_list_realm (ShellRealms *realms,
const char *description, const char *realm_name,
const char *namespace, const char *description,
guint8 status); guint64 namespace,
guint8 status);
void shell_realms_on_realm_started (ShellRealms *realms, const gchar *realm_name, const gchar *namespace, guint8 status); void shell_realms_on_realm_started (ShellRealms *realms, const gchar *realm_name, guint64 namespace, guint8 status);
void shell_realms_on_realm_current (ShellRealms *realms, const gchar *realm_name); void shell_realms_on_realm_current (ShellRealms *realms, const gchar *realm_name);
void shell_realms_on_realm_stopped (ShellRealms *realms, const gchar *realm_name); void shell_realms_on_realm_stopped (ShellRealms *realms, const gchar *realm_name);
void shell_realms_on_realm_removed (ShellRealms *realms, const gchar *realm_name); void shell_realms_on_realm_removed (ShellRealms *realms, const gchar *realm_name);

View File

@ -9,6 +9,7 @@
struct _ShellRealmsWindowFrames { struct _ShellRealmsWindowFrames {
GObject parent; GObject parent;
ShellRealms *realms;
GSettings *settings; GSettings *settings;
GHashTable *realm_frame_colors; GHashTable *realm_frame_colors;
GList *default_colors; GList *default_colors;
@ -24,6 +25,17 @@ enum {
static guint shell_realms_window_frames_signals [LAST_SIGNAL] = { 0 }; static guint shell_realms_window_frames_signals [LAST_SIGNAL] = { 0 };
ShellRealmsWindowFrames *
shell_realms_window_frames_new (ShellRealms *realms)
{
ShellRealmsWindowFrames *frames;
frames = g_object_new (SHELL_TYPE_REALMS_WINDOW_FRAMES, NULL);
frames->realms = realms;
return frames;
}
static void static void
shell_realms_window_frames_process_color (ShellRealmsWindowFrames *frames, const char *entry) shell_realms_window_frames_process_color (ShellRealmsWindowFrames *frames, const char *entry)
{ {
@ -32,13 +44,13 @@ shell_realms_window_frames_process_color (ShellRealmsWindowFrames *frames, const
gchar **split = g_strsplit (entry, ":", -1); gchar **split = g_strsplit (entry, ":", -1);
if (g_strv_length (split) != 2) { if (g_strv_length (split) != 2) {
g_warning("ShellRealmsWindowFrames: Unable to parse realm-frame-colors entry: %s", entry); g_warning ("ShellRealmsWindowFrames: Unable to parse realm-frame-colors entry: %s", entry);
g_strfreev (split); g_strfreev (split);
return; return;
} }
if (!gdk_rgba_parse (&rgba, split[1])) { if (!gdk_rgba_parse (&rgba, split[1])) {
g_warning("ShellRealmsWindowFrames: Failed to parse RGBA component of realm frame color entry: %s", entry); g_warning ("ShellRealmsWindowFrames: Failed to parse RGBA component of realm frame color entry: %s", entry);
} else { } else {
g_hash_table_insert (frames->realm_frame_colors, g_strdup (split[0]), gdk_rgba_copy (&rgba)); g_hash_table_insert (frames->realm_frame_colors, g_strdup (split[0]), gdk_rgba_copy (&rgba));
} }
@ -62,7 +74,7 @@ load_realm_frame_colors (ShellRealmsWindowFrames *frames)
} }
static void static void
on_realm_frame_colors_changed(GSettings *settings, const gchar *key, ShellRealmsWindowFrames *frames) on_realm_frame_colors_changed (GSettings *settings, const gchar *key, ShellRealmsWindowFrames *frames)
{ {
load_realm_frame_colors (frames); load_realm_frame_colors (frames);
g_signal_emit (frames, shell_realms_window_frames_signals[REALM_FRAME_COLORS_CHANGED], 0); g_signal_emit (frames, shell_realms_window_frames_signals[REALM_FRAME_COLORS_CHANGED], 0);
@ -78,7 +90,7 @@ load_default_colors (ShellRealmsWindowFrames *frames)
entries = g_settings_get_strv (frames->settings, FRAME_COLOR_LIST_KEY); entries = g_settings_get_strv (frames->settings, FRAME_COLOR_LIST_KEY);
n_entries = g_strv_length (entries); n_entries = g_strv_length (entries);
g_clear_list(&frames->default_colors, (GDestroyNotify) gdk_rgba_free); g_clear_list (&frames->default_colors, (GDestroyNotify) gdk_rgba_free);
for (i = 0; i < n_entries; i++) { for (i = 0; i < n_entries; i++) {
if (gdk_rgba_parse (&rgba, entries[i])) { if (gdk_rgba_parse (&rgba, entries[i])) {
@ -102,12 +114,12 @@ shell_realms_window_frames_init (ShellRealmsWindowFrames *frames)
frames->default_colors = NULL; frames->default_colors = NULL;
frames->frame_disabled_windows = NULL; frames->frame_disabled_windows = NULL;
g_signal_connect(frames->settings, g_signal_connect (frames->settings,
"changed::" FRAME_COLOR_LIST_KEY, "changed::" FRAME_COLOR_LIST_KEY,
G_CALLBACK(on_frame_color_list_changed), G_CALLBACK(on_frame_color_list_changed),
frames); frames);
g_signal_connect(frames->settings, g_signal_connect (frames->settings,
"changed::" REALM_FRAME_COLORS_KEY, "changed::" REALM_FRAME_COLORS_KEY,
G_CALLBACK(on_realm_frame_colors_changed), G_CALLBACK(on_realm_frame_colors_changed),
frames); frames);
@ -172,7 +184,7 @@ add_to_disabled_list (ShellRealmsWindowFrames *frames, guint32 window_id)
} }
static gint static gint
color_compare(gconstpointer c1, gconstpointer c2) { color_compare (gconstpointer c1, gconstpointer c2) {
return gdk_rgba_equal (c1, c2) ? 0 : 1; return gdk_rgba_equal (c1, c2) ? 0 : 1;
} }
@ -199,7 +211,7 @@ allocate_color (ShellRealmsWindowFrames *frames)
g_list_free (used_colors); g_list_free (used_colors);
// 3) Choose a random element of the default list // 3) Choose a random element of the default list
guint index = (guint) g_random_int_range(0, (gint32) n_colors); guint index = (guint) g_random_int_range (0, (gint32) n_colors);
return g_list_nth_data (frames->default_colors, index); return g_list_nth_data (frames->default_colors, index);
} }
@ -209,11 +221,11 @@ shell_realms_window_frames_store_colors (ShellRealmsWindowFrames *frames)
GHashTableIter iter; GHashTableIter iter;
gpointer key, value; gpointer key, value;
GPtrArray *entries = g_ptr_array_new_with_free_func(g_free); GPtrArray *entries = g_ptr_array_new_with_free_func (g_free);
g_hash_table_iter_init (&iter, frames->realm_frame_colors); g_hash_table_iter_init (&iter, frames->realm_frame_colors);
while (g_hash_table_iter_next(&iter, &key, &value)) { while (g_hash_table_iter_next (&iter, &key, &value)) {
gchar *name = key; gchar *name = key;
GdkRGBA *rgba = value; GdkRGBA *rgba = value;
char *rgba_str = gdk_rgba_to_string (rgba); char *rgba_str = gdk_rgba_to_string (rgba);
@ -230,10 +242,10 @@ shell_realms_window_frames_store_colors (ShellRealmsWindowFrames *frames)
} }
static const char * static const char *
shell_realms_window_frames_realm_name_for_window (ShellRealmsWindowFrames *frames, ShellRealms *realms, MetaWindow *window) shell_realms_window_frames_realm_name_for_window (ShellRealmsWindowFrames *frames, MetaWindow *window)
{ {
ShellRealmItem *realm = shell_realms_realm_by_window (realms, window); ShellRealmItem *realm = shell_realms_realm_by_window (frames->realms, window);
if (realm) { if (realm) {
return shell_realm_item_get_realm_name (realm); return shell_realm_item_get_realm_name (realm);
@ -292,7 +304,7 @@ shell_realms_window_frames_is_frame_enabled (ShellRealmsWindowFrames *frames, Me
gboolean gboolean
shell_realms_window_frames_has_frame (ShellRealmsWindowFrames *frames, MetaWindow *window) shell_realms_window_frames_has_frame (ShellRealmsWindowFrames *frames, MetaWindow *window)
{ {
return !is_ignored_window(window) && meta_window_is_on_foreign_workspace_context (window); return !is_ignored_window (window) && shell_realms_is_foreign_window (frames->realms, window);
} }
/** /**
@ -342,9 +354,11 @@ shell_realms_window_frames_color_for_window (ShellRealmsWindowFrames *frames, Me
return NULL; return NULL;
} }
ShellRealms *realms = shell_realms_get_default(); const gchar *name = shell_realms_window_frames_realm_name_for_window (frames, window);
const gchar *name = shell_realms_window_frames_realm_name_for_window (frames, realms, window); if (name == NULL) {
return NULL;
}
GdkRGBA *rgba = g_hash_table_lookup (frames->realm_frame_colors, name); GdkRGBA *rgba = g_hash_table_lookup (frames->realm_frame_colors, name);
@ -376,11 +390,9 @@ shell_realms_window_frames_label_for_window (ShellRealmsWindowFrames *frames, Me
return NULL; return NULL;
} }
ShellRealms *realms = shell_realms_get_default(); if (shell_realms_is_citadel_window (frames->realms, window)) {
if (shell_realms_is_citadel_window (realms, window)) {
return "Citadel"; return "Citadel";
} else { } else {
return shell_realms_window_frames_realm_name_for_window (frames, realms, window); return shell_realms_window_frames_realm_name_for_window (frames, window);
} }
} }

View File

@ -8,6 +8,9 @@
#define SHELL_TYPE_REALMS_WINDOW_FRAMES (shell_realms_window_frames_get_type()) #define SHELL_TYPE_REALMS_WINDOW_FRAMES (shell_realms_window_frames_get_type())
G_DECLARE_FINAL_TYPE (ShellRealmsWindowFrames, shell_realms_window_frames, SHELL, REALMS_WINDOW_FRAMES, GObject) G_DECLARE_FINAL_TYPE (ShellRealmsWindowFrames, shell_realms_window_frames, SHELL, REALMS_WINDOW_FRAMES, GObject)
typedef struct _ShellRealms ShellRealms;
ShellRealmsWindowFrames *shell_realms_window_frames_new (ShellRealms *realms);
gboolean shell_realms_window_frames_has_frame (ShellRealmsWindowFrames *frames, MetaWindow *window); gboolean shell_realms_window_frames_has_frame (ShellRealmsWindowFrames *frames, MetaWindow *window);
gboolean shell_realms_window_frames_is_frame_enabled (ShellRealmsWindowFrames *frames, MetaWindow *window); gboolean shell_realms_window_frames_is_frame_enabled (ShellRealmsWindowFrames *frames, MetaWindow *window);
void shell_realms_window_frames_set_frame_enabled (ShellRealmsWindowFrames *frames, MetaWindow *window, gboolean enabled); void shell_realms_window_frames_set_frame_enabled (ShellRealmsWindowFrames *frames, MetaWindow *window, gboolean enabled);

View File

@ -50,8 +50,12 @@ shell_realms_current_realm (ShellRealms *realms)
* if name not found * if name not found
*/ */
ShellRealmItem * ShellRealmItem *
shell_realms_realm_by_name(ShellRealms *realms, const gchar *realm_name) shell_realms_realm_by_name (ShellRealms *realms, const gchar *realm_name)
{ {
if (realm_name == NULL) {
return NULL;
}
ShellRealmItem *item = g_hash_table_lookup (realms->realms, realm_name); ShellRealmItem *item = g_hash_table_lookup (realms->realms, realm_name);
if (!item) { if (!item) {
g_warning("ShellRealms: No realm found for name '%s'", realm_name); g_warning("ShellRealms: No realm found for name '%s'", realm_name);
@ -83,6 +87,17 @@ shell_realms_realm_by_context_id (ShellRealms *realms, guint context_id)
return NULL; return NULL;
} }
static gchar *
realm_name_from_window_pid (ShellRealms *realms, MetaWindow *window)
{
ShellRealmTracker *tracker = shell_realm_tracker_get_default();
pid_t pid = meta_window_get_pid (window);
if (pid > 0) {
return shell_realm_tracker_call_realm_from_citadel_pid (tracker, pid);
}
return NULL;
}
/** /**
* shell_realms_realm_by_window: * shell_realms_realm_by_window:
* @realms: a #ShellRealms instance * @realms: a #ShellRealms instance
@ -94,19 +109,14 @@ shell_realms_realm_by_context_id (ShellRealms *realms, guint context_id)
ShellRealmItem * ShellRealmItem *
shell_realms_realm_by_window (ShellRealms *realms, MetaWindow *window) shell_realms_realm_by_window (ShellRealms *realms, MetaWindow *window)
{ {
const char *window_ns = meta_window_namespace (window); ShellRealmItem *realm = NULL;
gchar *realm_name = realm_name_from_window_pid (realms, window);
if (!window_ns) { // g_warning("shell_realms_realm_by_window() realm_name=%s", realm_name);
return NULL; if (realm_name && g_strcmp0 (CITADEL_REALM_TAG, realm_name)) {
realm = shell_realms_realm_by_name (realms, realm_name);
} }
g_free(realm_name);
for (GList *iter = realms->running_realms; iter; iter = iter->next) { return realm;
ShellRealmItem *item = iter->data;
if (g_strcmp0 (window_ns, shell_realm_item_get_namespace (item)) == 0) {
return item;
}
}
return NULL;
} }
/** /**
@ -122,13 +132,26 @@ shell_realms_realm_by_window (ShellRealms *realms, MetaWindow *window)
gboolean gboolean
shell_realms_is_citadel_window (ShellRealms *realms, MetaWindow *window) shell_realms_is_citadel_window (ShellRealms *realms, MetaWindow *window)
{ {
MetaDisplay *display = shell_global_get_display (shell_global_get()); gchar *realm_name = realm_name_from_window_pid (realms, window);
MetaWorkspaceManager *workspace_manager = meta_display_get_workspace_manager (display); gboolean is_citadel = g_strcmp0 (CITADEL_REALM_TAG, realm_name) == 0;
g_free(realm_name);
return is_citadel;
}
const char *mutter_ns = meta_workspace_manager_mutter_namespace (workspace_manager);
const char *window_ns = meta_window_namespace (window);
return g_strcmp0 (mutter_ns, window_ns) == 0; gboolean
shell_realms_is_foreign_window (ShellRealms *realms, MetaWindow *window)
{
MetaWorkspace *workspace = meta_window_get_workspace (window);
guint current_id = meta_workspace_get_context_id (workspace);
ShellRealmItem *realm_item = shell_realms_realm_by_window (realms, window);
if (current_id && realm_item) {
guint realm_id = shell_realm_item_get_context_id (realm_item);
return current_id != realm_id;
}
return FALSE;
} }
/** /**
@ -237,9 +260,11 @@ static ShellRealmItem *
shell_realms_add_realm_item (ShellRealms *realms, shell_realms_add_realm_item (ShellRealms *realms,
const char *realm_name, const char *realm_name,
const char *description, const char *description,
const char *namespace, guint64 namespace,
guint8 status) guint8 status)
{ {
g_assert (realm_name != NULL);
ShellRealmItem *item = g_hash_table_lookup (realms->realms, realm_name); ShellRealmItem *item = g_hash_table_lookup (realms->realms, realm_name);
if (item) { if (item) {
shell_realm_item_update (item, realm_name, namespace, status); shell_realm_item_update (item, realm_name, namespace, status);
@ -249,27 +274,120 @@ shell_realms_add_realm_item (ShellRealms *realms,
item = shell_realm_item_new (realm_name, description, namespace, status); item = shell_realm_item_new (realm_name, description, namespace, status);
if (shell_realm_item_is_system (item)) { if (shell_realm_item_is_system (item)) {
g_clear_object(&item); g_clear_object (&item);
return NULL; return NULL;
} }
g_hash_table_insert (realms->realms, g_strdup (realm_name), item); g_hash_table_insert (realms->realms, g_strdup (realm_name), item);
return item; return item;
} }
void static void
shell_realms_update_realm (ShellRealms *realms, remove_workspace_context (ShellRealmItem *realm)
const char *realm_name,
const char *description,
const char *namespace,
guint8 status)
{ {
ShellRealmItem *item = shell_realms_add_realm_item (realms, realm_name, description, namespace, status); MetaWorkspaceContext *context = shell_realm_item_get_context (realm);
if (context) {
shell_realm_item_set_context (realm, NULL);
if (!meta_workspace_context_is_current (context)) {
meta_workspace_context_remove (context);
}
}
}
// Ignore system realms static ShellRealmItem *
if (!item) { find_realm_with_context (ShellRealms *realms, MetaWorkspaceContext *context)
{
GHashTableIter iter;
gpointer value;
if (context == NULL) {
return NULL;
}
g_hash_table_iter_init (&iter, realms->realms);
while (g_hash_table_iter_next (&iter, NULL, &value)) {
ShellRealmItem *item = value;
if (shell_realm_item_get_context (item) == context) {
return item;
}
}
return NULL;
}
static void
acquire_active_workspace_context (ShellRealms *realms, ShellRealmItem *realm)
{
MetaDisplay *display = shell_global_get_display (shell_global_get ());
MetaWorkspaceManager *workspace_manager = meta_display_get_workspace_manager (display);
MetaWorkspaceContext *active_context = meta_workspace_manager_active_context (workspace_manager);
if (shell_realm_item_get_context (realm) == active_context) {
return; return;
} }
if (!shell_realm_item_is_current (realm)) {
g_warning ("ShellRealms: Cannot acquire active workspace context for realm that is not the current realm");
return;
}
ShellRealmItem *other_realm = find_realm_with_context (realms, active_context);
if (other_realm) {
g_warning ("Stealing active workspace context from realm-%s for realm-%s",
shell_realm_item_get_realm_name(other_realm),
shell_realm_item_get_realm_name(realm));
if (shell_realm_item_is_current (other_realm)) {
shell_realm_item_set_current_flag (other_realm, false);
}
shell_realm_item_set_context (other_realm, NULL);
if (shell_realm_item_is_running (other_realm)) {
MetaWorkspaceContext *context = meta_workspace_context_new(workspace_manager);
shell_realm_item_set_context(other_realm, context);
}
}
shell_realm_item_set_context (realm, active_context);
}
static void
acquire_workspace_context (ShellRealms *realms, ShellRealmItem *realm)
{
if (shell_realm_item_is_system (realm) || shell_realm_item_get_context (realm) != NULL) {
return;
}
if (shell_realm_item_is_current (realm)) {
acquire_active_workspace_context (realms, realm);
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);
shell_realm_item_set_context(realm, context);
}
void
shell_realms_process_list_realm (ShellRealms *realms,
const char *realm_name,
const char *description,
guint64 namespace,
guint8 status)
{
// Ignore system realms
if (shell_realm_is_flag_set (status, SHELL_REALM_ITEM_STATUS_SYSTEM)) {
return;
}
ShellRealmItem *item = shell_realms_add_realm_item (realms, realm_name, description, namespace, status);
shell_realms_update_running_list_for_item (realms, item); shell_realms_update_running_list_for_item (realms, item);
shell_realm_item_set_tagged (item, TRUE); shell_realm_item_set_tagged (item, TRUE);
@ -277,7 +395,11 @@ shell_realms_update_realm (ShellRealms *realms,
// first context requested is for the current realm. // first context requested is for the current realm.
if (shell_realm_item_is_current (item)) { if (shell_realm_item_is_current (item)) {
shell_realms_set_current_item (realms, item); shell_realms_set_current_item (realms, item);
shell_realm_item_acquire_context (item); acquire_workspace_context (realms, item);
}
if (!shell_realm_item_is_running (item) && shell_realm_item_get_context (item) != NULL) {
remove_workspace_context (item);
} }
} }
@ -312,26 +434,47 @@ shell_realms_remove_untagged (ShellRealms *realms)
ShellRealmItem *item = value; ShellRealmItem *item = value;
if (!shell_realm_item_is_tagged (item)) { if (!shell_realm_item_is_tagged (item)) {
shell_realms_remove_running_realm (realms, item); shell_realms_remove_running_realm (realms, item);
remove_workspace_context (item);
g_hash_table_iter_remove (&iter); g_hash_table_iter_remove (&iter);
} }
} }
} }
void
shell_realms_update_contexts (ShellRealms *realms) {
for (GList *iter = realms->running_realms; iter; iter = iter->next) {
ShellRealmItem *item = iter->data;
if (shell_realm_item_get_context (item) == NULL) {
acquire_workspace_context (realms, item);
}
}
}
// Signal handlers // Signal handlers
void void
shell_realms_on_realm_started (ShellRealms *realms, const gchar *realm_name, const gchar *namespace, guint8 status) shell_realms_on_realm_started (ShellRealms *realms, const gchar *realm_name, guint64 namespace, guint8 status)
{ {
ShellRealmItem *item = shell_realms_realm_by_name (realms, realm_name); ShellRealmItem *item = shell_realms_realm_by_name (realms, realm_name);
if (item) { if (item) {
shell_realm_item_update (item, realm_name, namespace, status); shell_realm_item_update (item, realm_name, namespace, status);
if (!shell_realm_item_is_system (item)) { if (!shell_realm_item_is_system (item)) {
shell_realms_update_running_list_for_item (realms, item); shell_realms_update_running_list_for_item (realms, item);
shell_realm_item_acquire_context (item); acquire_workspace_context(realms, item);
} }
} }
} }
static void
activate_workspace_context (ShellRealmItem *realm)
{
MetaWorkspaceContext *context = shell_realm_item_get_context (realm);
if (context) {
meta_workspace_context_activate (context);
}
}
void void
shell_realms_on_realm_current (ShellRealms *realms, const gchar *realm_name) shell_realms_on_realm_current (ShellRealms *realms, const gchar *realm_name)
{ {
@ -340,7 +483,7 @@ shell_realms_on_realm_current (ShellRealms *realms, const gchar *realm_name)
if (item && realms->current_realm != item) { if (item && realms->current_realm != item) {
shell_realms_set_current_item (realms, item); shell_realms_set_current_item (realms, item);
shell_realms_update_running_list_for_item (realms, item); shell_realms_update_running_list_for_item (realms, item);
shell_realm_item_activate_context (item); activate_workspace_context (item);
g_signal_emit (realms, shell_realms_signals[REALM_CONTEXT_SWITCHED], 0); g_signal_emit (realms, shell_realms_signals[REALM_CONTEXT_SWITCHED], 0);
} }
} }
@ -351,6 +494,7 @@ shell_realms_on_realm_stopped (ShellRealms *realms, const gchar *realm_name)
ShellRealmItem *item = shell_realms_realm_by_name (realms, realm_name); ShellRealmItem *item = shell_realms_realm_by_name (realms, realm_name);
if (item) { if (item) {
shell_realm_item_set_running_flag (item, FALSE); shell_realm_item_set_running_flag (item, FALSE);
remove_workspace_context (item);
shell_realms_remove_running_realm (realms, item); shell_realms_remove_running_realm (realms, item);
} }
} }
@ -360,6 +504,9 @@ shell_realms_on_realm_removed (ShellRealms *realms, const gchar *realm_name)
{ {
ShellRealmItem *item = shell_realms_realm_by_name (realms, realm_name); ShellRealmItem *item = shell_realms_realm_by_name (realms, realm_name);
if (item) { if (item) {
shell_realm_item_set_running_flag (item, FALSE);
remove_workspace_context (item);
shell_realms_remove_running_realm (realms, item); shell_realms_remove_running_realm (realms, item);
g_hash_table_remove (realms->realms, realm_name); g_hash_table_remove (realms->realms, realm_name);
} }
@ -368,10 +515,14 @@ shell_realms_on_realm_removed (ShellRealms *realms, const gchar *realm_name)
void void
shell_realms_on_realm_new (ShellRealms *realms, const gchar *realm_name, const gchar *description, guint8 status) shell_realms_on_realm_new (ShellRealms *realms, const gchar *realm_name, const gchar *description, guint8 status)
{ {
if (realm_name == NULL || shell_realm_is_flag_set (status, SHELL_REALM_ITEM_STATUS_SYSTEM)) {
return;
}
if (!g_hash_table_contains (realms->realms, realm_name)) { if (!g_hash_table_contains (realms->realms, realm_name)) {
(void) shell_realms_add_realm_item (realms, realm_name, description, NULL, status); (void) shell_realms_add_realm_item (realms, realm_name, description, 0, status);
} else { } else {
g_warning("ShellRealms: RealmNew signal received for realm '%s' but it already exists", realm_name); g_warning ("ShellRealms: RealmNew signal received for realm '%s' but it already exists", realm_name);
} }
} }
@ -397,7 +548,7 @@ shell_realms_init(ShellRealms *realms)
realms->realms = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); realms->realms = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
realms->running_realms = NULL; realms->running_realms = NULL;
realms->current_realm = NULL; realms->current_realm = NULL;
realms->frames = g_object_new (SHELL_TYPE_REALMS_WINDOW_FRAMES, NULL); realms->frames = shell_realms_window_frames_new (realms);
} }
static void static void

View File

@ -13,10 +13,11 @@ ShellRealms *shell_realms_get_default(void);
ShellRealmItem *shell_realms_current_realm (ShellRealms *realms); ShellRealmItem *shell_realms_current_realm (ShellRealms *realms);
ShellRealmItem *shell_realms_realm_by_name(ShellRealms *realms, const gchar *realm_name); ShellRealmItem *shell_realms_realm_by_name (ShellRealms *realms, const gchar *realm_name);
ShellRealmItem *shell_realms_realm_by_context_id (ShellRealms *realms, guint context_id); ShellRealmItem *shell_realms_realm_by_context_id (ShellRealms *realms, guint context_id);
ShellRealmItem *shell_realms_realm_by_window (ShellRealms *realms, MetaWindow *window); ShellRealmItem *shell_realms_realm_by_window (ShellRealms *realms, MetaWindow *window);
gboolean shell_realms_is_citadel_window (ShellRealms *realms, MetaWindow *window); gboolean shell_realms_is_citadel_window (ShellRealms *realms, MetaWindow *window);
gboolean shell_realms_is_foreign_window (ShellRealms *realms, MetaWindow *window);
ShellRealmsWindowFrames *shell_realms_window_frames (ShellRealms *realms); ShellRealmsWindowFrames *shell_realms_window_frames (ShellRealms *realms);

View File

@ -217,6 +217,9 @@ get_app_from_window_wmclass (MetaWindow *window)
/* first try a match from WM_CLASS (instance part) to StartupWMClass */ /* first try a match from WM_CLASS (instance part) to StartupWMClass */
wm_instance = meta_window_get_wm_class_instance (window); wm_instance = meta_window_get_wm_class_instance (window);
if (realm_name) {
// g_warning ("ShellWindowTracker: get_app_from_window_class(wmclass: %s, realm: %s)", wm_instance, realm_name);
}
app = shell_app_system_lookup_startup_wmclass (appsys, wm_instance, realm_name); app = shell_app_system_lookup_startup_wmclass (appsys, wm_instance, realm_name);
if (app != NULL && check_app_id_prefix (app, app_prefix)) if (app != NULL && check_app_id_prefix (app, app_prefix))
return g_object_ref (app); return g_object_ref (app);