static void interact_request_callback (SmsConn conn, SmPointer manager_data, int dialog_type) { CsmXSMPClient *client = manager_data; #if 0 gboolean res; GError *error; #endif g_debug ("CsmXSMPClient: Client '%s' received InteractRequest(%s)", client->priv->description, dialog_type == SmDialogNormal ? "Dialog" : "Errors"); csm_client_end_session_response (CSM_CLIENT (client), FALSE, FALSE, FALSE, _("This program is blocking logout.")); #if 0 /* Can't just call back with Interact because session client grabs the keyboard! So, we try to get it to release grabs by telling it we've cancelled the shutdown. This grabbing is clearly bullshit and is not supported by the client spec or protocol spec. */ res = xsmp_cancel_end_session (CSM_CLIENT (client), &error); if (! res) { g_warning ("Unable to cancel end session: %s", error->message); g_error_free (error); } #endif xsmp_interact (CSM_CLIENT (client)); }
static DBusHandlerResult client_dbus_filter_function (DBusConnection *connection, DBusMessage *message, void *user_data) { CsmDBusClient *client = CSM_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 ("CsmDBusClient: 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 (csm_client_peek_id (CSM_CLIENT (client)) != NULL); if (path != NULL && strcmp (path, csm_client_peek_id (CSM_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 void delete_property (CsmXSMPClient *client, const char *name) { int index; SmProp *prop; prop = find_property (client, name, &index); if (!prop) { return; } #if 0 /* This is wrong anyway; we can't unconditionally run the current * discard command; if this client corresponds to a CsmAppResumed, * and the current discard command is identical to the app's * discard_command, then we don't run the discard command now, * because that would delete a saved state we may want to resume * again later. */ if (!strcmp (name, SmDiscardCommand)) { csm_client_run_discard (CSM_CLIENT (client)); } #endif g_ptr_array_remove_index_fast (client->priv->props, index); SmFreeProperty (prop); }
static void save_yourself_done_callback (SmsConn conn, SmPointer manager_data, Bool success) { CsmXSMPClient *client = manager_data; g_debug ("CsmXSMPClient: Client '%s' received SaveYourselfDone(success = %s)", client->priv->description, success ? "True" : "False"); if (client->priv->current_save_yourself != -1) { SmsSaveComplete (client->priv->conn); client->priv->current_save_yourself = -1; } /* If success is false then the application couldn't save data. Nothing * the session manager can do about, though. FIXME: we could display a * dialog about this, I guess. */ csm_client_end_session_response (CSM_CLIENT (client), TRUE, FALSE, FALSE, NULL); if (client->priv->next_save_yourself) { int save_type = client->priv->next_save_yourself; gboolean allow_interact = client->priv->next_save_yourself_allow_interact; client->priv->next_save_yourself = -1; client->priv->next_save_yourself_allow_interact = -1; do_save_yourself (client, save_type, allow_interact); } }
static Status register_client_callback (SmsConn conn, SmPointer manager_data, char *previous_id) { CsmXSMPClient *client = manager_data; gboolean handled; char *id; g_debug ("CsmXSMPClient: Client '%s' received RegisterClient(%s)", client->priv->description, previous_id ? previous_id : "NULL"); /* There are three cases: * 1. id is NULL - we'll use a new one * 2. id is known - we'll use known one * 3. id is unknown - this is an error */ id = g_strdup (previous_id); handled = FALSE; g_signal_emit (client, signals[REGISTER_REQUEST], 0, &id, &handled); if (! handled) { g_debug ("CsmXSMPClient: RegisterClient not handled!"); g_free (id); free (previous_id); g_assert_not_reached (); return FALSE; } if (IS_STRING_EMPTY (id)) { g_debug ("CsmXSMPClient: rejected: invalid previous_id"); free (previous_id); return FALSE; } g_object_set (client, "startup-id", id, NULL); set_description (client); g_debug ("CsmXSMPClient: Sending RegisterClientReply to '%s'", client->priv->description); SmsRegisterClientReply (conn, id); if (IS_STRING_EMPTY (previous_id)) { /* Send the initial SaveYourself. */ g_debug ("CsmXSMPClient: Sending initial SaveYourself"); SmsSaveYourself (conn, SmSaveLocal, False, SmInteractStyleNone, False); client->priv->current_save_yourself = SmSaveLocal; } csm_client_set_status (CSM_CLIENT (client), CSM_CLIENT_REGISTERED); g_free (id); free (previous_id); return TRUE; }
static void close_connection_callback (SmsConn conn, SmPointer manager_data, int count, char **reason_msgs) { CsmXSMPClient *client = manager_data; int i; g_debug ("CsmXSMPClient: Client '%s' received CloseConnection", client->priv->description); for (i = 0; i < count; i++) { g_debug ("CsmXSMPClient: close reason: '%s'", reason_msgs[i]); } SmFreeReasons (count, reason_msgs); csm_client_set_status (CSM_CLIENT (client), CSM_CLIENT_FINISHED); csm_client_disconnected (CSM_CLIENT (client)); }
static void handle_end_session_response (CsmDBusClient *client, DBusMessage *message) { const char *sender; DBusMessage *reply; DBusError error; dbus_bool_t is_ok; const char *reason; dbus_error_init (&error); if (! dbus_message_get_args (message, &error, DBUS_TYPE_BOOLEAN, &is_ok, DBUS_TYPE_STRING, &reason, DBUS_TYPE_INVALID)) { if (dbus_error_is_set (&error)) { g_warning ("Invalid method call: %s", error.message); dbus_error_free (&error); } raise_error (client->priv->connection, message, DBUS_ERROR_FAILED, "There is a syntax error in the invocation of the method EndSessionResponse"); return; } g_debug ("CsmDBusClient: got EndSessionResponse is-ok:%d reason=%s", is_ok, reason); /* make sure it is from our client */ sender = dbus_message_get_sender (message); if (sender == NULL || IS_STRING_EMPTY (client->priv->bus_name) || strcmp (sender, client->priv->bus_name) != 0) { raise_error (client->priv->connection, message, DBUS_ERROR_FAILED, "Caller not recognized as the client"); return; } reply = dbus_message_new_method_return (message); if (reply == NULL) { g_error ("No memory"); } csm_client_end_session_response (CSM_CLIENT (client), is_ok, FALSE, FALSE, reason); if (! dbus_connection_send (client->priv->connection, reply, NULL)) { g_error ("No memory"); } dbus_message_unref (reply); }
CsmClient * csm_xsmp_client_new (IceConn ice_conn) { CsmXSMPClient *xsmp; xsmp = g_object_new (CSM_TYPE_XSMP_CLIENT, "ice-connection", ice_conn, NULL); return CSM_CLIENT (xsmp); }
CsmClient * csm_dbus_client_new (const char *startup_id, const char *bus_name) { CsmDBusClient *client; client = g_object_new (CSM_TYPE_DBUS_CLIENT, "startup-id", startup_id, "bus-name", bus_name, NULL); return CSM_CLIENT (client); }
static gboolean client_iochannel_watch (GIOChannel *channel, GIOCondition condition, CsmXSMPClient *client) { gboolean keep_going; g_object_ref (client); switch (IceProcessMessages (client->priv->ice_connection, NULL, NULL)) { case IceProcessMessagesSuccess: keep_going = TRUE; break; case IceProcessMessagesIOError: g_debug ("CsmXSMPClient: IceProcessMessagesIOError on '%s'", client->priv->description); csm_client_set_status (CSM_CLIENT (client), CSM_CLIENT_FAILED); /* Emitting "disconnected" will eventually cause * IceCloseConnection() to be called. */ csm_client_disconnected (CSM_CLIENT (client)); keep_going = FALSE; break; case IceProcessMessagesConnectionClosed: g_debug ("CsmXSMPClient: IceProcessMessagesConnectionClosed on '%s'", client->priv->description); client->priv->ice_connection = NULL; keep_going = FALSE; break; default: g_assert_not_reached (); } g_object_unref (client); return keep_going; }
static void interact_done_callback (SmsConn conn, SmPointer manager_data, Bool cancel_shutdown) { CsmXSMPClient *client = manager_data; g_debug ("CsmXSMPClient: Client '%s' received InteractDone(cancel_shutdown = %s)", client->priv->description, cancel_shutdown ? "True" : "False"); csm_client_end_session_response (CSM_CLIENT (client), TRUE, FALSE, cancel_shutdown, NULL); }
static void save_yourself_phase2_request_callback (SmsConn conn, SmPointer manager_data) { CsmXSMPClient *client = manager_data; g_debug ("CsmXSMPClient: Client '%s' received SaveYourselfPhase2Request", client->priv->description); client->priv->current_save_yourself = -1; /* this is a valid response to SaveYourself and therefore may be a response to a QES or ES */ csm_client_end_session_response (CSM_CLIENT (client), TRUE, TRUE, FALSE, NULL); }
static void set_description (CsmXSMPClient *client) { SmProp *prop; const char *id; prop = find_property (client, SmProgram, NULL); id = csm_client_peek_startup_id (CSM_CLIENT (client)); g_free (client->priv->description); if (prop) { client->priv->description = g_strdup_printf ("%p [%.*s %s]", client, prop->vals[0].length, (char *)prop->vals[0].value, id); } else if (id != NULL) { client->priv->description = g_strdup_printf ("%p [%s]", client, id); } else { client->priv->description = g_strdup_printf ("%p", client); } }
static char * get_desktop_file_path (CsmXSMPClient *client) { SmProp *prop; char *desktop_file_path = NULL; const char *program_name; /* XSMP clients using egcsmclient defines a special property * pointing to their respective desktop entry file */ prop = find_property (client, CsmDesktopFile, 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 CsmDesktopFile then we * try to find the desktop file from its program name */ prop = find_property (client, SmProgram, NULL); if (!prop) { goto out; } program_name = prop->vals[0].value; desktop_file_path = csm_util_find_desktop_file_for_app_name (program_name, TRUE, FALSE); out: g_debug ("CsmXSMPClient: desktop file for client %s is %s", csm_client_peek_id (CSM_CLIENT (client)), desktop_file_path ? desktop_file_path : "(null)"); return desktop_file_path; }