[mutter/wayland] Revert "Move window pings to MetaWindow"
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wayland] Revert "Move window pings to MetaWindow"
- Date: Sun, 16 Feb 2014 15:22:20 +0000 (UTC)
commit a66060e21aeb215feae57c79b4a75774482bd03e
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Sat Feb 15 11:33:12 2014 -0500
Revert "Move window pings to MetaWindow"
This was a bad idea, as ping/pong has moved to a client-specific
request/event pair, rather than a surface-specific one. Revert
the changes we made here and correct the code to make up for it.
This reverts commit aa3643cdde4277a26e5730a0f6335c76a1a22d4f.
src/core/delete.c | 10 +-
src/core/display-private.h | 14 ++-
src/core/display.c | 260 +++++++++++++++++++++++++++++++++++-
src/core/window-private.h | 13 --
src/core/window.c | 214 -----------------------------
src/wayland/meta-wayland-surface.c | 4 +-
6 files changed, 274 insertions(+), 241 deletions(-)
---
diff --git a/src/core/delete.c b/src/core/delete.c
index a24c1b9..9cfa715 100644
--- a/src/core/delete.c
+++ b/src/core/delete.c
@@ -132,11 +132,11 @@ void
meta_window_check_alive (MetaWindow *window,
guint32 timestamp)
{
- meta_window_ping (window,
- timestamp,
- delete_ping_reply_func,
- delete_ping_timeout_func,
- NULL);
+ meta_display_ping_window (window,
+ timestamp,
+ delete_ping_reply_func,
+ delete_ping_timeout_func,
+ NULL);
}
void
diff --git a/src/core/display-private.h b/src/core/display-private.h
index 4d86eae..11b3a60 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -55,6 +55,10 @@ 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 */
@@ -183,7 +187,7 @@ struct _MetaDisplay
guint32 window_sequence_counter;
/* Pings which we're waiting for a reply from */
- GHashTable *pending_pings;
+ GSList *pending_pings;
/* Pending focus change */
guint focus_timeout_id;
@@ -449,6 +453,14 @@ void meta_display_retheme_all (void);
void meta_display_set_cursor_theme (const char *theme,
int size);
+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);
+
int meta_resize_gravity_from_grab_op (MetaGrabOp op);
gboolean meta_grab_op_is_moving (MetaGrabOp op);
diff --git a/src/core/display.c b/src/core/display.c
index 4ecf6db..8854e79 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -82,6 +82,40 @@
g == META_GRAB_OP_KEYBOARD_ESCAPING_DOCK || \
g == META_GRAB_OP_KEYBOARD_ESCAPING_GROUP)
+/*
+ * SECTION:pings
+ *
+ * Sometimes we want to see whether a window is responding,
+ * so we send it a "ping" message and see whether it sends us back a "pong"
+ * message within a reasonable time. Here we have a system which lets us
+ * nominate one function to be called if we get the pong in time and another
+ * function if we don't. The system is rather more complicated than it needs
+ * to be, since we only ever use it to destroy windows which are asked to
+ * close themselves and don't do so within a reasonable amount of time, and
+ * therefore we always use the same callbacks. It's possible that we might
+ * use it for other things in future, or on the other hand we might decide
+ * that we're never going to do so and simplify it a bit.
+ */
+
+/**
+ * MetaPingData:
+ *
+ * Describes a ping on a window. When we send a ping to a window, we build
+ * one of these structs, and it eventually gets passed to the timeout function
+ * or to the function which handles the response from the window. If the window
+ * does or doesn't respond to the ping, we use this information to deal with
+ * these facts; we have a handler function for each.
+ */
+typedef struct
+{
+ MetaWindow *window;
+ guint32 timestamp;
+ MetaWindowPingFunc ping_reply_func;
+ MetaWindowPingFunc ping_timeout_func;
+ void *user_data;
+ guint ping_timeout_id;
+} MetaPingData;
+
G_DEFINE_TYPE(MetaDisplay, meta_display, G_TYPE_OBJECT);
/* Signals */
@@ -283,6 +317,62 @@ meta_display_class_init (MetaDisplayClass *klass)
G_PARAM_READABLE));
}
+
+/**
+ * ping_data_free:
+ *
+ * Destructor for #MetaPingData structs. Will destroy the
+ * event source for the struct as well.
+ */
+static void
+ping_data_free (MetaPingData *ping_data)
+{
+ /* Remove the timeout */
+ if (ping_data->ping_timeout_id != 0)
+ g_source_remove (ping_data->ping_timeout_id);
+
+ g_free (ping_data);
+}
+
+/**
+ * remove_pending_pings_for_window:
+ * @display: The display the window appears on
+ * @xwindow: The X ID of the window whose pings we should remove
+ *
+ * Frees every pending ping structure for the given X window on the
+ * given display. This means that we also destroy the timeouts.
+ */
+static void
+remove_pending_pings_for_window (MetaDisplay *display, Window xwindow)
+{
+ GSList *tmp;
+ GSList *dead;
+
+ /* could obviously be more efficient, don't care */
+
+ /* build list to be removed */
+ dead = NULL;
+ for (tmp = display->pending_pings; tmp; tmp = tmp->next)
+ {
+ MetaPingData *ping_data = tmp->data;
+
+ if (ping_data->window->xwindow == xwindow)
+ dead = g_slist_prepend (dead, ping_data);
+ }
+
+ /* remove what we found */
+ for (tmp = dead; tmp; tmp = tmp->next)
+ {
+ MetaPingData *ping_data = tmp->data;
+
+ display->pending_pings = g_slist_remove (display->pending_pings, ping_data);
+ ping_data_free (ping_data);
+ }
+
+ g_slist_free (dead);
+}
+
+
#ifdef HAVE_STARTUP_NOTIFICATION
static void
sn_error_trap_push (SnDisplay *sn_display,
@@ -433,6 +523,7 @@ meta_display_open (void)
the_display->server_grab_count = 0;
the_display->display_opening = TRUE;
+ the_display->pending_pings = NULL;
the_display->autoraise_timeout_id = 0;
the_display->autoraise_window = NULL;
the_display->focus_window = NULL;
@@ -504,7 +595,6 @@ meta_display_open (void)
the_display->xids = g_hash_table_new (meta_unsigned_long_hash,
meta_unsigned_long_equal);
- the_display->pending_pings = g_hash_table_new (g_int_hash, g_int_equal);
the_display->wayland_windows = g_hash_table_new (NULL, NULL);
i = 0;
@@ -3056,12 +3146,8 @@ handle_other_xevent (MetaDisplay *display,
if ((Atom)event->xclient.data.l[0] == display->atom__NET_WM_PING)
{
guint32 timestamp = event->xclient.data.l[1];
- window = g_hash_table_lookup (display->pending_pings, ×tamp);
- if (window)
- meta_window_pong (window, timestamp);
- else
- meta_verbose ("Received invalid _NET_WM_PING for unknown timestamp %d\n", timestamp);
+ meta_display_pong_for_serial (display, timestamp);
/* We don't want ping reply events going into
* the GTK+ event loop because gtk+ will treat
@@ -3970,6 +4056,9 @@ meta_display_unregister_x_window (MetaDisplay *display,
g_return_if_fail (g_hash_table_lookup (display->xids, &xwindow) != NULL);
g_hash_table_remove (display->xids, &xwindow);
+
+ /* Remove any pending pings */
+ remove_pending_pings_for_window (display, xwindow);
}
void
@@ -4818,6 +4907,115 @@ meta_set_syncing (gboolean setting)
}
}
+/*
+ * How long, in milliseconds, we should wait after pinging a window
+ * before deciding it's not going to get back to us.
+ */
+#define PING_TIMEOUT_DELAY 5000
+
+/**
+ * meta_display_ping_timeout:
+ * @data: All the information about this ping. It is a #MetaPingData
+ * cast to a #gpointer in order to be passable to a timeout function.
+ * This function will also free this parameter.
+ *
+ * Does whatever it is we decided to do when a window didn't respond
+ * to a ping. We also remove the ping from the display's list of
+ * pending pings. This function is called by the event loop when the timeout
+ * times out which we created at the start of the ping.
+ *
+ * Returns: Always returns %FALSE, because this function is called as a
+ * timeout and we don't want to run the timer again.
+ */
+static gboolean
+meta_display_ping_timeout (gpointer data)
+{
+ MetaPingData *ping_data = data;
+ MetaDisplay *display = ping_data->window->display;
+
+ 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);
+
+ display->pending_pings = g_slist_remove (display->pending_pings, ping_data);
+ ping_data_free (ping_data);
+
+ return FALSE;
+}
+
+/**
+ * meta_display_ping_window:
+ * @display: The #MetaDisplay that the window is on
+ * @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
+ * will call one callback; if the time passes and we haven't had
+ * a response, we call a different callback. The window must have
+ * the hint showing that it can respond to a ping; if it doesn't,
+ * we call the "got a response" callback immediately and return.
+ * This function returns straight away after setting things up;
+ * 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)
+{
+ MetaDisplay *display = window->display;
+ MetaPingData *ping_data;
+
+ if (timestamp == CurrentTime)
+ {
+ meta_warning ("Tried to ping a window with CurrentTime! Not allowed.\n");
+ return;
+ }
+
+ if (!window->net_wm_ping)
+ {
+ if (ping_reply_func)
+ (* ping_reply_func) (window, timestamp, user_data);
+
+ 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->ping_timeout_id = g_timeout_add (PING_TIMEOUT_DELAY,
+ meta_display_ping_timeout,
+ ping_data);
+
+ 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);
+
+ if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
+ meta_window_send_icccm_message (window,
+ display->atom__NET_WM_PING,
+ timestamp);
+ else
+ meta_wayland_surface_ping (window->surface, timestamp);
+}
+
static void
process_request_frame_extents (MetaDisplay *display,
XEvent *event)
@@ -4878,6 +5076,56 @@ process_request_frame_extents (MetaDisplay *display,
meta_XFree (hints);
}
+/**
+ * meta_display_pong_for_serial:
+ * @display: the display we got the pong from
+ * @serial: the serial in the pong repsonse
+ *
+ * Process the pong (the response message) from the ping we sent
+ * to the window. This involves removing the timeout, calling the
+ * reply handler function, and freeing memory.
+ */
+void
+meta_display_pong_for_serial (MetaDisplay *display,
+ guint32 serial)
+{
+ GSList *tmp;
+
+ meta_topic (META_DEBUG_PING, "Received a pong with serial %u\n", serial);
+
+ for (tmp = display->pending_pings; tmp; tmp = tmp->next)
+ {
+ MetaPingData *ping_data = tmp->data;
+
+ if (serial == ping_data->timestamp)
+ {
+ meta_topic (META_DEBUG_PING,
+ "Matching ping found for pong %u\n",
+ ping_data->timestamp);
+
+ /* Remove the ping data from the list */
+ display->pending_pings = g_slist_remove (display->pending_pings,
+ ping_data);
+
+ /* Remove the timeout */
+ if (ping_data->ping_timeout_id != 0)
+ {
+ g_source_remove (ping_data->ping_timeout_id);
+ ping_data->ping_timeout_id = 0;
+ }
+
+ /* Call callback */
+ (* ping_data->ping_reply_func) (ping_data->window,
+ ping_data->timestamp,
+ ping_data->user_data);
+
+ ping_data_free (ping_data);
+
+ break;
+ }
+ }
+}
+
MetaGroup*
get_focussed_group (MetaDisplay *display)
{
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 27ffc92..bcac505 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -467,8 +467,6 @@ struct _MetaWindow
/* Bypass compositor hints */
guint bypass_compositor;
-
- GSList *pending_pings;
};
struct _MetaWindowClass
@@ -744,17 +742,6 @@ void meta_window_handle_enter (MetaWindow *window,
void meta_window_set_surface_mapped (MetaWindow *window,
gboolean surface_mapped);
-typedef void (* MetaWindowPingFunc) (MetaWindow *window,
- guint32 timestamp,
- gpointer user_data);
-
-void meta_window_ping (MetaWindow *window,
- guint32 timestamp,
- MetaWindowPingFunc ping_reply_func,
- MetaWindowPingFunc ping_timeout_func,
- void *user_data);
-void meta_window_pong (MetaWindow *window,
- guint32 timestamp);
Window meta_window_get_toplevel_xwindow (MetaWindow *window);
void meta_window_activate_full (MetaWindow *window,
diff --git a/src/core/window.c b/src/core/window.c
index 0746817..ccd1749 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -69,26 +69,6 @@
static int destroying_windows_disallowed = 0;
-/**
- * MetaPingData:
- *
- * Describes a ping on a window. When we send a ping to a window, we build
- * one of these structs, and it eventually gets passed to the timeout function
- * or to the function which handles the response from the window. If the window
- * does or doesn't respond to the ping, we use this information to deal with
- * these facts; we have a handler function for each.
- */
-typedef struct
-{
- MetaWindow *window;
- guint32 timestamp;
- MetaWindowPingFunc ping_reply_func;
- MetaWindowPingFunc ping_timeout_func;
- void *user_data;
- guint ping_timeout_id;
-} MetaPingData;
-
-static void ping_data_free (MetaPingData *ping_data);
static void update_sm_hints (MetaWindow *window);
static void update_net_frame_extents (MetaWindow *window);
@@ -1783,8 +1763,6 @@ meta_window_unmanage (MetaWindow *window,
else
meta_display_unregister_wayland_window (window->display, window);
- g_slist_free_full (window->pending_pings, (GDestroyNotify) ping_data_free);
-
meta_prefs_remove_listener (prefs_changed_callback, window);
meta_screen_queue_check_fullscreen (window->screen);
@@ -10613,198 +10591,6 @@ meta_window_set_surface_mapped (MetaWindow *window,
meta_window_queue (window, META_QUEUE_CALC_SHOWING);
}
-/*
- * SECTION:pings
- *
- * Sometimes we want to see whether a window is responding,
- * so we send it a "ping" message and see whether it sends us back a "pong"
- * message within a reasonable time. Here we have a system which lets us
- * nominate one function to be called if we get the pong in time and another
- * function if we don't. The system is rather more complicated than it needs
- * to be, since we only ever use it to destroy windows which are asked to
- * close themselves and don't do so within a reasonable amount of time, and
- * therefore we always use the same callbacks. It's possible that we might
- * use it for other things in future, or on the other hand we might decide
- * that we're never going to do so and simplify it a bit.
- */
-
-/**
- * ping_data_free:
- *
- * Destructor for #MetaPingData structs. Will destroy the
- * event source for the struct as well.
- */
-static void
-ping_data_free (MetaPingData *ping_data)
-{
- MetaWindow *window = ping_data->window;
- MetaDisplay *display = window->display;
-
- /* Remove the timeout */
- if (ping_data->ping_timeout_id != 0)
- g_source_remove (ping_data->ping_timeout_id);
-
- g_hash_table_remove (display->pending_pings, &ping_data->timestamp);
-
- g_free (ping_data);
-}
-
-/**
- * meta_window_pong:
- * @window: the window we got the pong on
- * @timestamp: the timestamp that the client sent back
- *
- * Process the pong (the response message) from the ping we sent
- * to the window. This involves removing the timeout, calling the
- * reply handler function, and freeing memory.
- */
-void
-meta_window_pong (MetaWindow *window,
- guint32 timestamp)
-{
- GSList *tmp;
-
- meta_topic (META_DEBUG_PING, "Received a pong with timestamp %u\n",
- timestamp);
-
- for (tmp = window->pending_pings; tmp; tmp = tmp->next)
- {
- MetaPingData *ping_data = tmp->data;
-
- if (timestamp == ping_data->timestamp)
- {
- meta_topic (META_DEBUG_PING,
- "Matching ping found for pong %u\n",
- ping_data->timestamp);
-
- /* Remove the ping data from the list */
- window->pending_pings = g_slist_remove (window->pending_pings, ping_data);
-
- /* Remove the timeout */
- if (ping_data->ping_timeout_id != 0)
- {
- g_source_remove (ping_data->ping_timeout_id);
- ping_data->ping_timeout_id = 0;
- }
-
- /* Call callback */
- (* ping_data->ping_reply_func) (window,
- ping_data->timestamp,
- ping_data->user_data);
-
- ping_data_free (ping_data);
-
- break;
- }
- }
-}
-
-/*
- * How long, in milliseconds, we should wait after pinging a window
- * before deciding it's not going to get back to us.
- */
-#define PING_TIMEOUT_DELAY 5000
-
-/**
- * ping_timeout:
- * @data: All the information about this ping. It is a #MetaPingData
- * cast to a #gpointer in order to be passable to a timeout function.
- * This function will also free this parameter.
- *
- * Does whatever it is we decided to do when a window didn't respond
- * to a ping. We also remove the ping from the display's list of
- * pending pings. This function is called by the event loop when the timeout
- * times out which we created at the start of the ping.
- *
- * Returns: Always returns %FALSE, because this function is called as a
- * timeout and we don't want to run the timer again.
- */
-static gboolean
-ping_timeout (gpointer data)
-{
- MetaPingData *ping_data;
-
- ping_data = data;
-
- 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_free (ping_data);
-
- return FALSE;
-}
-
-/**
- * meta_window_ping:
- * @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
- * will call one callback; if the time passes and we haven't had
- * a response, we call a different callback. The window must have
- * the hint showing that it can respond to a ping; if it doesn't,
- * we call the "got a response" callback immediately and return.
- * This function returns straight away after setting things up;
- * the callbacks will be called from the event loop.
- */
-void
-meta_window_ping (MetaWindow *window,
- guint32 timestamp,
- MetaWindowPingFunc ping_reply_func,
- MetaWindowPingFunc ping_timeout_func,
- gpointer user_data)
-{
- MetaPingData *ping_data;
- MetaDisplay *display = window->display;
-
- if (timestamp == CurrentTime)
- {
- meta_warning ("Tried to ping a window with CurrentTime! Not allowed.\n");
- return;
- }
-
- if (!window->net_wm_ping)
- {
- if (ping_reply_func)
- (* ping_reply_func) (window, timestamp, user_data);
-
- 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->ping_timeout_id = g_timeout_add (PING_TIMEOUT_DELAY, ping_timeout, ping_data);
-
- window->pending_pings = g_slist_prepend (window->pending_pings, ping_data);
-
- g_hash_table_insert (display->pending_pings, &ping_data->timestamp, window);
-
- meta_topic (META_DEBUG_PING,
- "Sending ping with timestamp %u to window %s\n",
- timestamp, window->desc);
-
- if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
- meta_window_send_icccm_message (window, display->atom__NET_WM_PING, timestamp);
- else
- meta_wayland_surface_ping (window->surface, timestamp);
-}
-
Window
meta_window_get_toplevel_xwindow (MetaWindow *window)
{
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index 39738af..42f937c 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -800,7 +800,7 @@ xdg_surface_pong (struct wl_client *client,
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
- meta_window_pong (surface->window, serial);
+ meta_display_pong_for_serial (surface->window->display, serial);
}
static gboolean
@@ -1017,7 +1017,7 @@ xdg_popup_pong (struct wl_client *client,
MetaWaylandSurfaceExtension *xdg_popup = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (xdg_popup, surface, xdg_popup);
- meta_window_pong (surface->window, serial);
+ meta_display_pong_for_serial (surface->window->display, serial);
}
static const struct xdg_popup_interface meta_wayland_xdg_popup_interface = {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]