mirror of
https://github.com/brl/mutter.git
synced 2024-11-27 18:40:40 -05:00
238 lines
6.7 KiB
C
238 lines
6.7 KiB
C
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
/*
|
|
* Copyright (C) 2015-2017 Red Hat Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
* 02111-1307, USA.
|
|
*
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "backends/meta-dbus-session-watcher.h"
|
|
|
|
#include <gio/gio.h>
|
|
|
|
enum
|
|
{
|
|
SESSION_SIGNAL_SESSION_CLOSED,
|
|
|
|
N_SESSION_SIGNALS
|
|
};
|
|
|
|
static guint session_signals[N_SESSION_SIGNALS];
|
|
|
|
G_DEFINE_INTERFACE (MetaDbusSession, meta_dbus_session, G_TYPE_OBJECT)
|
|
|
|
struct _MetaDbusSessionWatcher
|
|
{
|
|
GObject parent;
|
|
|
|
GHashTable *clients;
|
|
};
|
|
|
|
G_DEFINE_TYPE (MetaDbusSessionWatcher,
|
|
meta_dbus_session_watcher,
|
|
G_TYPE_OBJECT)
|
|
|
|
typedef struct _MetaDbusSessionClient
|
|
{
|
|
MetaDbusSessionWatcher *session_watcher;
|
|
MetaDbusSession *session;
|
|
char *dbus_name;
|
|
guint name_watcher_id;
|
|
GList *sessions;
|
|
} MetaDbusSessionClient;
|
|
|
|
static void
|
|
meta_dbus_session_client_vanished (MetaDbusSession *session)
|
|
{
|
|
META_DBUS_SESSION_GET_IFACE (session)->client_vanished (session);
|
|
}
|
|
|
|
static void
|
|
meta_dbus_session_client_destroy (MetaDbusSessionClient *client)
|
|
{
|
|
while (TRUE)
|
|
{
|
|
GList *l;
|
|
MetaDbusSession *session;
|
|
|
|
l = client->sessions;
|
|
if (!l)
|
|
break;
|
|
|
|
session = l->data;
|
|
|
|
/*
|
|
* This will invoke on_session_closed which removes the session from the
|
|
* list.
|
|
*/
|
|
meta_dbus_session_client_vanished (session);
|
|
}
|
|
|
|
if (client->name_watcher_id)
|
|
g_bus_unwatch_name (client->name_watcher_id);
|
|
|
|
g_free (client->dbus_name);
|
|
g_free (client);
|
|
}
|
|
|
|
static void
|
|
meta_dbus_session_watcher_destroy_client (MetaDbusSessionWatcher *session_watcher,
|
|
MetaDbusSessionClient *client)
|
|
{
|
|
g_hash_table_remove (session_watcher->clients, client->dbus_name);
|
|
}
|
|
|
|
static void
|
|
name_vanished_callback (GDBusConnection *connection,
|
|
const char *name,
|
|
gpointer user_data)
|
|
{
|
|
MetaDbusSessionClient *client = user_data;
|
|
|
|
g_warning ("D-Bus client with active sessions vanished");
|
|
|
|
client->name_watcher_id = 0;
|
|
|
|
meta_dbus_session_watcher_destroy_client (client->session_watcher, client);
|
|
}
|
|
|
|
static MetaDbusSessionClient *
|
|
meta_dbus_session_client_new (MetaDbusSessionWatcher *session_watcher,
|
|
MetaDbusSession *session,
|
|
const char *dbus_name)
|
|
{
|
|
GDBusInterfaceSkeleton *interface_skeleton =
|
|
G_DBUS_INTERFACE_SKELETON (session);
|
|
GDBusConnection *connection =
|
|
g_dbus_interface_skeleton_get_connection (interface_skeleton);
|
|
MetaDbusSessionClient *client;
|
|
|
|
client = g_new0 (MetaDbusSessionClient, 1);
|
|
client->session_watcher = session_watcher;
|
|
client->session = session;
|
|
client->dbus_name = g_strdup (dbus_name);
|
|
|
|
client->name_watcher_id =
|
|
g_bus_watch_name_on_connection (connection,
|
|
dbus_name,
|
|
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
|
NULL,
|
|
name_vanished_callback,
|
|
client,
|
|
NULL);
|
|
|
|
return client;
|
|
}
|
|
|
|
static void
|
|
on_session_closed (MetaDbusSession *session,
|
|
MetaDbusSessionClient *client)
|
|
{
|
|
client->sessions = g_list_remove (client->sessions, session);
|
|
|
|
if (!client->sessions)
|
|
meta_dbus_session_watcher_destroy_client (client->session_watcher, client);
|
|
}
|
|
|
|
static void
|
|
meta_dbus_session_client_add_session (MetaDbusSessionClient *client,
|
|
MetaDbusSession *session)
|
|
{
|
|
client->sessions = g_list_append (client->sessions, session);
|
|
|
|
g_signal_connect (session, "session-closed",
|
|
G_CALLBACK (on_session_closed),
|
|
client);
|
|
}
|
|
|
|
static MetaDbusSessionClient *
|
|
meta_dbus_session_watcher_get_client (MetaDbusSessionWatcher *session_watcher,
|
|
const char *dbus_name)
|
|
{
|
|
return g_hash_table_lookup (session_watcher->clients, dbus_name);
|
|
}
|
|
|
|
void
|
|
meta_dbus_session_watcher_watch_session (MetaDbusSessionWatcher *session_watcher,
|
|
const char *client_dbus_name,
|
|
MetaDbusSession *session)
|
|
{
|
|
MetaDbusSessionClient *client;
|
|
|
|
client = meta_dbus_session_watcher_get_client (session_watcher,
|
|
client_dbus_name);
|
|
if (!client)
|
|
{
|
|
client = meta_dbus_session_client_new (session_watcher,
|
|
session,
|
|
client_dbus_name);
|
|
g_hash_table_insert (session_watcher->clients,
|
|
g_strdup (client_dbus_name),
|
|
client);
|
|
}
|
|
|
|
meta_dbus_session_client_add_session (client, session);
|
|
}
|
|
|
|
void
|
|
meta_dbus_session_notify_closed (MetaDbusSession *session)
|
|
{
|
|
g_signal_emit (session, session_signals[SESSION_SIGNAL_SESSION_CLOSED], 0);
|
|
}
|
|
|
|
static void
|
|
meta_dbus_session_default_init (MetaDbusSessionInterface *iface)
|
|
{
|
|
session_signals[SESSION_SIGNAL_SESSION_CLOSED] =
|
|
g_signal_new ("session-closed",
|
|
G_TYPE_FROM_INTERFACE (iface),
|
|
G_SIGNAL_RUN_LAST,
|
|
0,
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 0);
|
|
}
|
|
|
|
static void
|
|
meta_dbus_session_watcher_finalize (GObject *object)
|
|
{
|
|
MetaDbusSessionWatcher *session_watcher = META_DBUS_SESSION_WATCHER (object);
|
|
|
|
g_hash_table_destroy (session_watcher->clients);
|
|
|
|
G_OBJECT_CLASS (meta_dbus_session_watcher_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
meta_dbus_session_watcher_init (MetaDbusSessionWatcher *session_watcher)
|
|
{
|
|
session_watcher->clients =
|
|
g_hash_table_new_full (g_str_hash,
|
|
g_str_equal,
|
|
g_free,
|
|
(GDestroyNotify) meta_dbus_session_client_destroy);
|
|
}
|
|
|
|
static void
|
|
meta_dbus_session_watcher_class_init (MetaDbusSessionWatcherClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
object_class->finalize = meta_dbus_session_watcher_finalize;
|
|
}
|