Blob Blame History Raw
From a91e9dd202640598d8dec091c67ec94536390e7f Mon Sep 17 00:00:00 2001
From: "Owen W. Taylor" <otaylor@fishsoup.net>
Date: Mon, 17 Oct 2011 17:27:43 -0400
Subject: [PATCH] Fix logic for figuring out what ConfigureNotify positions
 can be trusted

When reading ahead in the queue for ConfigureNotify events, it's necessary
to look for intermediate ReparentNotify events as well, since they will
determine whether the position in the event can be trusted or not.
---
 src/gui/kernel/qapplication_x11.cpp |   47 ++++++++++++++++++++++++++++++----
 1 files changed, 41 insertions(+), 6 deletions(-)

diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp
index 408e9ac..3a1d3eb 100644
--- a/src/gui/kernel/qapplication_x11.cpp
+++ b/src/gui/kernel/qapplication_x11.cpp
@@ -816,6 +816,27 @@ static Bool qt_sync_request_scanner(Display*, XEvent *event, XPointer arg)
 #endif
 #endif // QT_NO_XSYNC
 
+struct qt_configure_event_data
+{
+    WId window;
+    WId parent;
+};
+
+static Bool qt_configure_event_scanner(Display*, XEvent *event, XPointer arg)
+{
+    qt_configure_event_data *data =
+        reinterpret_cast<qt_configure_event_data*>(arg);
+    if (event->type == ConfigureNotify &&
+        event->xconfigure.window == data->window) {
+        return true;
+    } else if (event->type == ReparentNotify &&
+               event->xreparent.window == data->window) {
+        data->parent = event->xreparent.parent;
+    }
+
+    return false;
+}
+
 static void qt_x11_create_intern_atoms()
 {
     const char *names[QX11Data::NAtoms];
@@ -5273,8 +5294,11 @@ bool QETWidget::translateConfigEvent(const XEvent *event)
         if (d->extra->compress_events) {
             // ConfigureNotify compression for faster opaque resizing
             XEvent otherEvent;
-            while (XCheckTypedWindowEvent(X11->display, internalWinId(), ConfigureNotify,
-                                          &otherEvent)) {
+            qt_configure_event_data configureData;
+            configureData.window = internalWinId();
+            configureData.parent = d->topData()->parentWinId;
+            while (XCheckIfEvent(X11->display, &otherEvent,
+                                 &qt_configure_event_scanner, (XPointer)&configureData)) {
                 if (qt_x11EventFilter(&otherEvent))
                     continue;
 
@@ -5287,13 +5311,19 @@ bool QETWidget::translateConfigEvent(const XEvent *event)
                 newSize.setWidth(otherEvent.xconfigure.width);
                 newSize.setHeight(otherEvent.xconfigure.height);
 
+                trust = isVisible()
+                        && (configureData.parent == XNone ||
+                            configureData.parent == QX11Info::appRootWindow());
+
                 if (otherEvent.xconfigure.send_event || trust) {
                     newCPos.rx() = otherEvent.xconfigure.x +
                                    otherEvent.xconfigure.border_width;
                     newCPos.ry() = otherEvent.xconfigure.y +
                                    otherEvent.xconfigure.border_width;
                     isCPos = true;
-                }
+                } else {
+                    isCPos = false;
+               }
             }
 #ifndef QT_NO_XSYNC
             qt_sync_request_event_data sync_event;
@@ -5306,9 +5336,14 @@ bool QETWidget::translateConfigEvent(const XEvent *event)
         }
 
         if (!isCPos) {
-            // we didn't get an updated position of the toplevel.
-            // either we haven't moved or there is a bug in the window manager.
-            // anyway, let's query the position to be certain.
+            // If the last configure event didn't have a trustable position,
+            // it's necessary to query, see ICCCM 4.24:
+            //
+            //  Any real ConfigureNotify event on a top-level window implies
+            //  that the window’s position on the root may have changed, even
+            //  though the event reports that the window’s position in its
+            //  parent is unchanged because the window may have been reparented.
+
             int x, y;
             Window child;
             XTranslateCoordinates(X11->display, internalWinId(),
-- 
1.7.6.4