static DBusHandlerResult
client_dbus_filter_function (DBusConnection *connection,
                             DBusMessage    *message,
                             void           *user_data)
{
        GsmDBusClient *client = GSM_DBUS_CLIENT (user_data);
        const char    *path;

        g_return_val_if_fail (connection != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
        g_return_val_if_fail (message != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);

        path = dbus_message_get_path (message);

        g_debug ("GsmDBusClient: obj_path=%s interface=%s method=%s",
                 dbus_message_get_path (message),
                 dbus_message_get_interface (message),
                 dbus_message_get_member (message));

        if (dbus_message_is_method_call (message, SM_DBUS_CLIENT_PRIVATE_INTERFACE, "EndSessionResponse")) {
                g_assert (gsm_client_peek_id (GSM_CLIENT (client)) != NULL);

                if (path != NULL && strcmp (path, gsm_client_peek_id (GSM_CLIENT (client))) != 0) {
                        /* Different object path */
                        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
                }
                handle_end_session_response (client, message);
                return DBUS_HANDLER_RESULT_HANDLED;
        }

        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
static gboolean
dbus_client_stop (GsmClient *client,
                  GError   **error)
{
        GsmDBusClient  *dbus_client = (GsmDBusClient *) client;
        DBusMessage    *message;
        gboolean        ret;

        ret = FALSE;

        /* unicast the signal to only the registered bus name */
        message = dbus_message_new_signal (gsm_client_peek_id (client),
                                           SM_DBUS_CLIENT_PRIVATE_INTERFACE,
                                           "Stop");
        if (message == NULL) {
                goto out;
        }
        if (!dbus_message_set_destination (message, dbus_client->priv->bus_name)) {
                goto out;
        }

        if (!dbus_connection_send (dbus_client->priv->connection, message, NULL)) {
                goto out;
        }

        ret = TRUE;

 out:
        if (message != NULL) {
                dbus_message_unref (message);
        }

        return ret;
}
static GKeyFile *
dbus_client_save (GsmClient *client,
                  GError   **error)
{
        g_debug ("GsmDBusClient: saving client with id %s",
                 gsm_client_peek_id (client));

        /* FIXME: We still don't support client saving for D-Bus
         * session clients */

        return NULL;
}
static gboolean
dbus_client_end_session (GsmClient                *client,
                         GsmClientEndSessionFlag   flags,
                         GError                  **error)
{
        GsmDBusClient  *dbus_client = (GsmDBusClient *) client;
        DBusMessage    *message;
        DBusMessageIter iter;
        gboolean        ret;

        ret = FALSE;

        /* unicast the signal to only the registered bus name */
        message = dbus_message_new_signal (gsm_client_peek_id (client),
                                           SM_DBUS_CLIENT_PRIVATE_INTERFACE,
                                           "EndSession");
        if (message == NULL) {
                g_set_error (error,
                             GSM_CLIENT_ERROR,
                             GSM_CLIENT_ERROR_NOT_REGISTERED,
                             "Unable to send EndSession message");
                goto out;
        }
        if (!dbus_message_set_destination (message, dbus_client->priv->bus_name)) {
                g_set_error (error,
                             GSM_CLIENT_ERROR,
                             GSM_CLIENT_ERROR_NOT_REGISTERED,
                             "Unable to send EndSession message");
                goto out;
        }

        dbus_message_iter_init_append (message, &iter);
        dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &flags);

        if (!dbus_connection_send (dbus_client->priv->connection, message, NULL)) {
                g_set_error (error,
                             GSM_CLIENT_ERROR,
                             GSM_CLIENT_ERROR_NOT_REGISTERED,
                             "Unable to send EndSession message");
                goto out;
        }

        ret = TRUE;

 out:
        if (message != NULL) {
                dbus_message_unref (message);
        }
        return ret;
}
static gboolean
dbus_client_cancel_end_session (GsmClient *client,
                                GError   **error)
{
        GsmDBusClient  *dbus_client = (GsmDBusClient *) client;
        DBusMessage    *message;
        gboolean        ret = FALSE;

        /* unicast the signal to only the registered bus name */
        message = dbus_message_new_signal (gsm_client_peek_id (client),
                                           SM_DBUS_CLIENT_PRIVATE_INTERFACE,
                                           "CancelEndSession");
        if (message == NULL) {
                g_set_error (error,
                             GSM_CLIENT_ERROR,
                             GSM_CLIENT_ERROR_NOT_REGISTERED,
                             "Unable to send CancelEndSession message");
                goto out;
        }
        if (!dbus_message_set_destination (message, dbus_client->priv->bus_name)) {
                g_set_error (error,
                             GSM_CLIENT_ERROR,
                             GSM_CLIENT_ERROR_NOT_REGISTERED,
                             "Unable to send CancelEndSession message");
                goto out;
        }

        if (!dbus_connection_send (dbus_client->priv->connection, message, NULL)) {
                g_set_error (error,
                             GSM_CLIENT_ERROR,
                             GSM_CLIENT_ERROR_NOT_REGISTERED,
                             "Unable to send CancelEndSession message");
                goto out;
        }

        ret = TRUE;

 out:
        if (message != NULL) {
                dbus_message_unref (message);
        }

        return ret;
}
static char *
get_desktop_file_path (GsmXSMPClient *client)
{
        SmProp     *prop;
        char       *desktop_file_path = NULL;
        char      **dirs;
        const char *program_name;

        /* XSMP clients using eggsmclient defines a special property
         * pointing to their respective desktop entry file */
        prop = find_property (client, GsmDesktopFile, NULL);

        if (prop) {
                GFile *file = g_file_new_for_uri (prop->vals[0].value);
                desktop_file_path = g_file_get_path (file);
                g_object_unref (file);
                goto out;
        }

        /* If we can't get desktop file from GsmDesktopFile then we
         * try to find the desktop file from its program name */
        prop = find_property (client, SmProgram, NULL);
        program_name = prop->vals[0].value;

        dirs = gsm_util_get_autostart_dirs ();

        desktop_file_path =
                gsm_util_find_desktop_file_for_app_name (program_name,
                                                         dirs);

        g_strfreev (dirs);

out:
        g_debug ("GsmXSMPClient: desktop file for client %s is %s",
                 gsm_client_peek_id (GSM_CLIENT (client)),
                 desktop_file_path ? desktop_file_path : "(null)");

        return desktop_file_path;
}
static GKeyFile *
xsmp_save (GsmClient *client,
           GError   **error)
{
        GsmClientRestartStyle restart_style;

        GKeyFile *keyfile = NULL;
        char     *desktop_file_path = NULL;
        char     *exec_program = NULL;
        char     *exec_discard = NULL;
        char     *startup_id = NULL;
        GError   *local_error;

        g_debug ("GsmXSMPClient: saving client with id %s",
                 gsm_client_peek_id (client));

        local_error = NULL;

        restart_style = xsmp_get_restart_style_hint (client);
        if (restart_style == GSM_CLIENT_RESTART_NEVER) {
                goto out;
        }

        exec_program = xsmp_get_restart_command (client);
        if (!exec_program) {
                goto out;
        }

        desktop_file_path = get_desktop_file_path (GSM_XSMP_CLIENT (client));

        keyfile = create_client_key_file (client,
                                          desktop_file_path,
                                          &local_error);

        if (local_error) {
                goto out;
        }

        g_object_get (client,
                      "startup-id", &startup_id,
                      NULL);

        g_key_file_set_string (keyfile,
                               G_KEY_FILE_DESKTOP_GROUP,
                               GSM_AUTOSTART_APP_STARTUP_ID_KEY,
                               startup_id);

        g_key_file_set_string (keyfile,
                               G_KEY_FILE_DESKTOP_GROUP,
                               G_KEY_FILE_DESKTOP_KEY_EXEC,
                               exec_program);

        exec_discard = xsmp_get_discard_command (client);
        if (exec_discard)
                g_key_file_set_string (keyfile,
                                       G_KEY_FILE_DESKTOP_GROUP,
                                       GSM_AUTOSTART_APP_DISCARD_KEY,
                                       exec_discard);

out:
        g_free (desktop_file_path);
        g_free (exec_program);
        g_free (exec_discard);
        g_free (startup_id);

        if (local_error != NULL) {
                g_propagate_error (error, local_error);
                g_key_file_free (keyfile);

                return NULL;
        }

        return keyfile;
}