summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2018-04-15 01:00:18 +0200
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2018-04-15 01:00:18 +0200
commit4aa6f54fec9d199f97759945118451c52767b2ce (patch)
tree5dc695cd4718437b5015aaef3a02463c61bc5dc2 /src/plugins/platforms/xcb
parent369e7572bac94bb5b83ef881012fdc4a86829496 (diff)
parentd5ac11891d8237ca2f02390ffd0ff103578b520e (diff)
Merge remote-tracking branch 'origin/5.11' into dev
Diffstat (limited to 'src/plugins/platforms/xcb')
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp14
-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.cpp57
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.h16
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp22
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h3
7 files changed, 74 insertions, 59 deletions
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
index 659d1c53cb..8cfcc49f9a 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
@@ -219,12 +219,14 @@ void QXcbBackingStoreImage::create(const QSize &size, const xcb_format_t *fmt, Q
if (!segmentSize)
return;
- if (hasShm() && m_segmentSize > 0 && (m_segmentSize < segmentSize || m_segmentSize / 2 >= segmentSize))
- destroyShmSegment(m_segmentSize);
- if (!hasShm() && connection()->hasShm())
- {
- qCDebug(lcQpaXcb) << "creating shared memory" << segmentSize << "for" << size << "depth" << fmt->depth << "bits" << fmt->bits_per_pixel;
- createShmSegment(segmentSize);
+ if (connection()->hasShm()) {
+ if (m_shm_info.shmaddr && (m_segmentSize < segmentSize || m_segmentSize / 2 >= segmentSize))
+ destroyShmSegment(m_segmentSize);
+ if (!m_shm_info.shmaddr) {
+ qCDebug(lcQpaXcb) << "creating shared memory" << segmentSize << "for"
+ << size << "depth" << fmt->depth << "bits" << fmt->bits_per_pixel;
+ createShmSegment(segmentSize);
+ }
}
m_xcb_image->data = m_shm_info.shmaddr ? m_shm_info.shmaddr : (uint8_t *)malloc(segmentSize);
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 94dbb76117..6f1a3e3c19 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -2109,17 +2109,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 9e16d15b20..3b42d7cf22 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -464,7 +464,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; }
@@ -685,6 +691,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 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);
diff --git a/src/plugins/platforms/xcb/qxcbcursor.h b/src/plugins/platforms/xcb/qxcbcursor.h
index e3f88518fe..5bc806381c 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.h
+++ b/src/plugins/platforms/xcb/qxcbcursor.h
@@ -43,6 +43,8 @@
#include <qpa/qplatformcursor.h>
#include "qxcbscreen.h"
+#include <QtCore/QCache>
+
QT_BEGIN_NAMESPACE
#ifndef QT_NO_CURSOR
@@ -76,7 +78,7 @@ public:
QXcbCursor(QXcbConnection *conn, QXcbScreen *screen);
~QXcbCursor();
#ifndef QT_NO_CURSOR
- void changeCursor(QCursor *cursor, QWindow *widget) override;
+ void changeCursor(QCursor *cursor, QWindow *window) override;
#endif
QPoint pos() const override;
void setPos(const QPoint &pos) override;
@@ -89,9 +91,20 @@ public:
#endif
private:
+
#ifndef QT_NO_CURSOR
typedef QHash<QXcbCursorCacheKey, xcb_cursor_t> CursorHash;
+ struct CachedCursor
+ {
+ explicit CachedCursor(xcb_connection_t *conn, xcb_cursor_t c)
+ : cursor(c), connection(conn) {}
+ ~CachedCursor() { xcb_free_cursor(connection, cursor); }
+ xcb_cursor_t cursor;
+ xcb_connection_t *connection;
+ };
+ typedef QCache<QXcbCursorCacheKey, CachedCursor> BitmapCursorCache;
+
xcb_cursor_t createFontCursor(int cshape);
xcb_cursor_t createBitmapCursor(QCursor *cursor);
xcb_cursor_t createNonStandardCursor(int cshape);
@@ -100,6 +113,7 @@ private:
QXcbScreen *m_screen;
#ifndef QT_NO_CURSOR
CursorHash m_cursorHash;
+ BitmapCursorCache m_bitmapCache;
#endif
#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library)
static void cursorThemePropertyChanged(QXcbVirtualDesktop *screen,
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index a19d69af41..01eb88eea7 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -560,10 +560,6 @@ void QXcbWindow::create()
QXcbWindow::~QXcbWindow()
{
- if (m_currentBitmapCursor != XCB_CURSOR_NONE) {
- xcb_free_cursor(xcb_connection(), m_currentBitmapCursor);
- }
-
destroy();
}
@@ -2591,24 +2587,6 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab)
return result;
}
-void QXcbWindow::setCursor(xcb_cursor_t cursor, bool isBitmapCursor)
-{
- xcb_connection_t *conn = xcb_connection();
-
- xcb_change_window_attributes(conn, m_window, XCB_CW_CURSOR, &cursor);
- xcb_flush(conn);
-
- if (m_currentBitmapCursor != XCB_CURSOR_NONE) {
- xcb_free_cursor(conn, m_currentBitmapCursor);
- }
-
- if (isBitmapCursor) {
- m_currentBitmapCursor = cursor;
- } else {
- m_currentBitmapCursor = XCB_CURSOR_NONE;
- }
-}
-
void QXcbWindow::windowEvent(QEvent *event)
{
switch (event->type()) {
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index a1f1540466..edfee1f574 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -103,8 +103,6 @@ public:
bool setKeyboardGrabEnabled(bool grab) override;
bool setMouseGrabEnabled(bool grab) override;
- void setCursor(xcb_cursor_t cursor, bool isBitmapCursor);
-
QSurfaceFormat format() const override;
void windowEvent(QEvent *event) override;
@@ -285,7 +283,6 @@ protected:
SyncState m_syncState = NoSyncNeeded;
QXcbSyncWindowRequest *m_pendingSyncRequest = nullptr;
- xcb_cursor_t m_currentBitmapCursor = XCB_CURSOR_NONE;
};
class QXcbForeignWindow : public QXcbWindow