libegg r858 - trunk/libegg/smclient



Author: danw
Date: Sun Mar 16 14:51:29 2008
New Revision: 858
URL: http://svn.gnome.org/viewvc/libegg?rev=858&view=rev

Log:
	* eggsmclient-xsmp.c: Reorganize; we have to call
	gdk_set_sm_client_id() before the application creates any windows
	(you're not allowed to change SM_CLIENT_ID while you have windows
	mapped), which means that to be safe, we have to do it at startup
	time, not after the main loop starts.
	(EggSMClientXSMP): add a waiting_to_set_initial_properties flag.
	(sm_client_xsmp_startup): Move the begining of the old
	sm_client_xsmp_connect to here. Set
	waiting_to_set_initial_properties and set up an idle handler to do
	that.
	(sm_client_xsmp_set_initial_properties): The rest of the old
	sm_client_xsmp_connect.
	(sm_client_xsmp_end_session): XSMP_STATE_START no longer exists,
	but we have to deal with waiting_to_set_initial_properties now.
	(xsmp_save_yourself): Likewise, if this arrives before we get a
	chance to set the initial properties, set them now.

	Based on a patch from Ivan N. Zlatev.


Modified:
   trunk/libegg/smclient/ChangeLog
   trunk/libegg/smclient/eggsmclient-xsmp.c

Modified: trunk/libegg/smclient/eggsmclient-xsmp.c
==============================================================================
--- trunk/libegg/smclient/eggsmclient-xsmp.c	(original)
+++ trunk/libegg/smclient/eggsmclient-xsmp.c	Sun Mar 16 14:51:29 2008
@@ -56,7 +56,6 @@
  */
 typedef enum
 {
-  XSMP_STATE_START,
   XSMP_STATE_IDLE,
   XSMP_STATE_SAVE_YOURSELF,
   XSMP_STATE_INTERACT_REQUEST,
@@ -101,6 +100,7 @@
   guint shutting_down : 1;
 
   /* Todo list */
+  guint waiting_to_set_initial_properties : 1;
   guint waiting_to_emit_quit : 1;
   guint waiting_to_emit_quit_cancelled : 1;
   guint waiting_to_save_myself : 1;
@@ -200,72 +200,19 @@
 }
 
 static gboolean
-sm_client_xsmp_connect (gpointer user_data)
+sm_client_xsmp_set_initial_properties (gpointer user_data)
 {
   EggSMClientXSMP *xsmp = user_data;
-  SmcCallbacks callbacks;
-  char *client_id;
-  char error_string_ret[256];
-  char pid_str[64];
   EggDesktopFile *desktop_file;
   GPtrArray *clone, *restart;
+  char pid_str[64];
 
-  g_source_remove (xsmp->idle);
-  xsmp->idle = 0;
-
-  ice_init ();
-  SmcSetErrorHandler (smc_error_handler);
-
-  callbacks.save_yourself.callback      = xsmp_save_yourself;
-  callbacks.die.callback                = xsmp_die;
-  callbacks.save_complete.callback      = xsmp_save_complete;
-  callbacks.shutdown_cancelled.callback = xsmp_shutdown_cancelled;
-
-  callbacks.save_yourself.client_data      = xsmp;
-  callbacks.die.client_data                = xsmp;
-  callbacks.save_complete.client_data      = xsmp;
-  callbacks.shutdown_cancelled.client_data = xsmp;
-
-  client_id = NULL;
-  error_string_ret[0] = '\0';
-  xsmp->connection =
-    SmcOpenConnection (NULL, xsmp, SmProtoMajor, SmProtoMinor,
-		       SmcSaveYourselfProcMask | SmcDieProcMask |
-		       SmcSaveCompleteProcMask |
-		       SmcShutdownCancelledProcMask,
-		       &callbacks,
-		       xsmp->client_id, &client_id,
-		       sizeof (error_string_ret), error_string_ret);
-
-  if (!xsmp->connection)
-    {
-      g_warning ("Failed to connect to the session manager: %s\n",
-		 error_string_ret[0] ?
-		 error_string_ret : "no error message given");
-      xsmp->state = XSMP_STATE_CONNECTION_CLOSED;
-      return FALSE;
-    }
-
-  /* We expect a pointless initial SaveYourself if either (a) we
-   * didn't have an initial client ID, or (b) we DID have an initial
-   * client ID, but the server rejected it and gave us a new one.
-   */
-  if (!xsmp->client_id ||
-      (client_id && strcmp (xsmp->client_id, client_id) != 0))
-    xsmp->expecting_initial_save_yourself = TRUE;
-
-  if (client_id)
+  if (xsmp->idle)
     {
-      g_free (xsmp->client_id);
-      xsmp->client_id = g_strdup (client_id);
-      free (client_id);
-
-      gdk_threads_enter ();
-      gdk_set_sm_client_id (xsmp->client_id);
-      gdk_threads_leave ();
-
-      g_debug ("Got client ID \"%s\"", xsmp->client_id);
+      g_source_remove (xsmp->idle);
+      xsmp->idle = 0;
     }
+  xsmp->waiting_to_set_initial_properties = FALSE;
 
   if (egg_sm_client_get_mode () == EGG_SM_CLIENT_MODE_NO_RESTART)
     xsmp->restart_style = SmRestartNever;
@@ -339,7 +286,7 @@
 		      NULL);
     }
 
-  xsmp->state = XSMP_STATE_IDLE;
+  update_pending_events (xsmp);
   return FALSE;
 }
 
@@ -371,19 +318,76 @@
 			const char  *client_id)
 {
   EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
+  SmcCallbacks callbacks;
+  char *ret_client_id;
+  char error_string_ret[256];
 
-  xsmp->state = XSMP_STATE_START;
-  if (xsmp->client_id)
-    g_free (xsmp->client_id);
   xsmp->client_id = g_strdup (client_id);
 
-  /* Don't connect to the session manager until we reach the main
-   * loop, since the session manager may assume we're fully up and
-   * running once we connect. (This also gives the application a
-   * chance to call egg_set_desktop_file() before we set the initial
-   * properties.)
+  ice_init ();
+  SmcSetErrorHandler (smc_error_handler);
+
+  callbacks.save_yourself.callback      = xsmp_save_yourself;
+  callbacks.die.callback                = xsmp_die;
+  callbacks.save_complete.callback      = xsmp_save_complete;
+  callbacks.shutdown_cancelled.callback = xsmp_shutdown_cancelled;
+
+  callbacks.save_yourself.client_data      = xsmp;
+  callbacks.die.client_data                = xsmp;
+  callbacks.save_complete.client_data      = xsmp;
+  callbacks.shutdown_cancelled.client_data = xsmp;
+
+  client_id = NULL;
+  error_string_ret[0] = '\0';
+  xsmp->connection =
+    SmcOpenConnection (NULL, xsmp, SmProtoMajor, SmProtoMinor,
+		       SmcSaveYourselfProcMask | SmcDieProcMask |
+		       SmcSaveCompleteProcMask |
+		       SmcShutdownCancelledProcMask,
+		       &callbacks,
+		       xsmp->client_id, &ret_client_id,
+		       sizeof (error_string_ret), error_string_ret);
+
+  if (!xsmp->connection)
+    {
+      g_warning ("Failed to connect to the session manager: %s\n",
+		 error_string_ret[0] ?
+		 error_string_ret : "no error message given");
+      xsmp->state = XSMP_STATE_CONNECTION_CLOSED;
+      return;
+    }
+
+  /* We expect a pointless initial SaveYourself if either (a) we
+   * didn't have an initial client ID, or (b) we DID have an initial
+   * client ID, but the server rejected it and gave us a new one.
+   */
+  if (!xsmp->client_id ||
+      (ret_client_id && strcmp (xsmp->client_id, ret_client_id) != 0))
+    xsmp->expecting_initial_save_yourself = TRUE;
+
+  if (ret_client_id)
+    {
+      g_free (xsmp->client_id);
+      xsmp->client_id = g_strdup (ret_client_id);
+      free (ret_client_id);
+
+      gdk_threads_enter ();
+      gdk_set_sm_client_id (xsmp->client_id);
+      gdk_threads_leave ();
+
+      g_debug ("Got client ID \"%s\"", xsmp->client_id);
+    }
+
+  xsmp->state = XSMP_STATE_IDLE;
+
+  /* Do not set the initial properties until we reach the main loop,
+   * so that the application has a chance to call
+   * egg_set_desktop_file(). (This may also help the session manager
+   * have a better idea of when the application is fully up and
+   * running.)
    */
-  xsmp->idle = g_idle_add (sm_client_xsmp_connect, client);
+  xsmp->waiting_to_set_initial_properties = TRUE;
+  xsmp->idle = g_idle_add (sm_client_xsmp_set_initial_properties, client);
 }
 
 static void
@@ -473,11 +477,6 @@
 
       switch (xsmp->state)
 	{
-	case XSMP_STATE_START:
-	  /* Force the connection to complete (or fail) now. */
-	  sm_client_xsmp_connect (xsmp);
-	  break;
-
 	case XSMP_STATE_CONNECTION_CLOSED:
 	  return FALSE;
 
@@ -498,6 +497,9 @@
 	  return TRUE;
 
 	case XSMP_STATE_IDLE:
+	  if (xsmp->waiting_to_set_initial_properties)
+	    sm_client_xsmp_set_initial_properties (xsmp);
+
 	  if (!xsmp->expecting_initial_save_yourself)
 	    break;
 	  /* else fall through */
@@ -638,6 +640,9 @@
       return;
     }
 
+  if (xsmp->waiting_to_set_initial_properties)
+    sm_client_xsmp_set_initial_properties (xsmp);
+
   /* If this is the initial SaveYourself, ignore it; we've already set
    * properties and there's no reason to actually save state too.
    */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]