summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.p.agocs@nokia.com>2011-06-08 17:41:12 +0200
committerLaszlo Agocs <laszlo.p.agocs@nokia.com>2011-06-09 11:00:02 +0200
commitbd781231b21308aad4c54b4046e65229a6184c00 (patch)
tree2867aac622cf072806e8163d8093a38e66cd923f /src/plugins/platforms
parent4469de4ce7a72ab6824629bfe8483131aaf22137 (diff)
Create custom cursors via XRender.
Reviewed-by: Samuel Rødal
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp22
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.cpp26
-rw-r--r--src/plugins/platforms/xcb/qxcbimage.cpp80
-rw-r--r--src/plugins/platforms/xcb/qxcbimage.h2
-rw-r--r--src/plugins/platforms/xcb/xcb.pro4
6 files changed, 120 insertions, 15 deletions
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 1f966b1bd8..0af71fa830 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -63,6 +63,10 @@
#include <X11/Xlib-xcb.h>
#endif
+#ifdef XCB_USE_RENDER
+#include <xcb/render.h>
+#endif
+
#ifdef XCB_USE_EGL //dont pull in eglext prototypes
#include <EGL/egl.h>
#endif
@@ -126,6 +130,7 @@ QXcbConnection::QXcbConnection(const char *displayName)
m_drag = new QXcbDrag(this);
initializeXFixes();
+ initializeXRender();
#ifdef XCB_USE_DRI2
initializeDri2();
@@ -848,6 +853,23 @@ void QXcbConnection::initializeXFixes()
free(xfixes_query);
}
+void QXcbConnection::initializeXRender()
+{
+#ifdef XCB_USE_RENDER
+ xcb_generic_error_t *error = 0;
+ xcb_render_query_version_cookie_t xrender_query_cookie = xcb_render_query_version(m_connection,
+ XCB_RENDER_MAJOR_VERSION,
+ XCB_RENDER_MINOR_VERSION);
+ xcb_render_query_version_reply_t *xrender_query = xcb_render_query_version_reply(m_connection,
+ xrender_query_cookie, &error);
+ if (!xrender_query || error || (xrender_query->major_version == 0 && xrender_query->minor_version < 5)) {
+ qWarning("Failed to initialize XRender");
+ free(error);
+ }
+ free(xrender_query);
+#endif
+}
+
#if defined(XCB_USE_EGL)
bool QXcbConnection::hasEgl() const
{
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index b148b56eb4..9413b682c3 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -293,6 +293,7 @@ private:
void initializeAllAtoms();
void sendConnectionEvent(QXcbAtom::Atom atom, uint id = 0);
void initializeXFixes();
+ void initializeXRender();
#ifdef XCB_USE_DRI2
void initializeDri2();
#endif
diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp
index cf1e5279a0..f6856d5694 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.cpp
+++ b/src/plugins/platforms/xcb/qxcbcursor.cpp
@@ -489,22 +489,18 @@ xcb_cursor_t QXcbCursor::createBitmapCursor(QCursor *cursor)
{
xcb_connection_t *conn = xcb_connection();
QPoint spot = cursor->hotSpot();
- xcb_pixmap_t cp;
- xcb_pixmap_t mp;
- if (cursor->pixmap().depth() > 1) {
- // ### this will result in monochrome cursors
- cp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->bitmap()->toImage());
- mp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->mask()->toImage());
- } else {
- cp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->bitmap()->toImage());
- mp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->mask()->toImage());
- }
- xcb_cursor_t c = xcb_generate_id(conn);
- xcb_create_cursor(conn, c, cp, mp, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF,
- spot.x(), spot.y());
- xcb_free_pixmap(conn, cp);
- if (mp)
+ xcb_cursor_t c = XCB_NONE;
+ if (cursor->pixmap().depth() > 1)
+ c = qt_xcb_createCursorXRender(m_screen, cursor->pixmap().toImage(), spot);
+ if (!c) {
+ 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);
+ xcb_create_cursor(conn, c, cp, mp, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF,
+ spot.x(), spot.y());
+ xcb_free_pixmap(conn, cp);
xcb_free_pixmap(conn, mp);
+ }
return c;
}
diff --git a/src/plugins/platforms/xcb/qxcbimage.cpp b/src/plugins/platforms/xcb/qxcbimage.cpp
index 6c8c4e32c8..3fb5e2c00e 100644
--- a/src/plugins/platforms/xcb/qxcbimage.cpp
+++ b/src/plugins/platforms/xcb/qxcbimage.cpp
@@ -42,6 +42,17 @@
#include "qxcbimage.h"
#include <QtGui/QColor>
#include <QtGui/private/qimage_p.h>
+#include <QtGui/private/qdrawhelper_p.h>
+#ifdef XCB_USE_RENDER
+#include <xcb/render.h>
+// 'template' is used as a function argument name in xcb_renderutil.h
+#define template template_param
+// extern "C" is missing too
+extern "C" {
+#include <xcb/xcb_renderutil.h>
+}
+#undef template
+#endif
QT_BEGIN_NAMESPACE
@@ -177,4 +188,73 @@ xcb_pixmap_t qt_xcb_XPixmapFromBitmap(QXcbScreen *screen, const QImage &image)
return pm;
}
+xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image,
+ const QPoint &spot)
+{
+#ifdef XCB_USE_RENDER
+ xcb_connection_t *conn = screen->xcb_connection();
+ const int w = image.width();
+ const int h = image.height();
+ xcb_generic_error_t *error = 0;
+ xcb_render_query_pict_formats_cookie_t formatsCookie = xcb_render_query_pict_formats(conn);
+ xcb_render_query_pict_formats_reply_t *formatsReply = xcb_render_query_pict_formats_reply(conn,
+ formatsCookie,
+ &error);
+ if (!formatsReply || error) {
+ qWarning("createCursorXRender: query_pict_formats failed");
+ free(formatsReply);
+ free(error);
+ return XCB_NONE;
+ }
+ xcb_render_pictforminfo_t *fmt = xcb_render_util_find_standard_format(formatsReply,
+ XCB_PICT_STANDARD_ARGB_32);
+ if (!fmt) {
+ qWarning("createCursorXRender: Failed to find format PICT_STANDARD_ARGB_32");
+ free(formatsReply);
+ return XCB_NONE;
+ }
+
+ QImage img = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ xcb_image_t *xi = xcb_image_create(w, h, XCB_IMAGE_FORMAT_Z_PIXMAP,
+ 32, 32, 32, 32,
+ QSysInfo::ByteOrder == QSysInfo::BigEndian ? XCB_IMAGE_ORDER_MSB_FIRST : XCB_IMAGE_ORDER_LSB_FIRST,
+ XCB_IMAGE_ORDER_MSB_FIRST,
+ 0, 0, 0);
+ if (!xi) {
+ qWarning("createCursorXRender: xcb_image_create failed");
+ free(formatsReply);
+ return XCB_NONE;
+ }
+ xi->data = (uint8_t *) malloc(xi->stride * h);
+ memcpy(xi->data, img.constBits(), img.byteCount());
+
+ xcb_pixmap_t pix = xcb_generate_id(conn);
+ xcb_create_pixmap(conn, 32, pix, screen->root(), w, h);
+
+ xcb_render_picture_t pic = xcb_generate_id(conn);
+ xcb_render_create_picture(conn, pic, pix, fmt->id, 0, 0);
+
+ xcb_gcontext_t gc = xcb_generate_id(conn);
+ xcb_create_gc(conn, gc, pix, 0, 0);
+ xcb_image_put(conn, pix, gc, xi, 0, 0, 0);
+ xcb_free_gc(conn, gc);
+
+ xcb_cursor_t cursor = xcb_generate_id(conn);
+ xcb_render_create_cursor(conn, cursor, pic, spot.x(), spot.y());
+
+ free(xi->data);
+ xcb_image_destroy(xi);
+ xcb_render_free_picture(conn, pic);
+ xcb_free_pixmap(conn, pix);
+ free(formatsReply);
+ return cursor;
+
+#else
+ Q_UNUSED(screen);
+ Q_UNUSED(image);
+ Q_UNUSED(spot);
+ return XCB_NONE;
+#endif
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbimage.h b/src/plugins/platforms/xcb/qxcbimage.h
index 39a7abd315..1e7f104084 100644
--- a/src/plugins/platforms/xcb/qxcbimage.h
+++ b/src/plugins/platforms/xcb/qxcbimage.h
@@ -56,6 +56,8 @@ QPixmap qt_xcb_pixmapFromXPixmap(QXcbConnection *connection, xcb_pixmap_t pixmap
int width, int height, int depth,
const xcb_visualtype_t *visual);
xcb_pixmap_t qt_xcb_XPixmapFromBitmap(QXcbScreen *screen, const QImage &image);
+xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image,
+ const QPoint &spot);
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/xcb.pro b/src/plugins/platforms/xcb/xcb.pro
index 0d9e969ddc..c5ce6fa57b 100644
--- a/src/plugins/platforms/xcb/xcb.pro
+++ b/src/plugins/platforms/xcb/xcb.pro
@@ -42,6 +42,9 @@ QT += gui-private core-private
# needed by GLX, Xcursor, ...
DEFINES += XCB_USE_XLIB
+# to support custom cursors with depth > 1
+DEFINES += XCB_USE_RENDER
+
contains(QT_CONFIG, opengl) {
QT += opengl
@@ -74,6 +77,7 @@ contains(QT_CONFIG, opengl) {
LIBS += -lxcb -lxcb-image -lxcb-keysyms -lxcb-icccm -lxcb-sync -lxcb-xfixes
contains(DEFINES, XCB_USE_XLIB): LIBS += -lX11 -lX11-xcb
+contains(DEFINES, XCB_USE_RENDER): LIBS += -lxcb-render -lxcb-render-util
DEFINES += $$QMAKE_DEFINES_XCB
LIBS += $$QMAKE_LIBS_XCB