From 4053c92abf16ef8cc8d067868b717c4d896d203d Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Tue, 20 May 2014 14:48:08 -0400 Subject: [PATCH] Rework timestamp pinging If a window temporarily goes unresponsive, and then returns later, we should hide the kill dialog that we showed to the user. --- src/core/delete.c | 127 +++++++++++++++++++------------------ src/core/display-private.h | 15 ++--- src/core/display.c | 63 ++++++------------ src/core/window-private.h | 5 +- 4 files changed, 94 insertions(+), 116 deletions(-) diff --git a/src/core/delete.c b/src/core/delete.c index 759c103ea..2f3e62d8c 100644 --- a/src/core/delete.c +++ b/src/core/delete.c @@ -39,35 +39,58 @@ #include "wayland/meta-wayland-surface.h" -static void meta_window_present_delete_dialog (MetaWindow *window, - guint32 timestamp); - -static void -delete_ping_reply_func (MetaWindow *window, - guint32 timestamp, - void *user_data) -{ - meta_topic (META_DEBUG_PING, "Got reply to delete ping for %s\n", window->desc); - - /* we do nothing */ -} - static void dialog_exited (GPid pid, int status, gpointer user_data) { - MetaWindow *ours = (MetaWindow*) user_data; + MetaWindow *window = user_data; - ours->dialog_pid = -1; + window->dialog_pid = -1; /* exit status of 1 means the user pressed "Force Quit" */ if (WIFEXITED (status) && WEXITSTATUS (status) == 1) - meta_window_kill (ours); + meta_window_kill (window); } static void -delete_ping_timeout_func (MetaWindow *window, - guint32 timestamp, - void *user_data) +present_existing_delete_dialog (MetaWindow *window, + guint32 timestamp) +{ + meta_topic (META_DEBUG_PING, + "Presenting existing ping dialog for %s\n", + window->desc); + + if (window->dialog_pid >= 0) + { + GSList *windows; + GSList *tmp; + + /* Activate transient for window that belongs to + * mutter-dialog + */ + + windows = meta_display_list_windows (window->display, META_LIST_DEFAULT); + tmp = windows; + while (tmp != NULL) + { + MetaWindow *w = tmp->data; + + if (w->transient_for == window && w->res_class && + g_ascii_strcasecmp (w->res_class, "mutter-dialog") == 0) + { + meta_window_activate (w, timestamp); + break; + } + + tmp = tmp->next; + } + + g_slist_free (windows); + } +} + +static void +show_delete_dialog (MetaWindow *window, + guint32 timestamp) { char *window_title; gchar *window_content, *tmp; @@ -79,7 +102,7 @@ delete_ping_timeout_func (MetaWindow *window, if (window->dialog_pid >= 0) { - meta_window_present_delete_dialog (window, timestamp); + present_existing_delete_dialog (window, timestamp); return; } @@ -128,15 +151,33 @@ delete_ping_timeout_func (MetaWindow *window, g_child_watch_add (dialog_pid, dialog_exited, window); } +static void +kill_delete_dialog (MetaWindow *window) +{ + if (window->dialog_pid > -1) + kill (window->dialog_pid, SIGTERM); +} + +void +meta_window_set_alive (MetaWindow *window, + gboolean is_alive) +{ + if (window->is_alive == is_alive) + return; + + window->is_alive = is_alive; + + if (window->is_alive) + kill_delete_dialog (window); + else + show_delete_dialog (window, CurrentTime); +} + void meta_window_check_alive (MetaWindow *window, guint32 timestamp) { - meta_display_ping_window (window, - timestamp, - delete_ping_reply_func, - delete_ping_timeout_func, - NULL); + meta_display_ping_window (window, timestamp); } void @@ -191,39 +232,3 @@ meta_window_free_delete_dialog (MetaWindow *window) window->dialog_pid = -1; } } - -static void -meta_window_present_delete_dialog (MetaWindow *window, guint32 timestamp) -{ - meta_topic (META_DEBUG_PING, - "Presenting existing ping dialog for %s\n", - window->desc); - - if (window->dialog_pid >= 0) - { - GSList *windows; - GSList *tmp; - - /* Activate transient for window that belongs to - * mutter-dialog - */ - - windows = meta_display_list_windows (window->display, META_LIST_DEFAULT); - tmp = windows; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - if (w->transient_for == window && w->res_class && - g_ascii_strcasecmp (w->res_class, "mutter-dialog") == 0) - { - meta_window_activate (w, timestamp); - break; - } - - tmp = tmp->next; - } - - g_slist_free (windows); - } -} diff --git a/src/core/display-private.h b/src/core/display-private.h index b63ca0da9..8dc482593 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -53,10 +53,6 @@ typedef struct _MetaWindowPropHooks MetaWindowPropHooks; typedef struct MetaEdgeResistanceData MetaEdgeResistanceData; -typedef void (* MetaWindowPingFunc) (MetaWindow *window, - guint32 timestamp, - gpointer user_data); - typedef enum { META_LIST_DEFAULT = 0, /* normal windows */ META_LIST_INCLUDE_OVERRIDE_REDIRECT = 1 << 0, /* normal and O-R */ @@ -393,13 +389,10 @@ const char* meta_event_detail_to_string (int d); void meta_display_queue_retheme_all_windows (MetaDisplay *display); void meta_display_retheme_all (void); -void meta_display_ping_window (MetaWindow *window, - guint32 timestamp, - MetaWindowPingFunc ping_reply_func, - MetaWindowPingFunc ping_timeout_func, - void *user_data); -void meta_display_pong_for_serial (MetaDisplay *display, - guint32 serial); +void meta_display_ping_window (MetaWindow *window, + guint32 serial); +void meta_display_pong_for_serial (MetaDisplay *display, + guint32 serial); int meta_resize_gravity_from_grab_op (MetaGrabOp op); diff --git a/src/core/display.c b/src/core/display.c index 193567274..74322506f 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -98,12 +98,9 @@ */ typedef struct { - MetaWindow *window; - guint32 timestamp; - MetaWindowPingFunc ping_reply_func; - MetaWindowPingFunc ping_timeout_func; - void *user_data; - guint ping_timeout_id; + MetaWindow *window; + guint32 serial; + guint ping_timeout_id; } MetaPingData; G_DEFINE_TYPE(MetaDisplay, meta_display, G_TYPE_OBJECT); @@ -2303,15 +2300,16 @@ static gboolean meta_display_ping_timeout (gpointer data) { MetaPingData *ping_data = data; - MetaDisplay *display = ping_data->window->display; + MetaWindow *window = ping_data->window; + MetaDisplay *display = window->display; + + meta_window_set_alive (window, FALSE); ping_data->ping_timeout_id = 0; meta_topic (META_DEBUG_PING, "Ping %u on window %s timed out\n", - ping_data->timestamp, ping_data->window->desc); - - (* ping_data->ping_timeout_func) (ping_data->window, ping_data->timestamp, ping_data->user_data); + ping_data->serial, ping_data->window->desc); display->pending_pings = g_slist_remove (display->pending_pings, ping_data); ping_data_free (ping_data); @@ -2325,11 +2323,6 @@ meta_display_ping_timeout (gpointer data) * @window: The #MetaWindow to send the ping to * @timestamp: The timestamp of the ping. Used for uniqueness. * Cannot be CurrentTime; use a real timestamp! - * @ping_reply_func: The callback to call if we get a response. - * @ping_timeout_func: The callback to call if we don't get a response. - * @user_data: Arbitrary data that will be passed to the callback - * function. (In practice it's often a pointer to - * the window.) * * Sends a ping request to a window. The window must respond to * the request within a certain amount of time. If it does, we @@ -2341,35 +2334,24 @@ meta_display_ping_timeout (gpointer data) * the callbacks will be called from the event loop. */ void -meta_display_ping_window (MetaWindow *window, - guint32 timestamp, - MetaWindowPingFunc ping_reply_func, - MetaWindowPingFunc ping_timeout_func, - gpointer user_data) +meta_display_ping_window (MetaWindow *window, + guint32 serial) { MetaDisplay *display = window->display; MetaPingData *ping_data; - if (timestamp == CurrentTime) + if (serial == 0) { - meta_warning ("Tried to ping a window with CurrentTime! Not allowed.\n"); + meta_warning ("Tried to ping a window with a bad serial! Not allowed.\n"); return; } if (!window->can_ping) - { - if (ping_reply_func) - (* ping_reply_func) (window, timestamp, user_data); - - return; - } + return; ping_data = g_new (MetaPingData, 1); ping_data->window = window; - ping_data->timestamp = timestamp; - ping_data->ping_reply_func = ping_reply_func; - ping_data->ping_timeout_func = ping_timeout_func; - ping_data->user_data = user_data; + ping_data->serial = serial; ping_data->ping_timeout_id = g_timeout_add (PING_TIMEOUT_DELAY, meta_display_ping_timeout, ping_data); @@ -2378,10 +2360,10 @@ meta_display_ping_window (MetaWindow *window, display->pending_pings = g_slist_prepend (display->pending_pings, ping_data); meta_topic (META_DEBUG_PING, - "Sending ping with timestamp %u to window %s\n", - timestamp, window->desc); + "Sending ping with serial %u to window %s\n", + serial, window->desc); - META_WINDOW_GET_CLASS (window)->ping (window, timestamp); + META_WINDOW_GET_CLASS (window)->ping (window, serial); } /** @@ -2405,11 +2387,11 @@ meta_display_pong_for_serial (MetaDisplay *display, { MetaPingData *ping_data = tmp->data; - if (serial == ping_data->timestamp) + if (serial == ping_data->serial) { meta_topic (META_DEBUG_PING, "Matching ping found for pong %u\n", - ping_data->timestamp); + ping_data->serial); /* Remove the ping data from the list */ display->pending_pings = g_slist_remove (display->pending_pings, @@ -2422,13 +2404,8 @@ meta_display_pong_for_serial (MetaDisplay *display, ping_data->ping_timeout_id = 0; } - /* Call callback */ - (* ping_data->ping_reply_func) (ping_data->window, - ping_data->timestamp, - ping_data->user_data); - + meta_window_set_alive (ping_data->window, TRUE); ping_data_free (ping_data); - break; } } diff --git a/src/core/window-private.h b/src/core/window-private.h index 14f4a67a8..cf26b7f2e 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -441,8 +441,9 @@ struct _MetaWindow MetaStackLayer layer; int stack_position; /* see comment in stack.h */ - /* Current dialog open for this window */ + /* Managed by delete.c */ int dialog_pid; + guint is_alive : 1; /* maintained by group.c */ MetaGroup *group; @@ -739,4 +740,6 @@ void meta_window_move_resize_internal (MetaWindow *window, void meta_window_grab_op_began (MetaWindow *window, MetaGrabOp op); void meta_window_grab_op_ended (MetaWindow *window, MetaGrabOp op); +void meta_window_set_alive (MetaWindow *window, gboolean is_alive); + #endif