From 044d8999a33f2cc36de36e5ccd03cdadc89b368c Mon Sep 17 00:00:00 2001 From: Elijah Newren Date: Thu, 26 Aug 2004 00:59:12 +0000 Subject: [PATCH] Make dialogs that Metacity shows follow focus-stealing-prevention 2004-08-25 Elijah Newren Make dialogs that Metacity shows follow focus-stealing-prevention conventions. (fixes one issue in #149028; see comments 47-54) * src/delete.c (delete_ping_reply_func, delete_ping_timeout_func): Make callback functions take a timestamp arg, (delete_ping_timeout_func): pass the timestamp to metacity-dialog * src/display.c (meta_display_ping_timeout): add a timestamp to the call to the ping_timeout_func, (meta_display_ping_window, process_pong_message): add a timestamp to the call to the ping_reply_func * src/display.h (MetaWindowPingFunc typedef): add a timestamp to this function typedef * src/keybindings.c (error_on_command): require a timestamp and pass the timestamp on to metacity-dialog, (handle_run_command): pass a timestamp to error_on_command * src/metacity-dialog.c (copy_of_gdk_x11_window_set_user_time): new function (temporary; only for use while using gtk+-2.4), (kill_window_question, warn_about_no_sm_support, error_about_command): make these functions take a timestamp and call copy_of_gdk_x11_window_set_user_time, (main): require the first two args to the program to be "--timestamp " * src/session.c (warn_about_lame_clients_and_finish_inter): pass a timestamp of 0 to metacity-dialog to prevent focus (it's a popup not generated by and kind of user request). --- ChangeLog | 33 +++++++++++++++++++ src/delete.c | 16 +++++++--- src/display.c | 8 +++-- src/display.h | 1 + src/keybindings.c | 23 ++++++++------ src/metacity-dialog.c | 73 ++++++++++++++++++++++++++++++++++--------- src/session.c | 10 ++++++ 7 files changed, 133 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index e8fba2f67..b0025934f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +2004-08-25 Elijah Newren + + Make dialogs that Metacity shows follow focus-stealing-prevention + conventions. (fixes one issue in #149028; see comments 47-54) + + * src/delete.c (delete_ping_reply_func, + delete_ping_timeout_func): Make callback functions take a + timestamp arg, (delete_ping_timeout_func): pass the timestamp to + metacity-dialog + + * src/display.c (meta_display_ping_timeout): add a timestamp to + the call to the ping_timeout_func, (meta_display_ping_window, + process_pong_message): add a timestamp to the call to the + ping_reply_func + + * src/display.h (MetaWindowPingFunc typedef): add a timestamp to + this function typedef + + * src/keybindings.c (error_on_command): require a timestamp and + pass the timestamp on to metacity-dialog, (handle_run_command): + pass a timestamp to error_on_command + + * src/metacity-dialog.c (copy_of_gdk_x11_window_set_user_time): + new function (temporary; only for use while using gtk+-2.4), + (kill_window_question, warn_about_no_sm_support, + error_about_command): make these functions take a timestamp and + call copy_of_gdk_x11_window_set_user_time, (main): require the + first two args to the program to be "--timestamp " + + * src/session.c (warn_about_lame_clients_and_finish_inter): pass a + timestamp of 0 to metacity-dialog to prevent focus (it's a popup + not generated by and kind of user request). + Fri Aug 20 12:54:12 2004 Soeren Sandmann * src/display.c (meta_display_end_grab_op): Move wireframe code diff --git a/src/delete.c b/src/delete.c index 881352bd5..c210b39a3 100644 --- a/src/delete.c +++ b/src/delete.c @@ -38,6 +38,7 @@ static void meta_window_present_delete_dialog (MetaWindow *window); static void delete_ping_reply_func (MetaDisplay *display, Window xwindow, + Time timestamp, void *user_data) { meta_topic (META_DEBUG_PING, @@ -290,14 +291,16 @@ io_from_ping_dialog (GIOChannel *channel, static void delete_ping_timeout_func (MetaDisplay *display, Window xwindow, + Time timestamp, void *user_data) { MetaWindow *window = user_data; GError *err; int child_pid; int outpipe; - char *argv[7]; + char *argv[9]; char numbuf[32]; + char timestampbuf[32]; char *window_id_str; GIOChannel *channel; @@ -314,14 +317,17 @@ delete_ping_timeout_func (MetaDisplay *display, window_id_str = g_strdup_printf ("0x%lx", window->xwindow); sprintf (numbuf, "%d", window->screen->number); + sprintf (timestampbuf, "%lu", timestamp); argv[0] = METACITY_LIBEXECDIR"/metacity-dialog"; argv[1] = "--screen"; argv[2] = numbuf; - argv[3] = "--kill-window-question"; - argv[4] = window->title; - argv[5] = window_id_str; - argv[6] = NULL; + 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 ("/", diff --git a/src/display.c b/src/display.c index e5cd7e438..4c1890d49 100644 --- a/src/display.c +++ b/src/display.c @@ -3675,7 +3675,7 @@ meta_display_ping_timeout (gpointer data) ping_data->timestamp, ping_data->xwindow); (* ping_data->ping_timeout_func) (ping_data->display, ping_data->xwindow, - ping_data->user_data); + ping_data->timestamp, ping_data->user_data); ping_data->display->pending_pings = g_slist_remove (ping_data->display->pending_pings, @@ -3704,7 +3704,7 @@ meta_display_ping_window (MetaDisplay *display, if (!window->net_wm_ping) { if (ping_reply_func) - (* ping_reply_func) (display, window->xwindow, user_data); + (* ping_reply_func) (display, window->xwindow, timestamp, user_data); return; } @@ -3830,7 +3830,9 @@ process_pong_message (MetaDisplay *display, } /* Call callback */ - (* ping_data->ping_reply_func) (display, ping_data->xwindow, + (* ping_data->ping_reply_func) (display, + ping_data->xwindow, + ping_data->timestamp, ping_data->user_data); ping_data_free (ping_data); diff --git a/src/display.h b/src/display.h index a81445c8a..8b93253d4 100644 --- a/src/display.h +++ b/src/display.h @@ -69,6 +69,7 @@ typedef struct _MetaGroupPropHooks MetaGroupPropHooks; typedef void (* MetaWindowPingFunc) (MetaDisplay *display, Window xwindow, + Time timestamp, gpointer user_data); diff --git a/src/keybindings.c b/src/keybindings.c index 9039e96a6..19316a2d7 100644 --- a/src/keybindings.c +++ b/src/keybindings.c @@ -2486,12 +2486,14 @@ static void error_on_command (int command_index, const char *command, const char *message, - int screen_number) + int screen_number, + Time timestamp) { GError *err; - char *argv[8]; + char *argv[10]; char *key; char numbuf[32]; + char timestampbuf[32]; meta_warning ("Error on command %d \"%s\": %s\n", command_index, command, message); @@ -2499,15 +2501,18 @@ error_on_command (int command_index, key = meta_prefs_get_gconf_key_for_command (command_index); sprintf (numbuf, "%d", screen_number); + sprintf (timestampbuf, "%lu", timestamp); argv[0] = METACITY_LIBEXECDIR"/metacity-dialog"; argv[1] = "--screen"; argv[2] = numbuf; - argv[3] = "--command-failed-error"; - argv[4] = key; - argv[5] = (char*) (command ? command : ""); - argv[6] = (char*) message; - argv[7] = NULL; + argv[3] = "--timestamp"; + argv[4] = timestampbuf; + argv[5] = "--command-failed-error"; + argv[6] = key; + argv[7] = (char*) (command ? command : ""); + argv[8] = (char*) message; + argv[9] = NULL; err = NULL; if (!g_spawn_async_with_pipes ("/", @@ -2596,7 +2601,7 @@ handle_run_command (MetaDisplay *display, s = g_strdup_printf (_("No command %d has been defined.\n"), which + 1); - error_on_command (which, NULL, s, screen->number); + error_on_command (which, NULL, s, screen->number, event->xkey.time); g_free (s); return; @@ -2605,7 +2610,7 @@ handle_run_command (MetaDisplay *display, err = NULL; if (!meta_spawn_command_line_async_on_screen (command, screen, &err)) { - error_on_command (which, command, err->message, screen->number); + error_on_command (which, command, err->message, screen->number, event->xkey.time); g_error_free (err); } diff --git a/src/metacity-dialog.c b/src/metacity-dialog.c index 73ab2386c..47a309070 100644 --- a/src/metacity-dialog.c +++ b/src/metacity-dialog.c @@ -30,6 +30,30 @@ #define N_(x) x #include +#include + +/* FIXME: When we switch to gtk+-2.6, use of this function should be + * replaced by using the real gdk_x11_window_set_user_time. + */ +static void +copy_of_gdk_x11_window_set_user_time (GdkWindow *window, + Time timestamp) +{ + GdkDisplay *display; + + g_return_if_fail (window != NULL); + g_return_if_fail (GDK_IS_WINDOW (window)); + + if (GDK_WINDOW_DESTROYED (window)) + return; + + display = gdk_drawable_get_display (window); + + XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), + gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_USER_TIME"), + XA_CARDINAL, 32, PropModeReplace, + (guchar *)×tamp, 1); +} static Window window_from_string (const char *str) @@ -76,7 +100,8 @@ on_realize (GtkWidget *dialog, static int kill_window_question (const char *window_name, - const char *parent_str) + const char *parent_str, + Time timestamp) { GtkWidget *dialog; char *str, *tmp; @@ -109,6 +134,9 @@ kill_window_question (const char *window_name, g_signal_connect (G_OBJECT (dialog), "realize", G_CALLBACK (on_realize), (char*) parent_str); + gtk_widget_realize (dialog); + copy_of_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); @@ -220,7 +248,8 @@ create_lame_apps_list (char **lame_apps) } static int -warn_about_no_sm_support (char **lame_apps) +warn_about_no_sm_support (char **lame_apps, + Time timestamp) { GtkWidget *dialog; GtkWidget *list; @@ -267,6 +296,9 @@ warn_about_no_sm_support (char **lame_apps) sw, TRUE, TRUE, 0); + gtk_widget_realize (dialog); + copy_of_gdk_x11_window_set_user_time (dialog->window, timestamp); + gtk_widget_show_all (dialog); gtk_main (); @@ -277,7 +309,8 @@ warn_about_no_sm_support (char **lame_apps) static int error_about_command (const char *gconf_key, const char *command, - const char *error) + const char *error, + Time timestamp) { GtkWidget *dialog; @@ -296,6 +329,9 @@ error_about_command (const char *gconf_key, GTK_BUTTONS_CLOSE, "%s", error); + gtk_widget_realize (dialog); + copy_of_gdk_x11_window_set_user_time (dialog->window, timestamp); + gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); @@ -306,52 +342,61 @@ error_about_command (const char *gconf_key, int main (int argc, char **argv) { + Time timestamp; + bindtextdomain (GETTEXT_PACKAGE, METACITY_LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); gtk_init (&argc, &argv); - if (argc < 2) + if (argc < 4) { g_printerr ("bad args to metacity-dialog\n"); return 1; } - - if (strcmp (argv[1], "--kill-window-question") == 0) + + if (strcmp (argv[1], "--timestamp") != 0) { - if (argc < 4) + g_printerr ("bad args to metacity-dialog\n"); + return 1; + } + timestamp = strtoul (argv[2], NULL, 10); + + if (strcmp (argv[3], "--kill-window-question") == 0) + { + if (argc < 6) { g_printerr ("bad args to metacity-dialog\n"); return 1; } - return kill_window_question (argv[2], argv[3]); + return kill_window_question (argv[4], argv[5], timestamp); } - else if (strcmp (argv[1], "--warn-about-no-sm-support") == 0) + else if (strcmp (argv[3], "--warn-about-no-sm-support") == 0) { /* argc must be even because we want title-class pairs */ - if (argc < 3 || (argc % 2) != 0) + if (argc < 5 || (argc % 2) != 0) { g_printerr ("bad args to metacity-dialog\n"); return 1; } - return warn_about_no_sm_support (&argv[2]); + return warn_about_no_sm_support (&argv[4], timestamp); } - else if (strcmp (argv[1], "--command-failed-error") == 0) + else if (strcmp (argv[3], "--command-failed-error") == 0) { /* the args are the gconf key of the failed command, the text of * the command, and the error message */ - if (argc != 5) + if (argc != 7) { g_printerr ("bad args to metacity-dialog\n"); return 1; } - return error_about_command (argv[2], argv[3], argv[4]); + return error_about_command (argv[4], argv[5], argv[6], timestamp); } g_printerr ("bad args to metacity-dialog\n"); diff --git a/src/session.c b/src/session.c index afb0a674e..5dbce1c72 100644 --- a/src/session.c +++ b/src/session.c @@ -1851,6 +1851,8 @@ warn_about_lame_clients_and_finish_interact (gboolean shutdown) GError *err; GIOChannel *channel; LameClientsDialogData *d; + Time timestamp; + char timestampbuf[32]; lame = NULL; displays = meta_displays_list (); @@ -1893,8 +1895,12 @@ warn_about_lame_clients_and_finish_interact (gboolean shutdown) lame = g_slist_sort (lame, (GCompareFunc) windows_cmp_by_title); + timestamp = 0; + sprintf (timestampbuf, "%lu", 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 */ @@ -1904,6 +1910,10 @@ warn_about_lame_clients_and_finish_interact (gboolean shutdown) argv[i] = METACITY_LIBEXECDIR"/metacity-dialog"; ++i; + argv[i] = "--timestamp"; + ++i; + argv[i] = timestampbuf; + ++i; argv[i] = "--warn-about-no-sm-support"; ++i;