summaryrefslogtreecommitdiff
path: root/src/core/display.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/display.c')
-rw-r--r--src/core/display.c59
1 files changed, 44 insertions, 15 deletions
diff --git a/src/core/display.c b/src/core/display.c
index 9ba48ac7..63a93b02 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -1218,6 +1218,17 @@ meta_display_get_current_time (MetaDisplay *display)
return display->current_time;
}
+static Bool
+find_timestamp_predicate (Display *xdisplay,
+ XEvent *ev,
+ XPointer arg)
+{
+ MetaDisplay *display = (MetaDisplay *) arg;
+
+ return (ev->type == PropertyNotify &&
+ ev->xproperty.atom == display->atom__METACITY_TIMESTAMP_PING);
+}
+
/* Get a timestamp, even if it means a roundtrip */
guint32
meta_display_get_current_time_roundtrip (MetaDisplay *display)
@@ -1229,17 +1240,13 @@ meta_display_get_current_time_roundtrip (MetaDisplay *display)
{
XEvent property_event;
- /* Using the property XA_PRIMARY because it's safe; nothing
- * would use it as a property. The type doesn't matter.
- */
- XChangeProperty (display->xdisplay,
- display->timestamp_pinging_window,
- XA_PRIMARY, XA_STRING, 8,
- PropModeAppend, NULL, 0);
- XWindowEvent (display->xdisplay,
- display->timestamp_pinging_window,
- PropertyChangeMask,
- &property_event);
+ XChangeProperty (display->xdisplay, display->timestamp_pinging_window,
+ display->atom__METACITY_TIMESTAMP_PING,
+ XA_STRING, 8, PropModeAppend, NULL, 0);
+ XIfEvent (display->xdisplay,
+ &property_event,
+ find_timestamp_predicate,
+ (XPointer) display);
timestamp = property_event.xproperty.time;
}
@@ -1493,6 +1500,7 @@ request_xserver_input_focus_change (MetaDisplay *display,
guint32 timestamp)
{
MetaWindow *meta_window;
+ gulong serial;
if (timestamp_too_old (display, &timestamp))
return;
@@ -1500,14 +1508,35 @@ request_xserver_input_focus_change (MetaDisplay *display,
meta_window = meta_display_lookup_x_window (display, xwindow);
meta_error_trap_push (display);
- update_focus_window (display,
- meta_window,
- XNextRequest (display->xdisplay));
+
+ /* In order for mutter to know that the focus request succeeded, we track
+ * the serial of the "focus request" we made, but if we take the serial
+ * of the XSetInputFocus request, then there's no way to determine the
+ * difference between focus events as a result of the SetInputFocus and
+ * focus events that other clients send around the same time. Ensure that
+ * we know which is which by making two requests that the server will
+ * process at the same time.
+ */
+ XGrabServer (display->xdisplay);
+
+ serial = XNextRequest (display->xdisplay);
XSetInputFocus (display->xdisplay,
xwindow,
RevertToPointerRoot,
timestamp);
+
+ XChangeProperty (display->xdisplay, display->timestamp_pinging_window,
+ display->atom__METACITY_FOCUS_SET,
+ XA_STRING, 8, PropModeAppend, NULL, 0);
+
+ XUngrabServer (display->xdisplay);
+ XFlush (display->xdisplay);
+
+ update_focus_window (display,
+ meta_window,
+ serial);
+
meta_error_trap_pop (display);
display->last_focus_time = timestamp;
@@ -1616,7 +1645,7 @@ handle_window_focus_event (MetaDisplay *display,
else
g_return_if_reached ();
- if (display->server_focus_serial >= display->focus_serial)
+ if (display->server_focus_serial > display->focus_serial)
{
update_focus_window (display, focus_window,
display->server_focus_serial);