Remove metacity-dialog and always use zenity

This is a merge of metacity commits 0b3f45bb1b and 3d0bfbb4f4
This commit is contained in:
Vincent Untz
2009-05-05 15:57:58 +02:00
parent 90c35f8181
commit ea91834407
10 changed files with 236 additions and 854 deletions

View File

@ -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;
meta_window_kill ((MetaWindow*) w_p);
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;
}
return FALSE; /* don't do it again */
}
static void
search_and_destroy_window (int pid,
Window xwindow)
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.
*/
GSList *tmp;
gboolean found = FALSE;
GSList *windows;
MetaWindow *ours = (MetaWindow*) user_data;
if (xwindow == None)
if (GPOINTER_TO_INT (arg2) == ours->dialog_pid)
{
meta_topic (META_DEBUG_PING,
"Window to destroy is None, doing nothing\n");
return;
if (arg1 == 1 /* pressed "force quit" */)
g_idle_add (delete_window_callback, user_data);
ours->dialog_pid = -1; /* forget it anyway */
}
windows = meta_display_list_windows (meta_get_display ());
tmp = windows;
while (tmp != NULL)
{
MetaWindow *w = tmp->data;
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);
}
static void
release_window_with_fd (int fd)
{
/* 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;
while (tmp != NULL)
{
MetaWindow *w = tmp->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;
}
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_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);
window->dialog_pid = child_pid;
window->dialog_pipe = outpipe;
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;
}
}

View File

@ -2416,6 +2416,7 @@ error_on_command (int command_index,
text,
NULL,
screen_number,
NULL, NULL, 0,
NULL, NULL);
g_free (text);
@ -2427,6 +2428,7 @@ error_on_command (int command_index,
message,
NULL,
screen_number,
NULL, NULL, 0,
NULL, NULL);
}
}

View File

@ -59,6 +59,7 @@
#include <stdlib.h>
#include <sys/types.h>
#include <wait.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
@ -467,6 +468,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
@ -497,6 +521,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;
@ -516,6 +542,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"))

View File

@ -1737,13 +1737,6 @@ windows_cmp_by_title (MetaWindow *a,
return g_utf8_collate (a->title, b->title);
}
typedef struct
{
int child_pid;
int child_pipe;
gboolean shutdown;
} LameClientsDialogData;
static void
finish_interact (gboolean shutdown)
{
@ -1755,63 +1748,26 @@ finish_interact (gboolean shutdown)
}
}
static gboolean
io_from_warning_dialog (GIOChannel *channel,
GIOCondition condition,
gpointer data)
static void
sigchld_handler (MetaNexus *nexus, guint arg1, gpointer arg2, gpointer user_data)
{
LameClientsDialogData *d;
gboolean shutdown = GPOINTER_TO_INT (user_data);
d = data;
meta_topic (META_DEBUG_PING,
"IO handler from lame clients dialog, condition = %x\n",
condition);
if (condition & (G_IO_HUP | G_IO_NVAL | G_IO_ERR))
if (arg1 == 0) /* pressed "OK" */
{
finish_interact (d->shutdown);
/* Remove the callback, freeing data */
return FALSE;
finish_interact (shutdown);
}
else if (condition & G_IO_IN)
{
/* Check for EOF */
char buf[16];
int ret;
ret = read (d->child_pipe, buf, sizeof (buf));
if (ret == 0)
{
finish_interact (d->shutdown);
return FALSE;
}
}
/* Keep callback installed */
return TRUE;
}
static void
warn_about_lame_clients_and_finish_interact (gboolean shutdown)
{
GSList *lame;
GSList *lame = NULL;
GSList *windows;
char **argv;
int i;
GSList *lame_details = NULL;
GSList *tmp;
int len;
int child_pid;
int child_pipe;
GError *err;
GIOChannel *channel;
LameClientsDialogData *d;
guint32 timestamp;
char timestampbuf[32];
GSList *columns = NULL;
lame = NULL;
windows = meta_display_list_windows (meta_get_display ());
tmp = windows;
while (tmp != NULL)
@ -1838,77 +1794,43 @@ warn_about_lame_clients_and_finish_interact (gboolean shutdown)
finish_interact (shutdown);
return;
}
columns = g_slist_prepend (columns, "Window");
columns = g_slist_prepend (columns, "Class");
lame = g_slist_sort (lame, (GCompareFunc) windows_cmp_by_title);
timestamp = meta_display_get_current_time_roundtrip (meta_get_display ());
sprintf (timestampbuf, "%u", timestamp);
len = g_slist_length (lame);
len *= 2; /* titles and also classes */
len += 2; /* --timestamp flag and actual timestamp */
len += 1; /* NULL term */
len += 2; /* metacity-dialog command and option */
argv = g_new0 (char*, len);
i = 0;
argv[i] = METACITY_LIBEXECDIR"/metacity-dialog";
++i;
argv[i] = "--timestamp";
++i;
argv[i] = timestampbuf;
++i;
argv[i] = "--warn-about-no-sm-support";
++i;
tmp = lame;
while (tmp != NULL)
{
MetaWindow *w = tmp->data;
argv[i] = w->title;
++i;
argv[i] = w->res_class ? w->res_class : "";
++i;
lame_details = g_slist_prepend (lame_details,
w->res_class ? w->res_class : "");
lame_details = g_slist_prepend (lame_details,
w->title);
tmp = tmp->next;
}
child_pipe = -1;
child_pid = -1;
err = NULL;
if (!g_spawn_async_with_pipes ("/",
argv,
NULL,
0,
NULL, NULL,
&child_pid,
NULL,
&child_pipe,
NULL,
&err))
{
meta_warning (_("Error launching metacity-dialog to warn about apps that don't support session management: %s\n"),
err->message);
g_error_free (err);
}
g_free (argv);
g_slist_free (lame);
d = g_new0 (LameClientsDialogData, 1);
d->child_pipe = child_pipe;
d->child_pid = child_pid;
d->shutdown = shutdown;
channel = g_io_channel_unix_new (d->child_pipe);
g_io_add_watch_full (channel, G_PRIORITY_DEFAULT,
G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
io_from_warning_dialog,
d, g_free);
g_io_channel_unref (channel);
meta_show_dialog("--list",
_("These windows do not support &quot;save current setup&quot; "
"and will have to be restarted manually next time "
"you log in."),
"240",
meta_screen_get_screen_number (meta_get_display()->active_screen),
NULL, NULL,
None,
columns,
lame_details);
g_slist_free (lame_details);
g_signal_connect (sigchld_nexus, "sigchld",
G_CALLBACK (sigchld_handler),
GINT_TO_POINTER (shutdown));
}
#endif /* HAVE_SM */

View File

@ -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,35 +540,26 @@ 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 **columns,
const char **entries)
const char *ok_text,
const char *cancel_text,
const int transient_for,
GSList *columns,
GSList *entries)
{
GError *error = NULL;
char *screen_number_text = g_strdup_printf("%d", screen_number);
/*
We want:
zenity --display X --screen S --title Metacity --error --text "There was an error running <tt>terminal</tt>:\n\nYour computer is on fire."
** with no pipes
zenity --display X --screen S --title Metacity --question --text "<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>"
zenity --display X --screen S --title Metacity --list --timeout 240 --text "These windows do not support \"save current setup\" and will have to be restarted manually next time you log in." --column "Window" --column "Class" "Firefox" "foo" "Duke Nukem Forever" "bar"
*/
const char **argvl;
GSList *tmp;
int i=0;
GPid child_pid;
argvl = g_malloc(sizeof (char*) *
(9 + (timeout?2:0))
);
const char **argvl = g_malloc(sizeof (char*) *
(15 +
g_slist_length (columns)*2 +
g_slist_length (entries)));
argvl[i++] = "zenity";
argvl[i++] = type;
@ -584,18 +577,54 @@ 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;
}
tmp = columns;
while (tmp)
{
argvl[i++] = "--column";
argvl[i++] = tmp->data;
tmp = tmp->next;
}
tmp = entries;
while (tmp)
{
argvl[i++] = tmp->data;
tmp = tmp->next;
}
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);
}
g_spawn_async (
"/",
(gchar**) argvl, /* ugh */
NULL,
G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
NULL, NULL,
&child_pid,
&error
);
if (transient_for)
unsetenv ("WINDOWID");
g_free (argvl);
g_free (screen_number_text);
@ -605,6 +634,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 */

View File

@ -354,7 +354,6 @@ struct _MetaWindow
/* Current dialog open for this window */
int dialog_pid;
int dialog_pipe;
/* maintained by group.c */
MetaGroup *group;

View File

@ -601,7 +601,6 @@ meta_window_new_with_attrs (MetaDisplay *display,
window->constructing = TRUE;
window->dialog_pid = -1;
window->dialog_pipe = -1;
window->xwindow = xwindow;