mirror of
https://github.com/brl/mutter.git
synced 2024-11-25 01:20:42 -05:00
Remove metacity-dialog and always use zenity
This is a merge of metacity commits0b3f45bb1b
and3d0bfbb4f4
This commit is contained in:
parent
90c35f8181
commit
ea91834407
@ -177,9 +177,6 @@ libmetacityinclude_HEADERS = \
|
|||||||
metacity_theme_viewer_SOURCES= \
|
metacity_theme_viewer_SOURCES= \
|
||||||
ui/theme-viewer.c
|
ui/theme-viewer.c
|
||||||
|
|
||||||
metacity_dialog_SOURCES= \
|
|
||||||
ui/metacity-dialog.c
|
|
||||||
|
|
||||||
schema_bindings_SOURCES = \
|
schema_bindings_SOURCES = \
|
||||||
core/schema-bindings.c \
|
core/schema-bindings.c \
|
||||||
metacity.schemas.in.in
|
metacity.schemas.in.in
|
||||||
@ -190,7 +187,6 @@ metacity.schemas.in: schema_bindings ${srcdir}/metacity.schemas.in.in
|
|||||||
${builddir}/schema_bindings ${srcdir}/metacity.schemas.in.in ${builddir}/metacity.schemas.in
|
${builddir}/schema_bindings ${srcdir}/metacity.schemas.in.in ${builddir}/metacity.schemas.in
|
||||||
|
|
||||||
bin_PROGRAMS=metacity metacity-theme-viewer
|
bin_PROGRAMS=metacity metacity-theme-viewer
|
||||||
libexec_PROGRAMS=metacity-dialog
|
|
||||||
|
|
||||||
api_version = $(METACITY_MAJOR_VERSION).$(METACITY_MINOR_VERSION)
|
api_version = $(METACITY_MAJOR_VERSION).$(METACITY_MINOR_VERSION)
|
||||||
|
|
||||||
@ -232,7 +228,6 @@ metacity_LDADD=@METACITY_LIBS@ libmetacity-private.la $(EFENCE)
|
|||||||
metacity_LDFLAGS=-export-dynamic
|
metacity_LDFLAGS=-export-dynamic
|
||||||
|
|
||||||
metacity_theme_viewer_LDADD= @METACITY_LIBS@ libmetacity-private.la
|
metacity_theme_viewer_LDADD= @METACITY_LIBS@ libmetacity-private.la
|
||||||
metacity_dialog_LDADD=@METACITY_LIBS@
|
|
||||||
|
|
||||||
testboxes_SOURCES=include/util.h core/util.c include/boxes.h core/boxes.c core/testboxes.c
|
testboxes_SOURCES=include/util.h core/util.c include/boxes.h core/boxes.c core/testboxes.c
|
||||||
testgradient_SOURCES=ui/gradient.h ui/gradient.c ui/testgradient.c
|
testgradient_SOURCES=ui/gradient.h ui/gradient.c ui/testgradient.c
|
||||||
|
@ -55,227 +55,26 @@ delete_ping_reply_func (MetaDisplay *display,
|
|||||||
/* we do nothing */
|
/* 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
|
static gboolean
|
||||||
parse_dialog_output (const char *str,
|
delete_window_callback (gpointer w_p)
|
||||||
int *pid_out,
|
|
||||||
Window *win_out)
|
|
||||||
{
|
{
|
||||||
char **split;
|
meta_window_kill ((MetaWindow*) w_p);
|
||||||
|
|
||||||
split = g_strsplit (str, "\n", 2);
|
return FALSE; /* don't do it again */
|
||||||
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
|
static void
|
||||||
search_and_destroy_window (int pid,
|
sigchld_handler (MetaNexus *nexus, guint arg1, gpointer arg2, gpointer user_data)
|
||||||
Window xwindow)
|
|
||||||
{
|
{
|
||||||
/* Find the window with the given dialog PID,
|
MetaWindow *ours = (MetaWindow*) user_data;
|
||||||
* double check that it matches "xwindow", then
|
|
||||||
* kill the window.
|
|
||||||
*/
|
|
||||||
GSList *tmp;
|
|
||||||
gboolean found = FALSE;
|
|
||||||
GSList *windows;
|
|
||||||
|
|
||||||
if (xwindow == None)
|
if (GPOINTER_TO_INT (arg2) == ours->dialog_pid)
|
||||||
{
|
{
|
||||||
meta_topic (META_DEBUG_PING,
|
if (arg1 == 1 /* pressed "force quit" */)
|
||||||
"Window to destroy is None, doing nothing\n");
|
g_idle_add (delete_window_callback, user_data);
|
||||||
return;
|
|
||||||
|
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
|
static void
|
||||||
@ -285,15 +84,9 @@ delete_ping_timeout_func (MetaDisplay *display,
|
|||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
MetaWindow *window = 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;
|
char *window_title;
|
||||||
GIOChannel *channel;
|
gchar *window_content;
|
||||||
|
GPid dialog_pid;
|
||||||
|
|
||||||
meta_topic (META_DEBUG_PING,
|
meta_topic (META_DEBUG_PING,
|
||||||
"Got delete ping timeout for %s\n",
|
"Got delete ping timeout for %s\n",
|
||||||
@ -304,54 +97,32 @@ delete_ping_timeout_func (MetaDisplay *display,
|
|||||||
meta_window_present_delete_dialog (window, timestamp);
|
meta_window_present_delete_dialog (window, timestamp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
window_id_str = g_strdup_printf ("0x%lx", window->xwindow);
|
|
||||||
window_title = g_locale_from_utf8 (window->title, -1, NULL, NULL, NULL);
|
window_title = g_locale_from_utf8 (window->title, -1, NULL, NULL, NULL);
|
||||||
|
|
||||||
sprintf (numbuf, "%d", window->screen->number);
|
window_content = g_strdup_printf(
|
||||||
sprintf (timestampbuf, "%u", timestamp);
|
_("<big><b><tt>%s</tt> is not responding.</b></big>\n\n"
|
||||||
|
"<i>You may choose to wait a short while for it to "
|
||||||
argv[0] = METACITY_LIBEXECDIR"/metacity-dialog";
|
"continue or force the application to quit entirely.</i>"),
|
||||||
argv[1] = "--screen";
|
window_title);
|
||||||
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->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_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
|
void
|
||||||
@ -461,9 +232,7 @@ meta_window_free_delete_dialog (MetaWindow *window)
|
|||||||
if (window->dialog_pid >= 0)
|
if (window->dialog_pid >= 0)
|
||||||
{
|
{
|
||||||
kill (window->dialog_pid, 9);
|
kill (window->dialog_pid, 9);
|
||||||
close (window->dialog_pipe);
|
|
||||||
window->dialog_pid = -1;
|
window->dialog_pid = -1;
|
||||||
window->dialog_pipe = -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2416,6 +2416,7 @@ error_on_command (int command_index,
|
|||||||
text,
|
text,
|
||||||
NULL,
|
NULL,
|
||||||
screen_number,
|
screen_number,
|
||||||
|
NULL, NULL, 0,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
|
|
||||||
g_free (text);
|
g_free (text);
|
||||||
@ -2427,6 +2428,7 @@ error_on_command (int command_index,
|
|||||||
message,
|
message,
|
||||||
NULL,
|
NULL,
|
||||||
screen_number,
|
screen_number,
|
||||||
|
NULL, NULL, 0,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <wait.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@ -467,6 +468,29 @@ sigterm_handler (int signum)
|
|||||||
|
|
||||||
exit (meta_exit_code);
|
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
|
* 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)
|
if (setlocale (LC_ALL, "") == NULL)
|
||||||
meta_warning ("Locale not understood by C library, internationalization will not work\n");
|
meta_warning ("Locale not understood by C library, internationalization will not work\n");
|
||||||
|
|
||||||
|
g_type_init ();
|
||||||
|
|
||||||
sigemptyset (&empty_mask);
|
sigemptyset (&empty_mask);
|
||||||
act.sa_handler = SIG_IGN;
|
act.sa_handler = SIG_IGN;
|
||||||
@ -516,6 +542,24 @@ main (int argc, char **argv)
|
|||||||
g_printerr ("Failed to register SIGTERM handler: %s\n",
|
g_printerr ("Failed to register SIGTERM handler: %s\n",
|
||||||
g_strerror (errno));
|
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"))
|
if (g_getenv ("METACITY_VERBOSE"))
|
||||||
meta_set_verbose (TRUE);
|
meta_set_verbose (TRUE);
|
||||||
if (g_getenv ("METACITY_DEBUG"))
|
if (g_getenv ("METACITY_DEBUG"))
|
||||||
|
@ -1737,13 +1737,6 @@ windows_cmp_by_title (MetaWindow *a,
|
|||||||
return g_utf8_collate (a->title, b->title);
|
return g_utf8_collate (a->title, b->title);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int child_pid;
|
|
||||||
int child_pipe;
|
|
||||||
gboolean shutdown;
|
|
||||||
} LameClientsDialogData;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
finish_interact (gboolean shutdown)
|
finish_interact (gboolean shutdown)
|
||||||
{
|
{
|
||||||
@ -1755,63 +1748,26 @@ finish_interact (gboolean shutdown)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static void
|
||||||
io_from_warning_dialog (GIOChannel *channel,
|
sigchld_handler (MetaNexus *nexus, guint arg1, gpointer arg2, gpointer user_data)
|
||||||
GIOCondition condition,
|
|
||||||
gpointer data)
|
|
||||||
{
|
{
|
||||||
LameClientsDialogData *d;
|
gboolean shutdown = GPOINTER_TO_INT (user_data);
|
||||||
|
|
||||||
d = data;
|
if (arg1 == 0) /* pressed "OK" */
|
||||||
|
|
||||||
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))
|
|
||||||
{
|
{
|
||||||
finish_interact (d->shutdown);
|
finish_interact (shutdown);
|
||||||
|
|
||||||
/* Remove the callback, freeing data */
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
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
|
static void
|
||||||
warn_about_lame_clients_and_finish_interact (gboolean shutdown)
|
warn_about_lame_clients_and_finish_interact (gboolean shutdown)
|
||||||
{
|
{
|
||||||
GSList *lame;
|
GSList *lame = NULL;
|
||||||
GSList *windows;
|
GSList *windows;
|
||||||
char **argv;
|
GSList *lame_details = NULL;
|
||||||
int i;
|
|
||||||
GSList *tmp;
|
GSList *tmp;
|
||||||
int len;
|
GSList *columns = NULL;
|
||||||
int child_pid;
|
|
||||||
int child_pipe;
|
|
||||||
GError *err;
|
|
||||||
GIOChannel *channel;
|
|
||||||
LameClientsDialogData *d;
|
|
||||||
guint32 timestamp;
|
|
||||||
char timestampbuf[32];
|
|
||||||
|
|
||||||
lame = NULL;
|
|
||||||
windows = meta_display_list_windows (meta_get_display ());
|
windows = meta_display_list_windows (meta_get_display ());
|
||||||
tmp = windows;
|
tmp = windows;
|
||||||
while (tmp != NULL)
|
while (tmp != NULL)
|
||||||
@ -1838,77 +1794,43 @@ warn_about_lame_clients_and_finish_interact (gboolean shutdown)
|
|||||||
finish_interact (shutdown);
|
finish_interact (shutdown);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
columns = g_slist_prepend (columns, "Window");
|
||||||
|
columns = g_slist_prepend (columns, "Class");
|
||||||
|
|
||||||
lame = g_slist_sort (lame, (GCompareFunc) windows_cmp_by_title);
|
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;
|
tmp = lame;
|
||||||
while (tmp != NULL)
|
while (tmp != NULL)
|
||||||
{
|
{
|
||||||
MetaWindow *w = tmp->data;
|
MetaWindow *w = tmp->data;
|
||||||
|
|
||||||
argv[i] = w->title;
|
lame_details = g_slist_prepend (lame_details,
|
||||||
++i;
|
w->res_class ? w->res_class : "");
|
||||||
argv[i] = w->res_class ? w->res_class : "";
|
lame_details = g_slist_prepend (lame_details,
|
||||||
++i;
|
w->title);
|
||||||
|
|
||||||
tmp = tmp->next;
|
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);
|
g_slist_free (lame);
|
||||||
|
|
||||||
d = g_new0 (LameClientsDialogData, 1);
|
meta_show_dialog("--list",
|
||||||
d->child_pipe = child_pipe;
|
_("These windows do not support "save current setup" "
|
||||||
d->child_pid = child_pid;
|
"and will have to be restarted manually next time "
|
||||||
d->shutdown = shutdown;
|
"you log in."),
|
||||||
|
"240",
|
||||||
channel = g_io_channel_unix_new (d->child_pipe);
|
meta_screen_get_screen_number (meta_get_display()->active_screen),
|
||||||
g_io_add_watch_full (channel, G_PRIORITY_DEFAULT,
|
NULL, NULL,
|
||||||
G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
|
None,
|
||||||
io_from_warning_dialog,
|
columns,
|
||||||
d, g_free);
|
lame_details);
|
||||||
g_io_channel_unref (channel);
|
|
||||||
|
g_slist_free (lame_details);
|
||||||
|
|
||||||
|
g_signal_connect (sigchld_nexus, "sigchld",
|
||||||
|
G_CALLBACK (sigchld_handler),
|
||||||
|
GINT_TO_POINTER (shutdown));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_SM */
|
#endif /* HAVE_SM */
|
||||||
|
116
src/core/util.c
116
src/core/util.c
@ -37,6 +37,8 @@
|
|||||||
#include <X11/Xlib.h> /* must explicitly be included for Solaris; #326746 */
|
#include <X11/Xlib.h> /* must explicitly be included for Solaris; #326746 */
|
||||||
#include <X11/Xutil.h> /* Just for the definition of the various gravities */
|
#include <X11/Xutil.h> /* Just for the definition of the various gravities */
|
||||||
|
|
||||||
|
MetaNexus *sigchld_nexus;
|
||||||
|
|
||||||
#ifdef HAVE_BACKTRACE
|
#ifdef HAVE_BACKTRACE
|
||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
void
|
void
|
||||||
@ -538,35 +540,26 @@ meta_gravity_to_string (int gravity)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
GPid
|
||||||
meta_show_dialog (const char *type,
|
meta_show_dialog (const char *type,
|
||||||
const char *message,
|
const char *message,
|
||||||
const char *timeout,
|
const char *timeout,
|
||||||
const gint screen_number,
|
const gint screen_number,
|
||||||
const char **columns,
|
const char *ok_text,
|
||||||
const char **entries)
|
const char *cancel_text,
|
||||||
|
const int transient_for,
|
||||||
|
GSList *columns,
|
||||||
|
GSList *entries)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
char *screen_number_text = g_strdup_printf("%d", screen_number);
|
char *screen_number_text = g_strdup_printf("%d", screen_number);
|
||||||
|
GSList *tmp;
|
||||||
/*
|
|
||||||
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;
|
|
||||||
int i=0;
|
int i=0;
|
||||||
GPid child_pid;
|
GPid child_pid;
|
||||||
|
const char **argvl = g_malloc(sizeof (char*) *
|
||||||
argvl = g_malloc(sizeof (char*) *
|
(15 +
|
||||||
(9 + (timeout?2:0))
|
g_slist_length (columns)*2 +
|
||||||
);
|
g_slist_length (entries)));
|
||||||
|
|
||||||
argvl[i++] = "zenity";
|
argvl[i++] = "zenity";
|
||||||
argvl[i++] = type;
|
argvl[i++] = type;
|
||||||
@ -584,18 +577,54 @@ zenity --display X --screen S --title Metacity --list --timeout 240 --text "Thes
|
|||||||
argvl[i++] = timeout;
|
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;
|
argvl[i] = NULL;
|
||||||
|
|
||||||
g_spawn_async_with_pipes (
|
if (transient_for)
|
||||||
"/",
|
{
|
||||||
(char**) argvl, /* ugh */
|
gchar *env = g_strdup_printf("%d", transient_for);
|
||||||
NULL,
|
setenv ("WINDOWID", env, 1);
|
||||||
G_SPAWN_SEARCH_PATH,
|
g_free (env);
|
||||||
NULL, NULL,
|
}
|
||||||
&child_pid,
|
|
||||||
NULL, NULL, NULL,
|
g_spawn_async (
|
||||||
&error
|
"/",
|
||||||
);
|
(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 (argvl);
|
||||||
g_free (screen_number_text);
|
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);
|
meta_warning ("%s\n", error->message);
|
||||||
g_error_free (error);
|
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 */
|
/* eof util.c */
|
||||||
|
@ -354,7 +354,6 @@ struct _MetaWindow
|
|||||||
|
|
||||||
/* Current dialog open for this window */
|
/* Current dialog open for this window */
|
||||||
int dialog_pid;
|
int dialog_pid;
|
||||||
int dialog_pipe;
|
|
||||||
|
|
||||||
/* maintained by group.c */
|
/* maintained by group.c */
|
||||||
MetaGroup *group;
|
MetaGroup *group;
|
||||||
|
@ -601,7 +601,6 @@ meta_window_new_with_attrs (MetaDisplay *display,
|
|||||||
window->constructing = TRUE;
|
window->constructing = TRUE;
|
||||||
|
|
||||||
window->dialog_pid = -1;
|
window->dialog_pid = -1;
|
||||||
window->dialog_pipe = -1;
|
|
||||||
|
|
||||||
window->xwindow = xwindow;
|
window->xwindow = xwindow;
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#define META_UTIL_H
|
#define META_UTIL_H
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
gboolean meta_is_verbose (void);
|
gboolean meta_is_verbose (void);
|
||||||
void meta_set_verbose (gboolean setting);
|
void meta_set_verbose (gboolean setting);
|
||||||
@ -97,12 +98,15 @@ char* meta_g_utf8_strndup (const gchar *src, gsize n);
|
|||||||
|
|
||||||
void meta_free_gslist_and_elements (GSList *list_to_deep_free);
|
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 *title,
|
||||||
const char *message,
|
const char *message,
|
||||||
gint timeout,
|
gint timeout,
|
||||||
const char **columns,
|
const char *ok_text,
|
||||||
const char **entries);
|
const char *cancel_text,
|
||||||
|
const int transient_for,
|
||||||
|
GSList *columns,
|
||||||
|
GSList *entries);
|
||||||
|
|
||||||
/* To disable verbose mode, we make these functions into no-ops */
|
/* To disable verbose mode, we make these functions into no-ops */
|
||||||
#ifdef WITH_VERBOSE_MODE
|
#ifdef WITH_VERBOSE_MODE
|
||||||
@ -127,6 +131,36 @@ void meta_show_dialog (const char *type,
|
|||||||
|
|
||||||
#endif /* !WITH_VERBOSE_MODE */
|
#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 */
|
#endif /* META_UTIL_H */
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,438 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/* Metacity dialog process */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2001 Havoc Pennington
|
|
||||||
* Copyright (C) 2004 Elijah Newren
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
||||||
* 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <gtk/gtk.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <libintl.h>
|
|
||||||
#define _(x) dgettext (GETTEXT_PACKAGE, x)
|
|
||||||
#define N_(x) x
|
|
||||||
|
|
||||||
#include <gdk/gdkx.h>
|
|
||||||
#include <X11/Xatom.h>
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
g_printerr (_("Could not parse \"%s\" as an integer"),
|
|
||||||
str);
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*end != '\0')
|
|
||||||
{
|
|
||||||
g_printerr (_("Did not understand trailing characters \"%s\" in string \"%s\""),
|
|
||||||
end, str);
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_realize (GtkWidget *dialog,
|
|
||||||
void *data)
|
|
||||||
{
|
|
||||||
const char *parent_str = data;
|
|
||||||
Window xwindow;
|
|
||||||
|
|
||||||
xwindow = window_from_string (parent_str);
|
|
||||||
|
|
||||||
gdk_error_trap_push ();
|
|
||||||
XSetTransientForHint (gdk_display, GDK_WINDOW_XID (dialog->window),
|
|
||||||
xwindow);
|
|
||||||
XSync (gdk_display, False);
|
|
||||||
gdk_error_trap_pop ();
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
kill_window_question (const char *window_name,
|
|
||||||
const char *parent_str,
|
|
||||||
guint32 timestamp)
|
|
||||||
{
|
|
||||||
GtkWidget *dialog;
|
|
||||||
char *str, *tmp;
|
|
||||||
|
|
||||||
tmp = g_markup_escape_text (window_name, -1);
|
|
||||||
str = g_strdup_printf (_("\"%s\" is not responding."), tmp);
|
|
||||||
g_free (tmp);
|
|
||||||
dialog = gtk_message_dialog_new (NULL, 0,
|
|
||||||
GTK_MESSAGE_WARNING,
|
|
||||||
GTK_BUTTONS_NONE,
|
|
||||||
"<big><b>%s</b></big>\n\n<i>%s</i>",
|
|
||||||
str,
|
|
||||||
_("You may choose to wait a short while "
|
|
||||||
"for it to continue or force the application "
|
|
||||||
"to quit entirely."));
|
|
||||||
g_free (str);
|
|
||||||
gtk_window_set_icon_name (GTK_WINDOW (dialog), "stock_dialog-warning");
|
|
||||||
|
|
||||||
gtk_label_set_use_markup (GTK_LABEL (GTK_MESSAGE_DIALOG (dialog)->label), TRUE);
|
|
||||||
gtk_label_set_line_wrap (GTK_LABEL (GTK_MESSAGE_DIALOG (dialog)->label), TRUE);
|
|
||||||
|
|
||||||
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
|
|
||||||
_("_Wait"),
|
|
||||||
GTK_RESPONSE_REJECT,
|
|
||||||
_("_Force Quit"),
|
|
||||||
GTK_RESPONSE_ACCEPT,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_REJECT);
|
|
||||||
|
|
||||||
g_signal_connect (G_OBJECT (dialog), "realize",
|
|
||||||
G_CALLBACK (on_realize), (char*) parent_str);
|
|
||||||
|
|
||||||
gtk_widget_realize (dialog);
|
|
||||||
gdk_x11_window_set_user_time (dialog->window, timestamp);
|
|
||||||
|
|
||||||
/* return our PID, then window ID that should be killed */
|
|
||||||
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
|
|
||||||
g_print ("%d\n%s\n", (int) getpid (), parent_str);
|
|
||||||
else
|
|
||||||
g_print ("%d\n0x0\n", (int) getpid ());
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char*
|
|
||||||
latin1_to_utf8 (const char *text)
|
|
||||||
{
|
|
||||||
GString *str;
|
|
||||||
const char *p;
|
|
||||||
|
|
||||||
str = g_string_new ("");
|
|
||||||
|
|
||||||
p = text;
|
|
||||||
while (*p)
|
|
||||||
{
|
|
||||||
g_string_append_unichar (str, *p);
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
|
|
||||||
return g_string_free (str, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
COLUMN_TITLE,
|
|
||||||
COLUMN_CLASS,
|
|
||||||
COLUMN_LAST
|
|
||||||
};
|
|
||||||
|
|
||||||
static GtkWidget*
|
|
||||||
create_lame_apps_list (char **lame_apps)
|
|
||||||
{
|
|
||||||
GtkTreeSelection *selection;
|
|
||||||
GtkCellRenderer *cell;
|
|
||||||
GtkWidget *tree_view;
|
|
||||||
GtkTreeViewColumn *column;
|
|
||||||
GtkListStore *model;
|
|
||||||
GtkTreeIter iter;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
model = gtk_list_store_new (COLUMN_LAST,
|
|
||||||
G_TYPE_STRING,
|
|
||||||
G_TYPE_STRING);
|
|
||||||
|
|
||||||
tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
|
|
||||||
|
|
||||||
g_object_unref (G_OBJECT (model));
|
|
||||||
|
|
||||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
|
|
||||||
|
|
||||||
gtk_tree_selection_set_mode (GTK_TREE_SELECTION (selection),
|
|
||||||
GTK_SELECTION_NONE);
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
while (lame_apps[i])
|
|
||||||
{
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
gtk_list_store_append (model, &iter);
|
|
||||||
|
|
||||||
/* window class is latin-1 */
|
|
||||||
s = latin1_to_utf8 (lame_apps[i+1]);
|
|
||||||
|
|
||||||
gtk_list_store_set (model,
|
|
||||||
&iter,
|
|
||||||
COLUMN_TITLE, lame_apps[i],
|
|
||||||
COLUMN_CLASS, s,
|
|
||||||
-1);
|
|
||||||
|
|
||||||
g_free (s);
|
|
||||||
|
|
||||||
i += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
cell = gtk_cell_renderer_text_new ();
|
|
||||||
|
|
||||||
g_object_set (G_OBJECT (cell),
|
|
||||||
"xpad", 2,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
column = gtk_tree_view_column_new_with_attributes (_("Title"),
|
|
||||||
cell,
|
|
||||||
"text", COLUMN_TITLE,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
gtk_tree_view_column_set_sort_column_id (column, COLUMN_TITLE);
|
|
||||||
|
|
||||||
gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view),
|
|
||||||
GTK_TREE_VIEW_COLUMN (column));
|
|
||||||
|
|
||||||
cell = gtk_cell_renderer_text_new ();
|
|
||||||
|
|
||||||
column = gtk_tree_view_column_new_with_attributes (_("Class"),
|
|
||||||
cell,
|
|
||||||
"text", COLUMN_CLASS,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
gtk_tree_view_column_set_sort_column_id (column, COLUMN_CLASS);
|
|
||||||
|
|
||||||
gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view),
|
|
||||||
GTK_TREE_VIEW_COLUMN (column));
|
|
||||||
|
|
||||||
return tree_view;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
warn_about_no_sm_support (char **lame_apps,
|
|
||||||
guint32 timestamp)
|
|
||||||
{
|
|
||||||
GtkWidget *dialog;
|
|
||||||
GtkWidget *list;
|
|
||||||
GtkWidget *sw;
|
|
||||||
GtkWidget *button;
|
|
||||||
|
|
||||||
dialog = gtk_message_dialog_new (NULL,
|
|
||||||
0,
|
|
||||||
GTK_MESSAGE_WARNING,
|
|
||||||
GTK_BUTTONS_NONE,
|
|
||||||
_("These windows do not support \"save current setup\" and will have to be restarted manually next time you log in."));
|
|
||||||
gtk_window_set_icon_name (GTK_WINDOW (dialog), "stock_dialog-warning");
|
|
||||||
|
|
||||||
g_signal_connect (G_OBJECT (dialog),
|
|
||||||
"response",
|
|
||||||
G_CALLBACK (gtk_main_quit),
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
/* Wait 4 minutes then force quit, so we don't wait around all night */
|
|
||||||
g_timeout_add (4 * 60 * 1000, (GSourceFunc) gtk_main_quit, NULL);
|
|
||||||
|
|
||||||
button = gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
|
|
||||||
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE);
|
|
||||||
list = create_lame_apps_list (lame_apps);
|
|
||||||
|
|
||||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
|
||||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
|
|
||||||
GTK_POLICY_AUTOMATIC,
|
|
||||||
GTK_POLICY_AUTOMATIC);
|
|
||||||
gtk_container_set_border_width (GTK_CONTAINER (sw), 3);
|
|
||||||
|
|
||||||
gtk_container_add (GTK_CONTAINER (sw), list);
|
|
||||||
|
|
||||||
/* sw as geometry widget */
|
|
||||||
gtk_window_set_geometry_hints (GTK_WINDOW (dialog),
|
|
||||||
sw, NULL, 0);
|
|
||||||
|
|
||||||
gtk_window_set_resizable (GTK_WINDOW(dialog), TRUE);
|
|
||||||
|
|
||||||
/* applies to geometry widget; try to avoid scrollbars,
|
|
||||||
* but don't make the window huge
|
|
||||||
*/
|
|
||||||
gtk_window_set_default_size (GTK_WINDOW (dialog),
|
|
||||||
400, 225);
|
|
||||||
|
|
||||||
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
|
|
||||||
sw,
|
|
||||||
TRUE, TRUE, 0);
|
|
||||||
|
|
||||||
gtk_window_stick (GTK_WINDOW (dialog));
|
|
||||||
|
|
||||||
gtk_widget_realize (dialog);
|
|
||||||
gdk_x11_window_set_user_time (dialog->window, timestamp);
|
|
||||||
|
|
||||||
gtk_widget_grab_focus (button);
|
|
||||||
gtk_widget_show_all (dialog);
|
|
||||||
|
|
||||||
gtk_main ();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
error_about_command (const char *gconf_key,
|
|
||||||
const char *command,
|
|
||||||
const char *error,
|
|
||||||
guint32 timestamp)
|
|
||||||
{
|
|
||||||
GtkWidget *dialog;
|
|
||||||
|
|
||||||
/* FIXME offer to change the value of the command's gconf key */
|
|
||||||
|
|
||||||
if (*command != '\0')
|
|
||||||
dialog = gtk_message_dialog_new (NULL, 0,
|
|
||||||
GTK_MESSAGE_ERROR,
|
|
||||||
GTK_BUTTONS_CLOSE,
|
|
||||||
_("There was an error running \"%s\":\n"
|
|
||||||
"%s."),
|
|
||||||
command, error);
|
|
||||||
else
|
|
||||||
dialog = gtk_message_dialog_new (NULL, 0,
|
|
||||||
GTK_MESSAGE_ERROR,
|
|
||||||
GTK_BUTTONS_CLOSE,
|
|
||||||
"%s", error);
|
|
||||||
gtk_window_set_icon_name (GTK_WINDOW (dialog), "stock_dialog-error");
|
|
||||||
|
|
||||||
gtk_widget_realize (dialog);
|
|
||||||
gdk_x11_window_set_user_time (dialog->window, timestamp);
|
|
||||||
|
|
||||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
|
||||||
|
|
||||||
gtk_widget_destroy (dialog);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gchar *screen = NULL;
|
|
||||||
static gchar *timestamp_string = NULL;
|
|
||||||
static gboolean isset_kill_window_question = FALSE;
|
|
||||||
static gboolean isset_warn_about_no_sm_support = FALSE;
|
|
||||||
static gboolean isset_command_failed_error = FALSE;
|
|
||||||
static gchar **remaining_args;
|
|
||||||
|
|
||||||
static const GOptionEntry options[] = {
|
|
||||||
{ "screen", 0, 0, G_OPTION_ARG_STRING, &screen, NULL, NULL},
|
|
||||||
{ "timestamp", 0, 0, G_OPTION_ARG_STRING, ×tamp_string, NULL, NULL},
|
|
||||||
{ "kill-window-question", 'k', 0, G_OPTION_ARG_NONE,
|
|
||||||
&isset_kill_window_question, NULL, NULL},
|
|
||||||
{ "warn-about-no-sm-support", 'w', 0, G_OPTION_ARG_NONE,
|
|
||||||
&isset_warn_about_no_sm_support, NULL, NULL},
|
|
||||||
{ "command-failed-error", 'c', 0, G_OPTION_ARG_NONE,
|
|
||||||
&isset_command_failed_error, NULL, NULL},
|
|
||||||
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY,
|
|
||||||
&remaining_args, NULL, NULL},
|
|
||||||
{ NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
int
|
|
||||||
main (int argc, char **argv)
|
|
||||||
{
|
|
||||||
GOptionContext *ctx;
|
|
||||||
guint32 timestamp = 0;
|
|
||||||
gint num_args = 0;
|
|
||||||
|
|
||||||
bindtextdomain (GETTEXT_PACKAGE, METACITY_LOCALEDIR);
|
|
||||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
|
||||||
textdomain (GETTEXT_PACKAGE);
|
|
||||||
|
|
||||||
gtk_init (&argc, &argv);
|
|
||||||
|
|
||||||
ctx = g_option_context_new ("- Dialogs for metacity. "
|
|
||||||
"This program is intented for use by metacity only.");
|
|
||||||
g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE);
|
|
||||||
g_option_context_parse (ctx, &argc, &argv, NULL);
|
|
||||||
g_option_context_free (ctx);
|
|
||||||
|
|
||||||
if (timestamp_string != NULL)
|
|
||||||
{
|
|
||||||
timestamp = strtoul (timestamp_string, NULL, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remaining_args != NULL)
|
|
||||||
{
|
|
||||||
num_args = g_strv_length (remaining_args);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((isset_kill_window_question && isset_warn_about_no_sm_support) ||
|
|
||||||
(isset_kill_window_question && isset_command_failed_error) ||
|
|
||||||
(isset_warn_about_no_sm_support && isset_command_failed_error) ||
|
|
||||||
timestamp == 0)
|
|
||||||
{
|
|
||||||
g_printerr ("bad args to metacity-dialog\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (isset_kill_window_question)
|
|
||||||
{
|
|
||||||
if (num_args < 2)
|
|
||||||
{
|
|
||||||
g_printerr ("bad args to metacity-dialog\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return kill_window_question (remaining_args[0],
|
|
||||||
remaining_args[1], timestamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (isset_warn_about_no_sm_support)
|
|
||||||
{
|
|
||||||
/* argc must be even because we want title-class pairs */
|
|
||||||
if (num_args == 0 || (num_args % 2) != 0)
|
|
||||||
{
|
|
||||||
g_printerr ("bad args to metacity-dialog\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return warn_about_no_sm_support (&remaining_args[0], timestamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (isset_command_failed_error)
|
|
||||||
{
|
|
||||||
/* the args are the gconf key of the failed command, the text of
|
|
||||||
* the command, and the error message
|
|
||||||
*/
|
|
||||||
if (num_args != 3)
|
|
||||||
{
|
|
||||||
g_printerr ("bad args to metacity-dialog\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return error_about_command (remaining_args[0],
|
|
||||||
remaining_args[1], remaining_args[2], timestamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_printerr ("bad args to metacity-dialog\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user