medit/moo/eggsmclient/eggsmclient-dbus.c
2012-08-15 18:35:27 -07:00

298 lines
8.7 KiB
C

/*
* Copyright (C) 2008 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "eggsmclient.h"
#include "eggsmclient-private.h"
#include "eggdesktopfile.h"
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <gdk/gdk.h>
#include <dbus/dbus-glib.h>
#define GSM_DBUS_NAME "org.gnome.SessionManager"
#define GSM_DBUS_PATH "/org/gnome/SessionManager"
#define GSM_DBUS_INTERFACE "org.gnome.SessionManager"
#define GSM_CLIENT_PRIVATE_DBUS_INTERFACE "org.gnome.SessionManager.ClientPrivate"
#define GSM_CLIENT_DBUS_INTERFACE "org.gnome.SessionManager.Client"
#define EGG_TYPE_SM_CLIENT_DBUS (egg_sm_client_dbus_get_type ())
#define EGG_SM_CLIENT_DBUS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SM_CLIENT_DBUS, EggSMClientDBus))
#define EGG_SM_CLIENT_DBUS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SM_CLIENT_DBUS, EggSMClientDBusClass))
#define EGG_IS_SM_CLIENT_DBUS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SM_CLIENT_DBUS))
#define EGG_IS_SM_CLIENT_DBUS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SM_CLIENT_DBUS))
#define EGG_SM_CLIENT_DBUS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SM_CLIENT_DBUS, EggSMClientDBusClass))
typedef struct _EggSMClientDBus EggSMClientDBus;
typedef struct _EggSMClientDBusClass EggSMClientDBusClass;
struct _EggSMClientDBus
{
EggSMClient parent;
DBusGConnection *conn;
DBusGProxy *sm_proxy, *client_proxy;
char *client_path;
};
struct _EggSMClientDBusClass
{
EggSMClientClass parent_class;
};
static void sm_client_dbus_startup (EggSMClient *client,
const char *client_id);
static void sm_client_dbus_will_quit (EggSMClient *client,
gboolean will_quit);
static gboolean sm_client_dbus_end_session (EggSMClient *client,
EggSMClientEndStyle style,
gboolean request_confirmation);
static void dbus_client_query_end_session (DBusGProxy *proxy,
guint flags,
gpointer smclient);
static void dbus_client_end_session (DBusGProxy *proxy,
guint flags,
gpointer smclient);
static void dbus_client_cancel_end_session (DBusGProxy *proxy,
gpointer smclient);
static void dbus_client_stop (DBusGProxy *proxy,
gpointer smclient);
G_DEFINE_TYPE (EggSMClientDBus, egg_sm_client_dbus, EGG_TYPE_SM_CLIENT)
static void
egg_sm_client_dbus_init (EggSMClientDBus *dbus)
{
;
}
static void
egg_sm_client_dbus_class_init (EggSMClientDBusClass *klass)
{
EggSMClientClass *sm_client_class = EGG_SM_CLIENT_CLASS (klass);
sm_client_class->startup = sm_client_dbus_startup;
sm_client_class->will_quit = sm_client_dbus_will_quit;
sm_client_class->end_session = sm_client_dbus_end_session;
}
EggSMClient *
egg_sm_client_dbus_new (void)
{
DBusGConnection *conn;
DBusGProxy *proxy;
EggSMClientDBus *dbus;
conn = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
if (!conn)
return NULL;
proxy = dbus_g_proxy_new_for_name (conn, GSM_DBUS_NAME, GSM_DBUS_PATH,
GSM_DBUS_INTERFACE);
if (!proxy)
{
g_object_unref (conn);
return NULL;
}
dbus = g_object_new (EGG_TYPE_SM_CLIENT_DBUS, NULL);
dbus->conn = conn;
dbus->sm_proxy = proxy;
return (EggSMClient *)dbus;
}
static void
sm_client_dbus_startup (EggSMClient *client,
const char *client_id)
{
EggSMClientDBus *dbus = (EggSMClientDBus *)client;
GError *error = NULL;
char *client_path, *ret_client_id;
DBusGProxy *client_public;
if (!dbus_g_proxy_call (dbus->sm_proxy, "RegisterClient", &error,
G_TYPE_STRING, g_get_prgname (),
G_TYPE_STRING, client_id,
G_TYPE_INVALID,
DBUS_TYPE_G_OBJECT_PATH, &client_path,
G_TYPE_INVALID))
{
g_warning ("Failed to register client: %s", error->message);
g_error_free (error);
return;
}
g_debug ("Client registered with session manager: %s", client_path);
dbus->client_proxy = dbus_g_proxy_new_for_name (dbus->conn, GSM_DBUS_NAME,
client_path,
GSM_CLIENT_PRIVATE_DBUS_INTERFACE);
dbus_g_proxy_add_signal (dbus->client_proxy, "QueryEndSession",
G_TYPE_UINT,
G_TYPE_INVALID);
dbus_g_proxy_connect_signal (dbus->client_proxy, "QueryEndSession",
G_CALLBACK (dbus_client_query_end_session),
dbus, NULL);
dbus_g_proxy_add_signal (dbus->client_proxy, "EndSession",
G_TYPE_UINT,
G_TYPE_INVALID);
dbus_g_proxy_connect_signal (dbus->client_proxy, "EndSession",
G_CALLBACK (dbus_client_end_session),
dbus, NULL);
dbus_g_proxy_add_signal (dbus->client_proxy, "CancelEndSession",
G_TYPE_INVALID);
dbus_g_proxy_connect_signal (dbus->client_proxy, "CancelEndSession",
G_CALLBACK (dbus_client_cancel_end_session),
dbus, NULL);
dbus_g_proxy_add_signal (dbus->client_proxy, "Stop",
G_TYPE_INVALID);
dbus_g_proxy_connect_signal (dbus->client_proxy, "Stop",
G_CALLBACK (dbus_client_stop),
dbus, NULL);
client_public = dbus_g_proxy_new_for_name (dbus->conn, GSM_DBUS_NAME,
client_path,
GSM_CLIENT_DBUS_INTERFACE);
if (dbus_g_proxy_call (client_public, "GetStartupId", &error,
G_TYPE_INVALID,
G_TYPE_STRING, &ret_client_id,
G_TYPE_INVALID))
{
gdk_threads_enter ();
#if !GTK_CHECK_VERSION(2,23,3) && !GTK_CHECK_VERSION(3,0,0)
gdk_set_sm_client_id (ret_client_id);
#else
gdk_x11_set_sm_client_id (ret_client_id);
#endif
gdk_threads_leave ();
g_debug ("Got client ID \"%s\"", ret_client_id);
g_free (ret_client_id);
}
else
{
g_warning ("Could not get client id: %s", error->message);
g_error_free (error);
}
g_object_unref (client_public);
}
static void
sm_client_dbus_shutdown (EggSMClient *client)
{
EggSMClientDBus *dbus = EGG_SM_CLIENT_DBUS (client);
GError *error = NULL;
if (!dbus_g_proxy_call (dbus->sm_proxy, "UnregisterClient", &error,
DBUS_TYPE_G_OBJECT_PATH, dbus->client_path,
G_TYPE_INVALID,
G_TYPE_INVALID))
{
g_warning ("Failed to unregister client: %s", error->message);
g_error_free (error);
return;
}
g_free (dbus->client_path);
dbus->client_path = NULL;
g_object_unref (dbus->client_proxy);
dbus->client_proxy = NULL;
}
static void
dbus_client_query_end_session (DBusGProxy *proxy,
guint flags,
gpointer smclient)
{
egg_sm_client_quit_requested (smclient);
}
static void
sm_client_dbus_will_quit (EggSMClient *client,
gboolean will_quit)
{
EggSMClientDBus *dbus = (EggSMClientDBus *)client;
g_return_if_fail (dbus->client_proxy != NULL);
dbus_g_proxy_call (dbus->client_proxy, "EndSessionResponse", NULL,
G_TYPE_BOOLEAN, will_quit,
G_TYPE_STRING, NULL,
G_TYPE_INVALID,
G_TYPE_INVALID);
}
static void
dbus_client_end_session (DBusGProxy *proxy,
guint flags,
gpointer smclient)
{
sm_client_dbus_will_quit (smclient, TRUE);
sm_client_dbus_shutdown (smclient);
egg_sm_client_quit (smclient);
}
static void
dbus_client_cancel_end_session (DBusGProxy *proxy,
gpointer smclient)
{
egg_sm_client_quit_cancelled (smclient);
}
static void
dbus_client_stop (DBusGProxy *proxy,
gpointer smclient)
{
sm_client_dbus_shutdown (smclient);
egg_sm_client_quit (smclient);
}
static gboolean
sm_client_dbus_end_session (EggSMClient *client,
EggSMClientEndStyle style,
gboolean request_confirmation)
{
EggSMClientDBus *dbus = (EggSMClientDBus *)client;
if (style == EGG_SM_CLIENT_END_SESSION_DEFAULT ||
style == EGG_SM_CLIENT_LOGOUT)
{
return dbus_g_proxy_call (dbus->sm_proxy, "Logout", NULL,
G_TYPE_UINT, request_confirmation ? 0 : 1,
G_TYPE_INVALID,
G_TYPE_INVALID);
}
else
{
return dbus_g_proxy_call (dbus->sm_proxy, "Shutdown", NULL,
G_TYPE_INVALID,
G_TYPE_INVALID);
}
}