[Xfce4-commits] [xfce/xfce4-session] 09/11: dbus-clients: Add the end session signals
noreply at xfce.org
noreply at xfce.org
Tue Jun 28 09:26:12 CEST 2016
This is an automated email from the git hooks/post-receive script.
eric pushed a commit to branch master
in repository xfce/xfce4-session.
commit 04810a0b4d2664b3ada9ad0f3c58b3536cf365f4
Author: Eric Koegel <eric.koegel at gmail.com>
Date: Tue Jun 28 07:28:42 2016 +0300
dbus-clients: Add the end session signals
The process goes:
xfsm-manager state -> XFSM_MANAGER_SHUTDOWN
xfsm-client state -> XFSM_CLIENT_SAVING
xfsm-client emits QueryEndSession
user program responds with EndSessionResponse
xfsm-client state -> XFSM_CLIENT_SAVEDONE
xfsm-manager state -> XFSM_MANAGER_SHUTDOWNPHASE2
xfsm-client emits EndSession
user program responds with EndSessionResponse
xfsm-client state -> XFSM_CLIENT_DISCONNECTED
xfsm-client emits Stop
user program quits or after 15 seconds xfsm-client sends SIGKILL.
---
xfce4-session/xfsm-client-dbus.xml | 67 +++++++++++++++++
xfce4-session/xfsm-client.c | 149 ++++++++++++++++++++++++++++++++++++-
xfce4-session/xfsm-client.h | 8 +-
xfce4-session/xfsm-manager.c | 19 ++++-
4 files changed, 237 insertions(+), 6 deletions(-)
diff --git a/xfce4-session/xfsm-client-dbus.xml b/xfce4-session/xfsm-client-dbus.xml
index 6d1ead4..f15d09e 100644
--- a/xfce4-session/xfsm-client-dbus.xml
+++ b/xfce4-session/xfsm-client-dbus.xml
@@ -115,6 +115,24 @@
<method name="Terminate"/>
<!--
+ void org.xfce.Session.Client.EndSessionResponse(Boolean is_ok,
+ String reason)
+
+ @is_ok: Whether or not it is OK to proceed. If not, the client
+ may want to inhibit session logout.
+ @reason: The reason it's not OK to proceed. This string will be
+ shown to the user.
+
+ This method is how the client communicates with the session
+ manager (and user) in response to QueryEndSession and EndSession
+ when the session is about to end.
+ -->
+ <method name="EndSessionResponse">
+ <arg direction="in" name="is_ok" type="b" />
+ <arg direction="in" name="reason" type="s" />
+ </method>
+
+ <!--
void org.xfce.Session.Client.StateChanged(Unsigned Int old_state,
Unsigned Int new_state)
@@ -159,5 +177,54 @@
<signal name="SmPropertyDeleted">
<arg name="name" type="s"/>
</signal>
+
+ <!--
+ void org.xfce.Session.Client.QueryEndSession(Unsigned Int flags)
+
+ @flags: 0 = a forceful quit.
+ 1 = a normal save and quit.
+
+ Emitted when the session is about to end. The client should
+ respond by calling EndSessionResponse. The client may interact
+ with the user during this time. The client should not begin
+ shutting down until the EndSession signal happens.
+ -->
+ <signal name="QueryEndSession">
+ <arg name="flags" type="u" />
+ </signal>
+
+ <!--
+ void org.xfce.Session.Client.EndSession(Unsigned Int flags)
+
+ @flags: 0 = a forceful quit.
+ 1 = a normal save and quit.
+
+ The client should save any work and then respond by
+ calling EndSessionResponse. The client must not interact with
+ the user, that should already have happened during the
+ QueryEndSession.
+ -->
+ <signal name="EndSession">
+ <arg name="flags" type="u" />
+ </signal>
+
+ <!--
+ void org.xfce.Session.Client.CancelEndSession(void)
+
+ Emitted when QueryEndSession has been canceled. Resume normal
+ operation.
+ -->
+ <signal name="CancelEndSession">
+ </signal>
+
+ <!--
+ void org.xfce.Session.Client.Stop(void)
+
+ Emitted when the client should terminate, this is the friendly
+ version giving the client time to save and exit gracefully before
+ it is forcefully killed.
+ -->
+ <signal name="Stop">
+ </signal>
</interface>
</node>
diff --git a/xfce4-session/xfsm-client.c b/xfce4-session/xfsm-client.c
index 09fcecb..5225905 100644
--- a/xfce4-session/xfsm-client.c
+++ b/xfce4-session/xfsm-client.c
@@ -52,11 +52,11 @@ struct _XfsmClient
gchar *app_id;
gchar *object_path;
gchar *service_name;
+ guint quit_timeout;
XfsmClientState state;
XfsmProperties *properties;
SmsConn sms_conn;
-
GDBusConnection *connection;
};
@@ -113,6 +113,9 @@ xfsm_client_finalize (GObject *obj)
if (client->properties != NULL)
xfsm_properties_free (client->properties);
+ if (client->quit_timeout != 0)
+ g_source_remove (client->quit_timeout);
+
g_free (client->id);
g_free (client->app_id);
g_free (client->object_path);
@@ -124,6 +127,24 @@ xfsm_client_finalize (GObject *obj)
+static const gchar*
+get_state (XfsmClientState state)
+{
+ static const gchar *client_state[XFSM_CLIENT_STATE_COUNT] =
+ {
+ "XFSM_CLIENT_IDLE",
+ "XFSM_CLIENT_INTERACTING",
+ "XFSM_CLIENT_SAVEDONE",
+ "XFSM_CLIENT_SAVING",
+ "XFSM_CLIENT_SAVINGLOCAL",
+ "XFSM_CLIENT_WAITFORINTERACT",
+ "XFSM_CLIENT_WAITFORPHASE2",
+ "XFSM_CLIENT_DISCONNECTED"
+ };
+
+ return client_state[state];
+}
+
static void
xfsm_properties_discard_command_changed (XfsmProperties *properties,
gchar **old_discard)
@@ -238,6 +259,22 @@ xfsm_client_get_state (XfsmClient *client)
}
+
+static const gchar*
+get_client_id (XfsmClient *client)
+{
+ const gchar *client_id;
+
+ if (client->app_id)
+ client_id = client->app_id;
+ else
+ client_id = client->id;
+
+ return client_id;
+}
+
+
+
void
xfsm_client_set_state (XfsmClient *client,
XfsmClientState state)
@@ -249,6 +286,18 @@ xfsm_client_set_state (XfsmClient *client,
XfsmClientState old_state = client->state;
client->state = state;
xfsm_dbus_client_emit_state_changed (XFSM_DBUS_CLIENT (client), old_state, state);
+
+ xfsm_verbose ("%s client state was %s and now is %s\n", get_client_id (client), get_state(old_state), get_state(state));
+
+ /* During a save, we need to ask the client if it's ok to shutdown */
+ if (state == XFSM_CLIENT_SAVING && xfsm_manager_get_state (client->manager) == XFSM_MANAGER_SHUTDOWN)
+ {
+ xfsm_dbus_client_emit_query_end_session (XFSM_DBUS_CLIENT (client), 1);
+ }
+ else if (state == XFSM_CLIENT_SAVING && xfsm_manager_get_state (client->manager) == XFSM_MANAGER_SHUTDOWNPHASE2)
+ {
+ xfsm_dbus_client_emit_end_session(XFSM_DBUS_CLIENT (client), 1);
+ }
}
}
@@ -551,6 +600,62 @@ xfsm_client_set_app_id (XfsmClient *client,
+static gboolean
+kill_hung_client (gpointer user_data)
+{
+ XfsmClient *client = XFSM_CLIENT (user_data);
+
+ client->quit_timeout = 0;
+
+ if (!client->properties)
+ return FALSE;
+
+ if (client->properties->pid < 2)
+ return FALSE;
+
+ xfsm_verbose ("killing unresponsive client %s\n", get_client_id (client));
+ kill (client->properties->pid, SIGKILL);
+
+ return FALSE;
+}
+
+
+
+void
+xfsm_client_terminate (XfsmClient *client)
+{
+ xfsm_verbose ("emitting stop signal for client %s\n", get_client_id (client));
+
+ /* Ask the client to shutdown gracefully */
+ xfsm_dbus_client_emit_stop (XFSM_DBUS_CLIENT (client));
+
+ /* add a timeout so we can forcefully stop the client */
+ client->quit_timeout = g_timeout_add_seconds (15, kill_hung_client, client);
+}
+
+
+
+void
+xfsm_client_end_session (XfsmClient *client)
+{
+ xfsm_verbose ("emitting end session signal for client %s\n", get_client_id (client));
+
+ /* Start the client shutdown */
+ xfsm_dbus_client_emit_end_session (XFSM_DBUS_CLIENT (client), 1);
+}
+
+
+void xfsm_client_cancel_shutdown (XfsmClient *client)
+{
+ xfsm_verbose ("emitting cancel session signal for client %s\n", get_client_id (client));
+
+ /* Cancel the client shutdown */
+ xfsm_dbus_client_emit_cancel_end_session (XFSM_DBUS_CLIENT (client));
+
+}
+
+
+
/*
* dbus server impl
*/
@@ -572,11 +677,12 @@ static gboolean xfsm_client_dbus_delete_sm_properties (XfsmDbusClient *object,
const gchar *const *arg_names);
static gboolean xfsm_client_dbus_terminate (XfsmDbusClient *object,
GDBusMethodInvocation *invocation);
+static gboolean xfsm_client_dbus_end_session_response (XfsmDbusClient *object,
+ GDBusMethodInvocation *invocation,
+ gboolean arg_is_ok,
+ const gchar *arg_reason);
-/* header needs the above fwd decls */
-#include <xfce4-session/xfsm-client-dbus.h>
-
static void
xfsm_client_dbus_class_init (XfsmClientClass *klass)
@@ -623,6 +729,7 @@ xfsm_client_iface_init (XfsmDbusClientIface *iface)
iface->handle_get_state = xfsm_client_dbus_get_state;
iface->handle_set_sm_properties = xfsm_client_dbus_set_sm_properties;
iface->handle_terminate = xfsm_client_dbus_terminate;
+ iface->handle_end_session_response = xfsm_client_dbus_end_session_response;
}
static void
@@ -820,5 +927,39 @@ xfsm_client_dbus_terminate (XfsmDbusClient *object,
return TRUE;
}
+ xfsm_dbus_client_complete_terminate (object, invocation);
+ return TRUE;
+}
+
+static gboolean
+xfsm_client_dbus_end_session_response (XfsmDbusClient *object,
+ GDBusMethodInvocation *invocation,
+ gboolean arg_is_ok,
+ const gchar *arg_reason)
+{
+ XfsmClient *client = XFSM_CLIENT (object);
+
+ xfsm_verbose ("got response for client %s, manager state is %s\n",
+ get_client_id (client),
+ xfsm_manager_get_state (client->manager) == XFSM_MANAGER_SHUTDOWN ? "XFSM_MANAGER_SHUTDOWN" :
+ xfsm_manager_get_state (client->manager) == XFSM_MANAGER_SHUTDOWNPHASE2 ? "XFSM_MANAGER_SHUTDOWNPHASE2" :
+ "Invalid time to respond");
+
+ if (xfsm_manager_get_state (client->manager) == XFSM_MANAGER_SHUTDOWN)
+ {
+ xfsm_manager_save_yourself_done (client->manager, client, arg_is_ok);
+ }
+ else if (xfsm_manager_get_state (client->manager) == XFSM_MANAGER_SHUTDOWNPHASE2)
+ {
+ xfsm_manager_close_connection (client->manager, client, TRUE);
+ }
+ else
+ {
+ throw_error (invocation, XFSM_ERROR_BAD_STATE,
+ "This method should be sent in response to a QueryEndSession or EndSession signal only");
+ return TRUE;
+ }
+
+ xfsm_dbus_client_complete_end_session_response (object, invocation);
return TRUE;
}
diff --git a/xfce4-session/xfsm-client.h b/xfce4-session/xfsm-client.h
index ea68c86..a396563 100644
--- a/xfce4-session/xfsm-client.h
+++ b/xfce4-session/xfsm-client.h
@@ -40,7 +40,7 @@ typedef struct _XfsmClient XfsmClient;
typedef enum
{
- XFSM_CLIENT_IDLE,
+ XFSM_CLIENT_IDLE = 0,
XFSM_CLIENT_INTERACTING,
XFSM_CLIENT_SAVEDONE,
XFSM_CLIENT_SAVING,
@@ -48,6 +48,7 @@ typedef enum
XFSM_CLIENT_WAITFORINTERACT,
XFSM_CLIENT_WAITFORPHASE2,
XFSM_CLIENT_DISCONNECTED,
+ XFSM_CLIENT_STATE_COUNT
} XfsmClientState;
GType xfsm_client_get_type (void) G_GNUC_CONST;
@@ -90,6 +91,11 @@ void xfsm_client_set_service_name (XfsmClient *client,
const gchar *service_name);
const gchar *xfsm_client_get_service_name (XfsmClient *client);
+void xfsm_client_terminate (XfsmClient *client);
+
+void xfsm_client_end_session (XfsmClient *client);
+
+void xfsm_client_cancel_shutdown (XfsmClient *client);
G_END_DECLS
diff --git a/xfce4-session/xfsm-manager.c b/xfce4-session/xfsm-manager.c
index 8912153..213c214 100644
--- a/xfce4-session/xfsm-manager.c
+++ b/xfce4-session/xfsm-manager.c
@@ -1087,7 +1087,8 @@ xfsm_manager_interact_done (XfsmManager *manager,
XfsmClient *cl = lp->data;
SmsConn sms = xfsm_client_get_sms_connection (cl);
- if (xfsm_client_get_state (cl) != XFSM_CLIENT_WAITFORINTERACT)
+ /* only sms clients do the interact stuff */
+ if (sms && xfsm_client_get_state (cl) != XFSM_CLIENT_WAITFORINTERACT)
continue;
/* reset all clients that are waiting for interact */
@@ -1096,6 +1097,10 @@ xfsm_manager_interact_done (XfsmManager *manager,
{
SmsShutdownCancelled (sms);
}
+ else
+ {
+ xfsm_client_cancel_shutdown (client);
+ }
}
xfsm_dbus_manager_emit_shutdown_cancelled (XFSM_DBUS_MANAGER (manager));
@@ -1376,6 +1381,10 @@ xfsm_manager_close_connection (XfsmManager *manager,
IceSetShutdownNegotiation (ice_conn, False);
IceCloseConnection (ice_conn);
}
+ else
+ {
+ xfsm_client_terminate (client);
+ }
}
if (manager->state == XFSM_MANAGER_SHUTDOWNPHASE2)
@@ -1479,6 +1488,10 @@ xfsm_manager_terminate_client (XfsmManager *manager,
{
SmsDie (sms);
}
+ else
+ {
+ xfsm_client_terminate (client);
+ }
return TRUE;
}
@@ -1511,6 +1524,10 @@ xfsm_manager_perform_shutdown (XfsmManager *manager)
{
SmsDie (sms);
}
+ else
+ {
+ xfsm_client_end_session (client);
+ }
}
/* check for SmRestartAnyway clients that have already quit and
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the Xfce4-commits
mailing list