[mutter: 9/209] Further movement of code out of metacity-dialog into Zenity; this time it's the "kil



commit 3d0bfbb4f40735fa2ae2fc1b5f664bf647721a71
Author: Thomas James Alexander Thurman <tthurman src gnome org>
Date:   Tue Feb 10 05:12:53 2009 +0000

            Further movement of code out of metacity-dialog into Zenity;
            this time it's the "kill or wait?" dialogue.  Much code saved.
    	* src/core/delete.c:
    	* src/core/keybindings.c:
    	* src/core/main.c:
    	* src/core/util.c:
    	* src/core/window-private.h:
    	* src/core/window.c:
    	* src/include/util.h:
    
    
    svn path=/trunk/; revision=4125

 ChangeLog                 |   13 ++
 src/core/delete.c         |  297 +++++----------------------------------------
 src/core/keybindings.c    |    2 +
 src/core/main.c           |   46 +++++++-
 src/core/util.c           |   79 ++++++++++--
 src/core/window-private.h |    1 -
 src/core/window.c         |    1 -
 src/include/util.h        |   36 ++++++-
 8 files changed, 192 insertions(+), 283 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index af935ff..6368636 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2009-02-10  Thomas Thurman  <tthurman gnome org>
+
+        Further movement of code out of metacity-dialog into Zenity;
+        this time it's the "kill or wait?" dialogue.  Much code saved.
+
+	* src/core/delete.c:
+	* src/core/keybindings.c:
+	* src/core/main.c:
+	* src/core/util.c:
+	* src/core/window-private.h:
+	* src/core/window.c:
+	* src/include/util.h:
+
 2009-02-07  Thomas Thurman  <tthurman gnome org>
 
         Windows demanding attention should never appear in the
diff --git a/src/core/delete.c b/src/core/delete.c
index abd1fd2..6294423 100644
--- a/src/core/delete.c
+++ b/src/core/delete.c
@@ -55,227 +55,26 @@ delete_ping_reply_func (MetaDisplay *display,
   /* we do nothing */
 }
 
-static Window
-window_from_string (const char *str)
-{
-  char *end;
-  unsigned long l;
-
-  end = NULL;
-  
-  l = strtoul (str, &end, 16);
-
-  if (end == NULL || end == str)
-    {
-      meta_warning (_("Could not parse \"%s\" as an integer"),
-                    str);
-      return None;
-    }
-
-  if (*end != '\0')
-    {
-      meta_warning (_("Did not understand trailing characters \"%s\" in string \"%s\""),
-                    end, str);
-      return None;
-    }
-
-  return l;
-}
-
-static int
-pid_from_string (const char *str)
-{
-  char *end;
-  long l;
-
-  end = NULL;
-  
-  l = strtol (str, &end, 10);
-
-  if (end == NULL || end == str)
-    {
-      meta_warning (_("Could not parse \"%s\" as an integer"),
-                    str);
-      return None;
-    }
-
-  if (*end != '\0')
-    {
-      meta_warning (_("Did not understand trailing characters \"%s\" in string \"%s\""),
-                    end, str);
-      return None;
-    }
-
-  return l;
-}
-
 static gboolean
-parse_dialog_output (const char *str,
-                     int        *pid_out,
-                     Window     *win_out)
+delete_window_callback (gpointer w_p)
 {
-  char **split;
-
-  split = g_strsplit (str, "\n", 2);
-  if (split && split[0] && split[1])
-    {
-      g_strchomp (split[0]);
-      g_strchomp (split[1]);
-
-      *pid_out = pid_from_string (split[0]);
-      *win_out = window_from_string (split[1]);
-
-      g_strfreev (split);
-      
-      return TRUE;
-    }
-  else
-    {
-      g_strfreev (split);
-      meta_warning (_("Failed to parse message \"%s\" from dialog process\n"),
-                    str);
-      return FALSE;
-    }
-}
-
-static void
-search_and_destroy_window (int    pid,
-                           Window xwindow)
-{
-  /* Find the window with the given dialog PID,
-   * double check that it matches "xwindow", then
-   * kill the window.
-   */
-  GSList *tmp;
-  gboolean found = FALSE;
-  GSList *windows;
-
-  if (xwindow == None)
-    {
-      meta_topic (META_DEBUG_PING,
-                  "Window to destroy is None, doing nothing\n");
-      return;
-    }
-
-  windows = meta_display_list_windows (meta_get_display ());
-  tmp = windows;
-
-  while (tmp != NULL)
-    {
-      MetaWindow *w = tmp->data;
+  meta_window_kill ((MetaWindow*) w_p);
 
-      if (w->dialog_pid == pid)
-        {
-          if (w->xwindow != xwindow)
-            meta_topic (META_DEBUG_PING,
-                        "Dialog pid matches but not xwindow (0x%lx vs. 0x%lx)\n",
-                        w->xwindow, xwindow);
-          else
-            {
-              meta_window_kill (w);
-              found = TRUE;
-            }
-        }
-          
-      tmp = tmp->next;
-    }
-
-  g_slist_free (windows);
-  
-  if (!found)
-    meta_topic (META_DEBUG_PING,
-                "Did not find a window with dialog pid %d xwindow 0x%lx\n",
-                pid, xwindow);
+  return FALSE; /* don't do it again */
 }
 
 static void
-release_window_with_fd (int fd)
+sigchld_handler (MetaNexus *nexus, guint arg1, gpointer arg2, gpointer user_data)
 {
-  /* Find the window with the given dialog PID,
-   * double check that it matches "xwindow", then
-   * kill the window.
-   */
-  gboolean found = FALSE;
-  
-  GSList *windows = meta_display_list_windows (meta_get_display ());
-  GSList *tmp = windows;
+  MetaWindow *ours = (MetaWindow*) user_data;
 
-  while (tmp != NULL)
+  if (GPOINTER_TO_INT (arg2) == ours->dialog_pid)
     {
-      MetaWindow *w = tmp->data;
+      if (arg1 == 1 /* pressed "force quit" */)
+        g_idle_add (delete_window_callback, user_data);
 
-      if (w->dialog_pid >= 0 &&
-          w->dialog_pipe == fd)
-        {
-          meta_topic (META_DEBUG_PING,
-                      "Removing dialog with fd %d pid %d from window %s\n",
-                      fd, w->dialog_pid, w->desc);
-          meta_window_free_delete_dialog (w);
-          found = TRUE;
-        }
-       
-      tmp = tmp->next;
+      ours->dialog_pid = -1; /* forget it anyway */
     }
-
-  g_slist_free (windows);
-      
-  if (!found)
-    meta_topic (META_DEBUG_PING,
-                "Did not find a window with a dialog pipe %d\n",
-                fd);
-}
-
-static gboolean  
-io_from_ping_dialog (GIOChannel   *channel,
-                     GIOCondition  condition,
-                     gpointer      data)
-{  
-  meta_topic (META_DEBUG_PING,
-              "IO handler from ping dialog, condition = %x\n",
-              condition);
-  
-  if (condition & G_IO_IN)
-    {
-      char *str;
-      gsize len;
-      GError *err;
-
-      /* Go ahead and block for all data from child */
-      str = NULL;
-      len = 0;
-      err = NULL;
-      g_io_channel_read_to_end (channel,
-                                &str, &len,
-                                &err);
-      
-      if (err)
-        {
-          meta_warning (_("Error reading from dialog display process: %s\n"),
-                        err->message);
-          g_error_free (err);
-        }
-
-      meta_topic (META_DEBUG_PING,
-                  "Read %" G_GSIZE_FORMAT " bytes strlen %d \"%s\" from child\n",
-                  len, str ? (int) strlen (str) : 0, str ? str : "NULL");
-      
-      if (len > 0)
-        {
-          /* We're supposed to kill the given window */
-          int pid;
-          Window xwindow;
-
-          if (parse_dialog_output (str, &pid, &xwindow))
-            search_and_destroy_window (pid, xwindow);
-        }
-
-      g_free (str);
-    }
-
-  release_window_with_fd (g_io_channel_unix_get_fd (channel));
-  
-  /* Remove the callback */
-  return FALSE; 
 }
 
 static void
@@ -285,15 +84,9 @@ delete_ping_timeout_func (MetaDisplay *display,
                           void        *user_data)
 {
   MetaWindow *window = user_data;
-  GError *err;
-  int child_pid;
-  int outpipe;
-  char *argv[9];
-  char numbuf[32];
-  char timestampbuf[32];
-  char *window_id_str;
   char *window_title;
-  GIOChannel *channel;
+  gchar *window_content;
+  GPid dialog_pid;
   
   meta_topic (META_DEBUG_PING,
               "Got delete ping timeout for %s\n",
@@ -304,54 +97,32 @@ delete_ping_timeout_func (MetaDisplay *display,
       meta_window_present_delete_dialog (window, timestamp);
       return;
     }
-  
-  window_id_str = g_strdup_printf ("0x%lx", window->xwindow);
-  window_title = g_locale_from_utf8 (window->title, -1, NULL, NULL, NULL);
 
-  sprintf (numbuf, "%d", window->screen->number);
-  sprintf (timestampbuf, "%u", timestamp);
-  
-  argv[0] = METACITY_LIBEXECDIR"/metacity-dialog";
-  argv[1] = "--screen";
-  argv[2] = numbuf;
-  argv[3] = "--timestamp";
-  argv[4] = timestampbuf;
-  argv[5] = "--kill-window-question";
-  argv[6] = window_title;
-  argv[7] = window_id_str;
-  argv[8] = NULL;
-  
-  err = NULL;
-  if (!g_spawn_async_with_pipes ("/",
-                                 argv,
-                                 NULL,
-                                 0,
-                                 NULL, NULL,
-                                 &child_pid,
-                                 NULL,
-                                 &outpipe,
-                                 NULL,
-                                 &err))
-    {
-      meta_warning (_("Error launching metacity-dialog to ask about killing an application: %s\n"),
-                    err->message);
-      g_error_free (err);
-      goto out;
-    }
+  window_title = g_locale_from_utf8 (window->title, -1, NULL, NULL, NULL);
 
-  window->dialog_pid = child_pid;
-  window->dialog_pipe = outpipe;  
+  window_content = g_strdup_printf(
+      _("<big><b><tt>%s</tt> is not responding.</b></big>\n\n"
+      "<i>You may choose to wait a short while for it to "
+      "continue or force the application to quit entirely.</i>"),
+      window_title);
 
-  channel = g_io_channel_unix_new (window->dialog_pipe);
-  g_io_add_watch_full (channel, G_PRIORITY_DEFAULT,
-                       G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
-                       io_from_ping_dialog,
-                       NULL, NULL);
-  g_io_channel_unref (channel);
-  
- out:
   g_free (window_title);
-  g_free (window_id_str);
+
+  dialog_pid =
+    meta_show_dialog ("--question",
+                      window_content, 0,
+                      window->screen->number,
+                      _("_Wait"), _("_Force Quit"), window->xwindow,
+                      NULL, NULL);
+
+  g_free (window_content);
+
+  window->dialog_pid = dialog_pid;
+
+  g_signal_connect (sigchld_nexus, "sigchld",
+                    G_CALLBACK (sigchld_handler),
+                    window);
+
 }
 
 void
@@ -461,9 +232,7 @@ meta_window_free_delete_dialog (MetaWindow *window)
   if (window->dialog_pid >= 0)
     {
       kill (window->dialog_pid, 9);
-      close (window->dialog_pipe);
       window->dialog_pid = -1;
-      window->dialog_pipe = -1;
     }
 }
 
diff --git a/src/core/keybindings.c b/src/core/keybindings.c
index 66b8294..63596bb 100644
--- a/src/core/keybindings.c
+++ b/src/core/keybindings.c
@@ -2300,6 +2300,7 @@ error_on_command (int         command_index,
                         text,
                         NULL,
                         screen_number,
+                        NULL, NULL, 0,
                         NULL, NULL);
 
       g_free (text);
@@ -2311,6 +2312,7 @@ error_on_command (int         command_index,
                         message,
                         NULL,
                         screen_number,
+                        NULL, NULL, 0,
                         NULL, NULL);
     }
 }
diff --git a/src/core/main.c b/src/core/main.c
index cfc5929..ede0cbb 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -58,6 +58,7 @@
 
 #include <stdlib.h>
 #include <sys/types.h>
+#include <wait.h>
 #include <stdio.h>
 #include <string.h>
 #include <signal.h>
@@ -365,6 +366,29 @@ sigterm_handler (int signum)
 
   exit (meta_exit_code);
 }
+
+static guint sigchld_signal_id = 0;
+
+static void
+sigchld_handler (int signum, siginfo_t *info, void *context)
+{
+  int stat;
+
+  if (info->si_code == CLD_EXITED)
+    {
+      g_signal_emit (sigchld_nexus, sigchld_signal_id, 0,
+                     info->si_status,
+                     GINT_TO_POINTER (info->si_pid));
+    }
+
+  g_signal_handlers_disconnect_matched (sigchld_nexus,
+                                        G_SIGNAL_MATCH_DATA,
+                                        sigchld_signal_id,
+                                        0, NULL, NULL,
+                                        GINT_TO_POINTER (info->si_pid));
+
+  waitpid (info->si_pid, &stat, WNOHANG);
+}
     
 /**
  * This is where the story begins. It parses commandline options and
@@ -394,6 +418,8 @@ main (int argc, char **argv)
   
   if (setlocale (LC_ALL, "") == NULL)
     meta_warning ("Locale not understood by C library, internationalization will not work\n");
+
+  g_type_init ();
   
   sigemptyset (&empty_mask);
   act.sa_handler = SIG_IGN;
@@ -413,6 +439,24 @@ main (int argc, char **argv)
     g_printerr ("Failed to register SIGTERM handler: %s\n",
 		g_strerror (errno));
 
+  sigchld_nexus = g_object_new (META_TYPE_NEXUS, NULL);
+
+  sigchld_signal_id =
+    g_signal_new ("sigchld", META_TYPE_NEXUS,
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL,
+                  g_cclosure_marshal_VOID__UINT_POINTER,
+                  G_TYPE_NONE,
+                  2,
+                  G_TYPE_UINT, G_TYPE_POINTER);
+  
+  act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
+  act.sa_handler = SIG_DFL;
+  act.sa_sigaction = &sigchld_handler;
+  if (sigaction (SIGCHLD, &act, NULL) < 0)
+    g_printerr ("Failed to register SIGCHLD handler: %s\n",
+		g_strerror (errno));
+
   if (g_getenv ("METACITY_VERBOSE"))
     meta_set_verbose (TRUE);
   if (g_getenv ("METACITY_DEBUG"))
@@ -447,8 +491,6 @@ main (int argc, char **argv)
   
   meta_main_loop = g_main_loop_new (NULL, FALSE);
   
-  g_type_init ();
-
   meta_ui_init (&argc, &argv);  
 
   /* must be after UI init so we can override GDK handlers */
diff --git a/src/core/util.c b/src/core/util.c
index bcfcb7f..af4b8dd 100644
--- a/src/core/util.c
+++ b/src/core/util.c
@@ -37,6 +37,8 @@
 #include <X11/Xlib.h>   /* must explicitly be included for Solaris; #326746 */
 #include <X11/Xutil.h>  /* Just for the definition of the various gravities */
 
+MetaNexus *sigchld_nexus;
+
 #ifdef HAVE_BACKTRACE
 #include <execinfo.h>
 void
@@ -538,11 +540,14 @@ meta_gravity_to_string (int gravity)
     }
 }
 
-void
+GPid
 meta_show_dialog (const char *type,
                   const char *message,
                   const char *timeout,
                   const gint screen_number,
+                  const char *ok_text,
+                  const char *cancel_text,
+                  const int transient_for,
                   const char **columns,
                   const char **entries)
 {
@@ -561,12 +566,11 @@ zenity --display X --screen S --title Metacity --list --timeout 240 --text "Thes
   */
 
   const char **argvl;
+  char **envl;
   int i=0;
   GPid child_pid;
 
-  argvl = g_malloc(sizeof (char*) *
-                   (9 + (timeout?2:0))
-                   );
+  argvl = g_malloc(sizeof (char*) * 15);
 
   argvl[i++] = "zenity";
   argvl[i++] = type;
@@ -584,18 +588,38 @@ zenity --display X --screen S --title Metacity --list --timeout 240 --text "Thes
       argvl[i++] = timeout;
     }
 
+  if (ok_text)
+    {
+      argvl[i++] = "--ok-label";
+      argvl[i++] = ok_text;
+     }
+
+   if (cancel_text)
+    {
+      argvl[i++] = "--cancel-label";
+      argvl[i++] = cancel_text;
+     }
+
   argvl[i] = NULL;
 
-  g_spawn_async_with_pipes (
-                            "/",
-                            (char**) argvl, /* ugh */
-                            NULL,
-                            G_SPAWN_SEARCH_PATH,
-                            NULL, NULL,
-                            &child_pid,
-                            NULL, NULL, NULL,
-                            &error
-                            );
+  if (transient_for)
+    {
+        gchar *env = g_strdup_printf("%d", transient_for);
+        setenv ("WINDOWID", env, 1);
+        g_free (env);
+    }
+  else
+    envl = NULL;
+
+  g_spawn_async (
+                 "/",
+                 (gchar**) argvl, /* ugh */
+                 NULL,
+                 G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
+                 NULL, NULL,
+                 &child_pid,
+                 &error
+                 );
 
   g_free (argvl);
   g_free (screen_number_text);
@@ -605,6 +629,33 @@ zenity --display X --screen S --title Metacity --list --timeout 240 --text "Thes
       meta_warning ("%s\n", error->message);
       g_error_free (error);
     }
+
+  return child_pid;
+}
+
+GType
+meta_nexus_get_type (void)
+{
+  static GType nexus_type = 0;
+
+  if (!nexus_type)
+    {
+      static const GTypeInfo nexus_info =
+      {
+        sizeof (MetaNexusClass),
+	NULL, NULL, NULL, NULL, NULL,
+	sizeof (MetaNexus),
+	0,
+	NULL, NULL
+      };
+
+      nexus_type = g_type_register_static (G_TYPE_OBJECT,
+					   "MetaNexus",
+					   &nexus_info,
+					   0);
+    }
+
+  return nexus_type;
 }
 
 /* eof util.c */
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 6574019..f5d890a 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -364,7 +364,6 @@ struct _MetaWindow
   
   /* Current dialog open for this window */
   int dialog_pid;
-  int dialog_pipe;
 
   /* maintained by group.c */
   MetaGroup *group;
diff --git a/src/core/window.c b/src/core/window.c
index c59f9a3..905f9c3 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -379,7 +379,6 @@ meta_window_new_with_attrs (MetaDisplay       *display,
   window->constructing = TRUE;
   
   window->dialog_pid = -1;
-  window->dialog_pipe = -1;
   
   window->xwindow = xwindow;
   
diff --git a/src/include/util.h b/src/include/util.h
index 5041f5e..ba202d3 100644
--- a/src/include/util.h
+++ b/src/include/util.h
@@ -26,6 +26,7 @@
 #define META_UTIL_H
 
 #include <glib.h>
+#include <glib-object.h>
 
 gboolean meta_is_verbose  (void);
 void     meta_set_verbose (gboolean setting);
@@ -97,10 +98,13 @@ char* meta_g_utf8_strndup (const gchar *src, gsize n);
 
 void  meta_free_gslist_and_elements (GSList *list_to_deep_free);
 
-void meta_show_dialog (const char *type,
+GPid meta_show_dialog (const char *type,
                        const char *title,
                        const char *message,
                        gint timeout,
+                       const char *ok_text,
+                       const char *cancel_text,
+                       const int transient_for,
                        const char **columns,
                        const char **entries);
 
@@ -127,6 +131,36 @@ void meta_show_dialog (const char *type,
 
 #endif /* !WITH_VERBOSE_MODE */
 
+#include <glib-object.h>
+
+#define META_TYPE_NEXUS            (meta_nexus_get_type ())
+#define META_NEXUS(obj)            (GTK_CHECK_CAST ((obj), META_TYPE_NEXUS, MetaNexus))
+#define META_NEXUS_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), META_TYPE_NEXUS, MetaNexusClass))
+#define META_IS_NEXUS(obj)         (GTK_CHECK_TYPE ((obj), META_TYPE_NEXUS))
+#define META_IS_NEXUS_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), META_TYPE_NEXUS))
+#define META_NEXUS_GET_CLASS(obj)  (GTK_CHECK_GET_CLASS ((obj), META_TYPE_NEXUS, MetaNexusClass))
+
+typedef struct _MetaNexus
+{
+  GObject parent_instance;
+} MetaNexus;
+
+typedef struct _MetaNexusClass
+{
+  GObjectClass parent_class;
+} MetaNexusClass;
+
+GType meta_nexus_get_type (void) G_GNUC_CONST;
+MetaNexus *meta_nexus_new ();
+
+/**
+ * An object which exists purely to attach signals to; this is to receive
+ * signals when a child process exits.  The signal is "sigchld" with no detail.
+ *
+ * \bug Eventually we should have a specialised type for objects like these.
+ */
+extern MetaNexus *sigchld_nexus;
+
 #endif /* META_UTIL_H */
 
 



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