diff options
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbcursor.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbcursor.cpp | 57 |
1 files changed, 34 insertions, 23 deletions
diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp index 34b7d0d236..8d151b760b 100644 --- a/src/plugins/platforms/xcb/qxcbcursor.cpp +++ b/src/plugins/platforms/xcb/qxcbcursor.cpp @@ -301,6 +301,9 @@ QXcbCursorCacheKey::QXcbCursorCacheKey(const QCursor &c) QXcbCursor::QXcbCursor(QXcbConnection *conn, QXcbScreen *screen) : QXcbObject(conn), m_screen(screen), m_gtkCursorThemeInitialized(false) { + // see NUM_BITMAPS in libXcursor/src/xcursorint.h + m_bitmapCache.setMaxCost(8); + if (cursorCount++) return; @@ -351,37 +354,38 @@ QXcbCursor::~QXcbCursor() } #ifndef QT_NO_CURSOR -void QXcbCursor::changeCursor(QCursor *cursor, QWindow *widget) +void QXcbCursor::changeCursor(QCursor *cursor, QWindow *window) { - QXcbWindow *w = 0; - if (widget && widget->handle()) - w = static_cast<QXcbWindow *>(widget->handle()); - else - // No X11 cursor control when there is no widget under the cursor + if (!window || !window->handle()) return; xcb_cursor_t c = XCB_CURSOR_NONE; - bool isBitmapCursor = false; - if (cursor) { + const QXcbCursorCacheKey key(*cursor); const Qt::CursorShape shape = cursor->shape(); - isBitmapCursor = shape == Qt::BitmapCursor; - if (!isBitmapCursor) { - const QXcbCursorCacheKey key(*cursor); - CursorHash::iterator it = m_cursorHash.find(key); - if (it == m_cursorHash.end()) { - it = m_cursorHash.insert(key, createFontCursor(shape)); + if (shape == Qt::BitmapCursor) { + auto *bitmap = m_bitmapCache.object(key); + if (bitmap) { + c = bitmap->cursor; + } else { + c = createBitmapCursor(cursor); + m_bitmapCache.insert(key, new CachedCursor(xcb_connection(), c)); } - c = it.value(); } else { - // Do not cache bitmap cursors, as otherwise they have unclear - // lifetime (we effectively leak xcb_cursor_t). - c = createBitmapCursor(cursor); + auto it = m_cursorHash.find(key); + if (it == m_cursorHash.end()) { + c = createFontCursor(shape); + m_cursorHash.insert(key, c); + } else { + c = it.value(); + } } } - w->setCursor(c, isBitmapCursor); + auto *w = static_cast<QXcbWindow *>(window->handle()); + xcb_change_window_attributes(xcb_connection(), w->xcb_window(), XCB_CW_CURSOR, &c); + xcb_flush(xcb_connection()); } static int cursorIdForShape(int cshape) @@ -597,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); |