summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb
diff options
context:
space:
mode:
authorGatis Paeglis <gatis.paeglis@qt.io>2018-04-10 11:50:31 +0200
committerGatis Paeglis <gatis.paeglis@qt.io>2018-04-14 17:03:10 +0000
commitd5ac11891d8237ca2f02390ffd0ff103578b520e (patch)
tree2ae7eb99d63bbb9ffed440e88731a8d08399b116 /src/plugins/platforms/xcb
parent7286d9d8dd1f8543007218a91d5c6767a7a7b152 (diff)
xcb: prevent crash with pixmap cursors on XRender-less X servers
We were using xcb_render_* APIs without checking if the server even supports this extension. Attempting to use an extension which is not present will always result in a crash. This patch adds the required guards and refactors how we detect presence of XRender extension. Also instead of falling back to some odd-looking bitmapped version just leave the current cursor unchanged. That is how we did it in Qt4 AFAICT. Task-number: QTBUG-66935 Change-Id: I4f27f1d65a77563ec34f3e0e94492c9236d7f9a6 Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Diffstat (limited to 'src/plugins/platforms/xcb')
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp11
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h10
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.cpp15
3 files changed, 28 insertions, 8 deletions
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 2431f99ab8..444e3a7669 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -2136,17 +2136,22 @@ void QXcbConnection::initializeXRender()
{
#if QT_CONFIG(xcb_render)
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_render_id);
- if (!reply || !reply->present)
+ if (!reply || !reply->present) {
+ qCDebug(lcQpaXcb, "XRender extension not present on the X server");
return;
+ }
auto xrender_query = Q_XCB_REPLY(xcb_render_query_version, m_connection,
XCB_RENDER_MAJOR_VERSION,
XCB_RENDER_MINOR_VERSION);
- if (!xrender_query || (xrender_query->major_version == 0 && xrender_query->minor_version < 5)) {
- qWarning("QXcbConnection: Failed to initialize XRender");
+ if (!xrender_query) {
+ qCWarning(lcQpaXcb, "xcb_render_query_version failed");
return;
}
+
has_render_extension = true;
+ m_xrenderVersion.first = xrender_query->major_version;
+ m_xrenderVersion.second = xrender_query->minor_version;
#endif
}
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index ced5208c81..d9321d94d0 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -478,7 +478,13 @@ public:
bool hasXRandr() const { return has_randr_extension; }
bool hasInputShape() const { return has_input_shape; }
bool hasXKB() const { return has_xkb; }
- bool hasXRender() const { return has_render_extension; }
+ bool hasXRender(int major = -1, int minor = -1) const
+ {
+ if (has_render_extension && major != -1 && minor != -1)
+ return m_xrenderVersion >= qMakePair(major, minor);
+
+ return has_render_extension;
+ }
bool hasXInput2() const { return m_xi2Enabled; }
bool hasShm() const { return has_shm; }
bool hasShmFd() const { return has_shm_fd; }
@@ -707,6 +713,8 @@ private:
bool has_shm = false;
bool has_shm_fd = false;
+ QPair<int, int> m_xrenderVersion;
+
Qt::MouseButtons m_buttonState = 0;
Qt::MouseButton m_button = Qt::NoButton;
diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp
index 70138abede..8d151b760b 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.cpp
+++ b/src/plugins/platforms/xcb/qxcbcursor.cpp
@@ -601,12 +601,19 @@ xcb_cursor_t QXcbCursor::createFontCursor(int cshape)
xcb_cursor_t QXcbCursor::createBitmapCursor(QCursor *cursor)
{
- xcb_connection_t *conn = xcb_connection();
QPoint spot = cursor->hotSpot();
xcb_cursor_t c = XCB_NONE;
- if (cursor->pixmap().depth() > 1)
- c = qt_xcb_createCursorXRender(m_screen, cursor->pixmap().toImage(), spot);
- if (!c) {
+ if (cursor->pixmap().depth() > 1) {
+#if QT_CONFIG(xcb_render)
+ if (connection()->hasXRender(0, 5))
+ c = qt_xcb_createCursorXRender(m_screen, cursor->pixmap().toImage(), spot);
+ else
+ qCWarning(lcQpaXcb, "xrender >= 0.5 required to create pixmap cursors");
+#else
+ qCWarning(lcQpaXcb, "This build of Qt does not support pixmap cursors");
+#endif
+ } else {
+ xcb_connection_t *conn = xcb_connection();
xcb_pixmap_t cp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->bitmap()->toImage());
xcb_pixmap_t mp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->mask()->toImage());
c = xcb_generate_id(conn);