[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