Take into account shaping in findRealWindow
authorAlbert Astals Cid <aacid@kde.org>
Tue, 7 Feb 2012 14:48:51 +0000 (15:48 +0100)
committerQt by Nokia <qt-info@nokia.com>
Thu, 9 Feb 2012 09:50:20 +0000 (10:50 +0100)
It can happen that there is a window covering all the screen but it is shaped
to only take part of the screen. If that happens, besides the condition of
   QRect(attr.x,attr.y,attr.width,attr.height).contains(pos)
we also need to query the server for its region rectangles and make
sure the cursor is inside one of those rectangles. If that does not happen
we have to return 0 so the hierarchical xcb_query_tree_children xcb_query_tree_childrenntinues

Change-Id: I67327672e3d854d064190b55a07bd56ade4dfddb
Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
Reviewed-by: Uli Schlachter <psychon@znc.in>
Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
src/plugins/platforms/xcb/qxcbdrag.cpp

index a05fc78..e928fe2 100644 (file)
@@ -234,6 +234,7 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md
         xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(xcb_connection(), w);
         xcb_get_geometry_reply_t *greply = xcb_get_geometry_reply(xcb_connection(), gcookie, 0);
         if (reply && QRect(greply->x, greply->y, greply->width, greply->height).contains(pos)) {
+            bool windowContainsMouse = true;
             {
                 xcb_get_property_cookie_t cookie =
                         Q_XCB_CALL(xcb_get_property(xcb_connection(), false, w, connection()->atom(QXcbAtom::XdndAware),
@@ -242,8 +243,26 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md
 
                 bool isAware = reply && reply->type != XCB_NONE;
                 free(reply);
-                if (isAware)
-                    return w;
+                if (isAware) {
+                    xcb_xfixes_region_t region = xcb_generate_id(xcb_connection());
+                    xcb_xfixes_create_region_from_window(xcb_connection(), region, w, XCB_SHAPE_SK_BOUNDING);
+                    xcb_xfixes_fetch_region_reply_t *reply = xcb_xfixes_fetch_region_reply(xcb_connection(), xcb_xfixes_fetch_region(xcb_connection(), region), NULL);
+                    if (reply) {
+                        xcb_rectangle_t *rectangles = xcb_xfixes_fetch_region_rectangles(reply);
+                        if (rectangles) {
+                            windowContainsMouse = false;
+                            const int nRectangles = xcb_xfixes_fetch_region_rectangles_length(reply);
+                            for (int i = 0; !windowContainsMouse && i < nRectangles; ++i) {
+                                windowContainsMouse = QRect(rectangles[i].x, rectangles[i].y, rectangles[i].width, rectangles[i].height).contains(pos);
+                            }
+                        }
+                        free(reply);
+                    }
+                    xcb_xfixes_destroy_region(xcb_connection(), region);
+
+                    if (windowContainsMouse)
+                        return w;
+                }
             }
 
             xcb_query_tree_cookie_t cookie = xcb_query_tree (xcb_connection(), w);
@@ -266,7 +285,10 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md
             // innermost window.
 
             // No children!
-            return w;
+            if (!windowContainsMouse)
+                return 0;
+            else
+                return w;
         }
     }
     return 0;