XShaping drag and drop fixes

No shaping rectangles means no interaction with the window
The shaping rectangles are based on the window coords, so need to substract the window coords when checking for the point

Change-Id: Ic9004a8ec0f447cddcd1b4324d9fd60a94787cb9
Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
bb10
Albert Astals Cid 2012-05-08 16:41:33 -07:00 committed by Qt by Nokia
parent 3b6b8a0f74
commit 07f3c1e26a
2 changed files with 13 additions and 9 deletions

View File

@ -218,12 +218,11 @@ translateCoordinates(QXcbConnection *c, xcb_window_t from, xcb_window_t to, int
static
bool windowInteractsWithPosition(xcb_connection_t *connection, const QPoint & pos, xcb_window_t w, xcb_shape_sk_t shapeType)
{
bool interacts = true;
bool interacts = false;
xcb_shape_get_rectangles_reply_t *reply = xcb_shape_get_rectangles_reply(connection, xcb_shape_get_rectangles(connection, w, shapeType), NULL);
if (reply) {
xcb_rectangle_t *rectangles = xcb_shape_get_rectangles_rectangles(reply);
if (rectangles) {
interacts = false;
const int nRectangles = xcb_shape_get_rectangles_rectangles_length(reply);
for (int i = 0; !interacts && i < nRectangles; ++i) {
interacts = QRect(rectangles[i].x, rectangles[i].y, rectangles[i].width, rectangles[i].height).contains(pos);
@ -235,7 +234,7 @@ bool windowInteractsWithPosition(xcb_connection_t *connection, const QPoint & po
return interacts;
}
xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md)
xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md, bool ignoreNonXdndAwareWindows)
{
if (w == shapedPixmapWindow()->handle()->winId())
return 0;
@ -252,7 +251,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;
bool windowContainsMouse = !ignoreNonXdndAwareWindows;
{
xcb_get_property_cookie_t cookie =
Q_XCB_CALL(xcb_get_property(xcb_connection(), false, w, connection()->atom(QXcbAtom::XdndAware),
@ -262,12 +261,15 @@ 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) {
const QPoint relPos = pos - QPoint(greply->x, greply->y);
// When ShapeInput and ShapeBounding are not set they return a single rectangle with the geometry of the window, this is why we
// need to check both here so that in the case one is set and the other is not we still get the correct result.
if (connection()->hasInputShape())
windowContainsMouse = windowInteractsWithPosition(xcb_connection(), pos, w, XCB_SHAPE_SK_INPUT);
windowContainsMouse = windowInteractsWithPosition(xcb_connection(), relPos, w, XCB_SHAPE_SK_INPUT);
if (windowContainsMouse && connection()->hasXShape())
windowContainsMouse = windowInteractsWithPosition(xcb_connection(), pos, w, XCB_SHAPE_SK_BOUNDING);
windowContainsMouse = windowInteractsWithPosition(xcb_connection(), relPos, w, XCB_SHAPE_SK_BOUNDING);
if (!connection()->hasInputShape() && !connection()->hasXShape())
windowContainsMouse = true;
if (windowContainsMouse)
return w;
}
@ -283,7 +285,7 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md
xcb_window_t r = 0;
for (uint i = nc; !r && i--;)
r = findRealWindow(pos - QPoint(greply->x, greply->y), c[i], md-1);
r = findRealWindow(pos - QPoint(greply->x, greply->y), c[i], md-1, ignoreNonXdndAwareWindows);
free(reply);
if (r)
@ -382,7 +384,9 @@ void QXcbDrag::move(const QMouseEvent *me)
if (!target || target == shapedPixmapWindow()->handle()->winId()) {
DNDDEBUG << "need to find real window";
target = findRealWindow(globalPos, rootwin, 6);
target = findRealWindow(globalPos, rootwin, 6, true);
if (target == 0)
target = findRealWindow(globalPos, rootwin, 6, false);
DNDDEBUG << "real window found" << target;
}
}

View File

@ -158,7 +158,7 @@ private:
void restartDropExpiryTimer();
int findTransactionByWindow(xcb_window_t window);
int findTransactionByTime(xcb_timestamp_t timestamp);
xcb_window_t findRealWindow(const QPoint & pos, xcb_window_t w, int md);
xcb_window_t findRealWindow(const QPoint & pos, xcb_window_t w, int md, bool ignoreNonXdndAwareWindows);
};
QT_END_NAMESPACE