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>bb10
parent
7286d9d8dd
commit
d5ac11891d
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue