summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas James Alexander Thurman <tthurman@src.gnome.org>2009-02-10 05:12:53 +0000
committerThomas James Alexander Thurman <tthurman@src.gnome.org>2009-02-10 05:12:53 +0000
commit3d0bfbb4f40735fa2ae2fc1b5f664bf647721a71 (patch)
tree4263155859f16736c9e0cecd6a23ddbd3cd2a790
parentb893e88e8b9edce521b340725848237bb0a1fd78 (diff)
downloadmetacity-3d0bfbb4f40735fa2ae2fc1b5f664bf647721a71.tar.gz
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
-rw-r--r--ChangeLog13
-rw-r--r--src/core/delete.c297
-rw-r--r--src/core/keybindings.c2
-rw-r--r--src/core/main.c46
-rw-r--r--src/core/util.c79
-rw-r--r--src/core/window-private.h1
-rw-r--r--src/core/window.c1
-rw-r--r--src/include/util.h36
8 files changed, 192 insertions, 283 deletions
diff --git a/ChangeLog b/ChangeLog
index af935ff1..63686364 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 abd1fd2c..62944232 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 66b8294f..63596bb8 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 cfc59296..ede0cbb4 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 bcfcb7f4..af4b8dd8 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 65740192..f5d890a2 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 c59f9a39..905f9c39 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 5041f5ec..ba202d3d 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 */