summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb/qxcbscreen.cpp
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2017-01-13 09:56:59 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2017-01-26 10:36:38 +0000
commitb6967d0c11a6f559350c105973780445e253d6b3 (patch)
tree68948ef3b79793d8d80397920a0163d9dee0161c /src/plugins/platforms/xcb/qxcbscreen.cpp
parent9ba16336c51c5843db7c39df30853449972f8ead (diff)
XCB QPA: Fix QScreen::grabWindow(0) to return the current screen
Previously, the code queried the window to be grabbed for the geometry and thus returned the entire virtual desktop for multi screen setups. Use the QPlatformScreen's geometry in case of WID = 0. Task-number: QTBUG-58110 Change-Id: I3a9c0b0b3ea057f5e58f272f5c3fd40fafc073ba Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbscreen.cpp')
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp117
1 files changed, 59 insertions, 58 deletions
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index d8facdbb84..0ad9c97521 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -678,85 +678,88 @@ void QXcbScreen::updateRefreshRate(xcb_randr_mode_t mode)
}
}
-QPixmap QXcbScreen::grabWindow(WId window, int x, int y, int width, int height) const
+static xcb_get_geometry_reply_t *getGeometryUnchecked(xcb_connection_t *connection, xcb_window_t window)
+{
+ const xcb_get_geometry_cookie_t geometry_cookie = xcb_get_geometry_unchecked(connection, window);
+ return xcb_get_geometry_reply(connection, geometry_cookie, NULL);
+}
+
+static inline bool translate(xcb_connection_t *connection, xcb_window_t child, xcb_window_t parent,
+ int *x, int *y)
+{
+ const xcb_translate_coordinates_cookie_t translate_cookie =
+ xcb_translate_coordinates_unchecked(connection, child, parent, *x, *y);
+ xcb_translate_coordinates_reply_t *translate_reply =
+ xcb_translate_coordinates_reply(connection, translate_cookie, NULL);
+ if (!translate_reply)
+ return false;
+ *x = translate_reply->dst_x;
+ *y = translate_reply->dst_y;
+ free(translate_reply);
+ return true;
+}
+
+QPixmap QXcbScreen::grabWindow(WId window, int xIn, int yIn, int width, int height) const
{
if (width == 0 || height == 0)
return QPixmap();
- // TODO: handle multiple screens
+ int x = xIn;
+ int y = yIn;
QXcbScreen *screen = const_cast<QXcbScreen *>(this);
xcb_window_t root = screen->root();
- if (window == 0)
- window = root;
-
- xcb_get_geometry_cookie_t geometry_cookie = xcb_get_geometry_unchecked(xcb_connection(), window);
-
- xcb_get_geometry_reply_t *reply =
- xcb_get_geometry_reply(xcb_connection(), geometry_cookie, NULL);
-
- if (!reply) {
+ xcb_get_geometry_reply_t *rootReply = getGeometryUnchecked(xcb_connection(), root);
+ if (!rootReply)
return QPixmap();
- }
-
- if (width < 0)
- width = reply->width - x;
- if (height < 0)
- height = reply->height - y;
-
- geometry_cookie = xcb_get_geometry_unchecked(xcb_connection(), root);
- xcb_get_geometry_reply_t *root_reply =
- xcb_get_geometry_reply(xcb_connection(), geometry_cookie, NULL);
- if (!root_reply) {
- free(reply);
- return QPixmap();
- }
-
- if (reply->depth == root_reply->depth) {
- // if the depth of the specified window and the root window are the
- // same, grab pixels from the root window (so that we get the any
- // overlapping windows and window manager frames)
-
- // map x and y to the root window
- xcb_translate_coordinates_cookie_t translate_cookie =
- xcb_translate_coordinates_unchecked(xcb_connection(), window, root, x, y);
+ const quint8 rootDepth = rootReply->depth;
+ free(rootReply);
- xcb_translate_coordinates_reply_t *translate_reply =
- xcb_translate_coordinates_reply(xcb_connection(), translate_cookie, NULL);
-
- if (!translate_reply) {
- free(reply);
- free(root_reply);
+ QSize windowSize;
+ quint8 effectiveDepth = 0;
+ if (window) {
+ xcb_get_geometry_reply_t *windowReply = getGeometryUnchecked(xcb_connection(), window);
+ if (!windowReply)
return QPixmap();
+ windowSize = QSize(windowReply->width, windowReply->height);
+ effectiveDepth = windowReply->depth;
+ free(windowReply);
+ if (effectiveDepth == rootDepth) {
+ // if the depth of the specified window and the root window are the
+ // same, grab pixels from the root window (so that we get the any
+ // overlapping windows and window manager frames)
+
+ // map x and y to the root window
+ if (!translate(xcb_connection(), window, root, &x, &y))
+ return QPixmap();
+
+ window = root;
}
-
- x = translate_reply->dst_x;
- y = translate_reply->dst_y;
-
- window = root;
-
- free(translate_reply);
- free(reply);
- reply = root_reply;
} else {
- free(root_reply);
- root_reply = 0;
+ window = root;
+ effectiveDepth = rootDepth;
+ windowSize = m_geometry.size();
+ x += m_geometry.x();
+ y += m_geometry.y();
}
+ if (width < 0)
+ width = windowSize.width() - xIn;
+ if (height < 0)
+ height = windowSize.height() - yIn;
+
xcb_get_window_attributes_reply_t *attributes_reply =
xcb_get_window_attributes_reply(xcb_connection(), xcb_get_window_attributes_unchecked(xcb_connection(), window), NULL);
- if (!attributes_reply) {
- free(reply);
+ if (!attributes_reply)
return QPixmap();
- }
const xcb_visualtype_t *visual = screen->visualForId(attributes_reply->visual);
free(attributes_reply);
xcb_pixmap_t pixmap = xcb_generate_id(xcb_connection());
- xcb_create_pixmap(xcb_connection(), reply->depth, pixmap, window, width, height);
+ xcb_create_pixmap(xcb_connection(), effectiveDepth, pixmap, window, width, height);
uint32_t gc_value_mask = XCB_GC_SUBWINDOW_MODE;
uint32_t gc_value_list[] = { XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS };
@@ -766,9 +769,7 @@ QPixmap QXcbScreen::grabWindow(WId window, int x, int y, int width, int height)
xcb_copy_area(xcb_connection(), window, pixmap, gc, x, y, 0, 0, width, height);
- QPixmap result = qt_xcb_pixmapFromXPixmap(connection(), pixmap, width, height, reply->depth, visual);
-
- free(reply);
+ QPixmap result = qt_xcb_pixmapFromXPixmap(connection(), pixmap, width, height, effectiveDepth, visual);
xcb_free_gc(xcb_connection(), gc);
xcb_free_pixmap(xcb_connection(), pixmap);