summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb/qxcbscreen.cpp
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2017-01-30 12:39:22 +0100
committerLiang Qi <liang.qi@qt.io>2017-01-30 12:46:20 +0100
commit246799d8a7bf42c1f22fca7ef6d77e8d58054bad (patch)
treea0b92a804d7d2a30cd68fa327df5777d8bcc36ba /src/plugins/platforms/xcb/qxcbscreen.cpp
parent5ad191850becd7dc1d61d0975f141a5db64e6373 (diff)
parent02cc57f4edbae450ecfa8368052afa44f8aeee19 (diff)
Merge remote-tracking branch 'origin/5.8' into dev
Conflicts: examples/network/network-chat/peermanager.cpp src/widgets/util/qsystemtrayicon.cpp src/widgets/util/qsystemtrayicon_qpa.cpp src/widgets/util/qsystemtrayicon_win.cpp src/widgets/util/qsystemtrayicon_x11.cpp Change-Id: I1c026df83818c0ccaf956980370e7522960627db
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbscreen.cpp')
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp119
1 files changed, 60 insertions, 59 deletions
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 736b4852d8..5e136b5d7e 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -620,7 +620,7 @@ void QXcbScreen::updateGeometry(const QRect &geom, uint8_t rotation)
m_sizeMillimeters = sizeInMillimeters(xGeometry.size(), virtualDpi());
qreal dpi = xGeometry.width() / physicalSize().width() * qreal(25.4);
- m_pixelDensity = qRound(dpi/96);
+ m_pixelDensity = qMax(1, qRound(dpi/96));
m_geometry = QRect(xGeometry.topLeft(), xGeometry.size());
m_availableGeometry = xGeometry & m_virtualDesktop->workArea();
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), m_geometry, m_availableGeometry);
@@ -667,85 +667,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 };
@@ -755,9 +758,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);