summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.p.agocs@nokia.com>2011-06-07 15:38:45 +0200
committerLaszlo Agocs <laszlo.p.agocs@nokia.com>2011-06-08 14:47:22 +0200
commit4469de4ce7a72ab6824629bfe8483131aaf22137 (patch)
treecc5b1c11c0681975e972f2d6aeab80e106d328c8
parent88f3b059a935d1ce7735a5ae082c256619eea8c1 (diff)
Cursor support in xcb plug-in.
Custom cursor pixmaps with depth greater than 1 are not yet supported and will be converted to monochrome always. Reviewed-by: Samuel Rødal
-rw-r--r--src/gui/kernel/qcursor_qpa.cpp23
-rw-r--r--src/gui/kernel/qguiapplication.cpp4
-rw-r--r--src/gui/kernel/qplatformcursor_qpa.cpp15
-rw-r--r--src/gui/kernel/qplatformcursor_qpa.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp34
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.cpp550
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.h71
-rw-r--r--src/plugins/platforms/xcb/qxcbimage.cpp180
-rw-r--r--src/plugins/platforms/xcb/qxcbimage.h62
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp100
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h2
-rw-r--r--src/plugins/platforms/xcb/xcb.pro19
-rw-r--r--src/widgets/kernel/qwidget.cpp6
-rw-r--r--src/widgets/kernel/qwidget_p.h3
-rw-r--r--src/widgets/kernel/qwidget_qpa.cpp96
19 files changed, 1002 insertions, 178 deletions
diff --git a/src/gui/kernel/qcursor_qpa.cpp b/src/gui/kernel/qcursor_qpa.cpp
index c0b27bebd8..a2927601a9 100644
--- a/src/gui/kernel/qcursor_qpa.cpp
+++ b/src/gui/kernel/qcursor_qpa.cpp
@@ -41,6 +41,7 @@
#include <qcursor.h>
#include <private/qcursor_p.h>
+#include <qplatformcursor_qpa.h>
#include <qbitmap.h>
QT_BEGIN_NAMESPACE
@@ -107,21 +108,39 @@ void QCursorData::update()
#endif //QT_NO_CURSOR
-extern int qt_last_x,qt_last_y;
+extern int qt_last_x;
+extern int qt_last_y;
QPoint QCursor::pos()
{
+ QList<QWeakPointer<QPlatformCursor> > cursors = QPlatformCursorPrivate::getInstances();
+ int cursorCount = cursors.count();
+ for (int i = 0; i < cursorCount; ++i) {
+ const QWeakPointer<QPlatformCursor> &cursor(cursors.at(i));
+ if (cursor)
+ return cursor.data()->pos();
+ }
return QPoint(qt_last_x, qt_last_y);
}
void QCursor::setPos(int x, int y)
{
+ QPoint target(x, y);
+
// Need to check, since some X servers generate null mouse move
// events, causing looping in applications which call setPos() on
// every mouse move event.
//
- if (pos() == QPoint(x, y))
+ if (pos() == target)
return;
+
+ QList<QWeakPointer<QPlatformCursor> > cursors = QPlatformCursorPrivate::getInstances();
+ int cursorCount = cursors.count();
+ for (int i = 0; i < cursorCount; ++i) {
+ const QWeakPointer<QPlatformCursor> &cursor(cursors.at(i));
+ if (cursor)
+ cursor.data()->setPos(target);
+ }
}
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 80b4aa3206..468e8c3bfd 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -212,7 +212,7 @@ static void init_platform(const QString &name, const QString &platformPluginPath
QStringList keys = QPlatformIntegrationFactory::keys(platformPluginPath);
QString fatalMessage =
QString::fromLatin1("Failed to load platform plugin \"%1\". Available platforms are: \n").arg(name);
- foreach(QString key, keys) {
+ foreach(const QString &key, keys) {
fatalMessage.append(key + QString::fromLatin1("\n"));
}
qFatal("%s", fatalMessage.toLocal8Bit().constData());
@@ -221,7 +221,7 @@ static void init_platform(const QString &name, const QString &platformPluginPath
}
-static void init_plugins(const QList<QByteArray> pluginList)
+static void init_plugins(const QList<QByteArray> &pluginList)
{
for (int i = 0; i < pluginList.count(); ++i) {
QByteArray pluginSpec = pluginList.at(i);
diff --git a/src/gui/kernel/qplatformcursor_qpa.cpp b/src/gui/kernel/qplatformcursor_qpa.cpp
index b3994103fe..4c98098898 100644
--- a/src/gui/kernel/qplatformcursor_qpa.cpp
+++ b/src/gui/kernel/qplatformcursor_qpa.cpp
@@ -98,6 +98,21 @@ QPlatformCursor::QPlatformCursor(QPlatformScreen *scr )
QPlatformCursorPrivate::instances.append(this);
}
+extern int qt_last_x;
+extern int qt_last_y;
+
+QPoint QPlatformCursor::pos() const
+{
+ // As a fallback return the last mouse position seen by QGuiApplication.
+ return QPoint(qt_last_x, qt_last_y);
+}
+
+void QPlatformCursor::setPos(const QPoint &pos)
+{
+ Q_UNUSED(pos);
+ qWarning("This plugin does not support QCursor::setPos()");
+}
+
// End of display and pointer event handling code
// Beginning of built-in cursor graphics
// from src/gui/embedded/QGraphicsSystemCursorImage_qws.cpp
diff --git a/src/gui/kernel/qplatformcursor_qpa.h b/src/gui/kernel/qplatformcursor_qpa.h
index 89091b555b..af40c7d1c0 100644
--- a/src/gui/kernel/qplatformcursor_qpa.h
+++ b/src/gui/kernel/qplatformcursor_qpa.h
@@ -86,6 +86,8 @@ public:
// input methods
virtual void pointerEvent(const QMouseEvent & event) { Q_UNUSED(event); }
virtual void changeCursor(QCursor * widgetCursor, QWindow * widget) = 0;
+ virtual QPoint pos() const;
+ virtual void setPos(const QPoint &pos);
protected:
QPlatformScreen* screen; // Where to request an update
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 94c30a989f..1f966b1bd8 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -56,6 +56,7 @@
#include <stdio.h>
#include <errno.h>
+#include <xcb/xfixes.h>
#ifdef XCB_USE_XLIB
#include <X11/Xlib.h>
@@ -68,7 +69,6 @@
#ifdef XCB_USE_DRI2
#include <xcb/dri2.h>
-#include <xcb/xfixes.h>
extern "C" {
#include <xf86drm.h>
}
@@ -125,6 +125,8 @@ QXcbConnection::QXcbConnection(const char *displayName)
m_clipboard = new QXcbClipboard(this);
m_drag = new QXcbDrag(this);
+ initializeXFixes();
+
#ifdef XCB_USE_DRI2
initializeDri2();
#endif
@@ -830,6 +832,22 @@ void QXcbConnection::sync()
free(xcb_get_input_focus_reply(xcb_connection(), cookie, 0));
}
+void QXcbConnection::initializeXFixes()
+{
+ xcb_generic_error_t *error = 0;
+ xcb_prefetch_extension_data (m_connection, &xcb_xfixes_id);
+ xcb_xfixes_query_version_cookie_t xfixes_query_cookie = xcb_xfixes_query_version(m_connection,
+ XCB_XFIXES_MAJOR_VERSION,
+ XCB_XFIXES_MINOR_VERSION);
+ xcb_xfixes_query_version_reply_t *xfixes_query = xcb_xfixes_query_version_reply (m_connection,
+ xfixes_query_cookie, &error);
+ if (!xfixes_query || error || xfixes_query->major_version < 2) {
+ qWarning("Failed to initialize XFixes");
+ free(error);
+ }
+ free(xfixes_query);
+}
+
#if defined(XCB_USE_EGL)
bool QXcbConnection::hasEgl() const
{
@@ -900,26 +918,12 @@ bool QXcbConnection::hasSupportForDri2() const
if (!m_dri2_support_probed) {
xcb_generic_error_t *error = 0;
- xcb_prefetch_extension_data (m_connection, &xcb_xfixes_id);
xcb_prefetch_extension_data (m_connection, &xcb_dri2_id);
- xcb_xfixes_query_version_cookie_t xfixes_query_cookie = xcb_xfixes_query_version(m_connection,
- XCB_XFIXES_MAJOR_VERSION,
- XCB_XFIXES_MINOR_VERSION);
-
xcb_dri2_query_version_cookie_t dri2_query_cookie = xcb_dri2_query_version (m_connection,
XCB_DRI2_MAJOR_VERSION,
XCB_DRI2_MINOR_VERSION);
- xcb_xfixes_query_version_reply_t *xfixes_query = xcb_xfixes_query_version_reply (m_connection,
- xfixes_query_cookie, &error);
- if (!xfixes_query || error || xfixes_query->major_version < 2) {
- delete error;
- delete xfixes_query;
- return false;
- }
- delete xfixes_query;
-
xcb_dri2_query_version_reply_t *dri2_query = xcb_dri2_query_version_reply (m_connection,
dri2_query_cookie, &error);
if (!dri2_query || error) {
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index aa54229779..b148b56eb4 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -292,6 +292,7 @@ private slots:
private:
void initializeAllAtoms();
void sendConnectionEvent(QXcbAtom::Atom atom, uint id = 0);
+ void initializeXFixes();
#ifdef XCB_USE_DRI2
void initializeDri2();
#endif
diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp
new file mode 100644
index 0000000000..cf1e5279a0
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbcursor.cpp
@@ -0,0 +1,550 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qxcbcursor.h"
+#include "qxcbconnection.h"
+#include "qxcbwindow.h"
+#include "qxcbimage.h"
+#include <QtCore/QLibrary>
+#include <QtGui/QWindow>
+#include <QtGui/QBitmap>
+#include <QtGui/private/qguiapplication_p.h>
+#include <X11/cursorfont.h>
+#include <xcb/xfixes.h>
+#include <xcb/xcb_image.h>
+
+QT_BEGIN_NAMESPACE
+
+typedef int (*PtrXcursorLibraryLoadCursor)(void *, const char *);
+static PtrXcursorLibraryLoadCursor ptrXcursorLibraryLoadCursor = 0;
+static xcb_font_t cursorFont = 0;
+static int cursorCount = 0;
+
+static uint8_t cur_blank_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static const uint8_t cur_ver_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f,
+ 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xf0, 0x0f,
+ 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00 };
+static const uint8_t mcur_ver_bits[] = {
+ 0x00, 0x00, 0x80, 0x03, 0xc0, 0x07, 0xe0, 0x0f, 0xf0, 0x1f, 0xf8, 0x3f,
+ 0xfc, 0x7f, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xfc, 0x7f, 0xf8, 0x3f,
+ 0xf0, 0x1f, 0xe0, 0x0f, 0xc0, 0x07, 0x80, 0x03 };
+static const uint8_t cur_hor_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x30, 0x18,
+ 0x38, 0x38, 0xfc, 0x7f, 0xfc, 0x7f, 0x38, 0x38, 0x30, 0x18, 0x20, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const uint8_t mcur_hor_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0x60, 0x0c, 0x70, 0x1c, 0x78, 0x3c,
+ 0xfc, 0x7f, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfc, 0x7f, 0x78, 0x3c,
+ 0x70, 0x1c, 0x60, 0x0c, 0x40, 0x04, 0x00, 0x00 };
+static const uint8_t cur_bdiag_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x3e,
+ 0x00, 0x37, 0x88, 0x23, 0xd8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0xf8, 0x00,
+ 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const uint8_t mcur_bdiag_bits[] = {
+ 0x00, 0x00, 0xc0, 0x7f, 0x80, 0x7f, 0x00, 0x7f, 0x00, 0x7e, 0x04, 0x7f,
+ 0x8c, 0x7f, 0xdc, 0x77, 0xfc, 0x63, 0xfc, 0x41, 0xfc, 0x00, 0xfc, 0x01,
+ 0xfc, 0x03, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00 };
+static const uint8_t cur_fdiag_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00,
+ 0xf8, 0x00, 0xd8, 0x01, 0x88, 0x23, 0x00, 0x37, 0x00, 0x3e, 0x00, 0x3c,
+ 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00 };
+static const uint8_t mcur_fdiag_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xfc, 0x03, 0xfc, 0x01, 0xfc, 0x00,
+ 0xfc, 0x41, 0xfc, 0x63, 0xdc, 0x77, 0x8c, 0x7f, 0x04, 0x7f, 0x00, 0x7e,
+ 0x00, 0x7f, 0x80, 0x7f, 0xc0, 0x7f, 0x00, 0x00 };
+static const uint8_t *cursor_bits16[] = {
+ cur_ver_bits, mcur_ver_bits, cur_hor_bits, mcur_hor_bits,
+ cur_bdiag_bits, mcur_bdiag_bits, cur_fdiag_bits, mcur_fdiag_bits,
+ 0, 0, cur_blank_bits, cur_blank_bits };
+
+static const uint8_t vsplit_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00,
+ 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const uint8_t vsplitm_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00,
+ 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00,
+ 0x00, 0xc0, 0x01, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00,
+ 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00,
+ 0x80, 0xff, 0xff, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00,
+ 0x00, 0xc0, 0x01, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf0, 0x07, 0x00,
+ 0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const uint8_t hsplit_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
+ 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
+ 0x00, 0x41, 0x82, 0x00, 0x80, 0x41, 0x82, 0x01, 0xc0, 0x7f, 0xfe, 0x03,
+ 0x80, 0x41, 0x82, 0x01, 0x00, 0x41, 0x82, 0x00, 0x00, 0x40, 0x02, 0x00,
+ 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
+ 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const uint8_t hsplitm_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
+ 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe3, 0xc7, 0x00,
+ 0x80, 0xe3, 0xc7, 0x01, 0xc0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x07,
+ 0xc0, 0xff, 0xff, 0x03, 0x80, 0xe3, 0xc7, 0x01, 0x00, 0xe3, 0xc7, 0x00,
+ 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
+ 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const uint8_t whatsthis_bits[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0xf0, 0x07, 0x00,
+ 0x09, 0x18, 0x0e, 0x00, 0x11, 0x1c, 0x0e, 0x00, 0x21, 0x1c, 0x0e, 0x00,
+ 0x41, 0x1c, 0x0e, 0x00, 0x81, 0x1c, 0x0e, 0x00, 0x01, 0x01, 0x07, 0x00,
+ 0x01, 0x82, 0x03, 0x00, 0xc1, 0xc7, 0x01, 0x00, 0x49, 0xc0, 0x01, 0x00,
+ 0x95, 0xc0, 0x01, 0x00, 0x93, 0xc0, 0x01, 0x00, 0x21, 0x01, 0x00, 0x00,
+ 0x20, 0xc1, 0x01, 0x00, 0x40, 0xc2, 0x01, 0x00, 0x40, 0x02, 0x00, 0x00,
+ 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
+static const uint8_t whatsthism_bits[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x07, 0x00, 0x07, 0xf8, 0x0f, 0x00,
+ 0x0f, 0xfc, 0x1f, 0x00, 0x1f, 0x3e, 0x1f, 0x00, 0x3f, 0x3e, 0x1f, 0x00,
+ 0x7f, 0x3e, 0x1f, 0x00, 0xff, 0x3e, 0x1f, 0x00, 0xff, 0x9d, 0x0f, 0x00,
+ 0xff, 0xc3, 0x07, 0x00, 0xff, 0xe7, 0x03, 0x00, 0x7f, 0xe0, 0x03, 0x00,
+ 0xf7, 0xe0, 0x03, 0x00, 0xf3, 0xe0, 0x03, 0x00, 0xe1, 0xe1, 0x03, 0x00,
+ 0xe0, 0xe1, 0x03, 0x00, 0xc0, 0xe3, 0x03, 0x00, 0xc0, 0xe3, 0x03, 0x00,
+ 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
+static const uint8_t busy_bits[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
+ 0x41, 0xe0, 0xff, 0x00, 0x81, 0x20, 0x80, 0x00, 0x01, 0xe1, 0xff, 0x00,
+ 0x01, 0x42, 0x40, 0x00, 0xc1, 0x47, 0x40, 0x00, 0x49, 0x40, 0x55, 0x00,
+ 0x95, 0x80, 0x2a, 0x00, 0x93, 0x00, 0x15, 0x00, 0x21, 0x01, 0x0a, 0x00,
+ 0x20, 0x01, 0x11, 0x00, 0x40, 0x82, 0x20, 0x00, 0x40, 0x42, 0x44, 0x00,
+ 0x80, 0x41, 0x4a, 0x00, 0x00, 0x40, 0x55, 0x00, 0x00, 0xe0, 0xff, 0x00,
+ 0x00, 0x20, 0x80, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static const uint8_t busym_bits[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x0f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0x00, 0xff, 0xe0, 0xff, 0x00, 0xff, 0xe1, 0xff, 0x00,
+ 0xff, 0xc3, 0x7f, 0x00, 0xff, 0xc7, 0x7f, 0x00, 0x7f, 0xc0, 0x7f, 0x00,
+ 0xf7, 0x80, 0x3f, 0x00, 0xf3, 0x00, 0x1f, 0x00, 0xe1, 0x01, 0x0e, 0x00,
+ 0xe0, 0x01, 0x1f, 0x00, 0xc0, 0x83, 0x3f, 0x00, 0xc0, 0xc3, 0x7f, 0x00,
+ 0x80, 0xc1, 0x7f, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00, 0xe0, 0xff, 0x00,
+ 0x00, 0xe0, 0xff, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+static const uint8_t * const cursor_bits32[] = {
+ vsplit_bits, vsplitm_bits, hsplit_bits, hsplitm_bits,
+ 0, 0, 0, 0, whatsthis_bits, whatsthism_bits, busy_bits, busym_bits
+};
+
+static const uint8_t forbidden_bits[] = {
+ 0x00,0x00,0x00,0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xf0,0x00,0x38,0xc0,0x01,
+ 0x7c,0x80,0x03,0xec,0x00,0x03,0xce,0x01,0x07,0x86,0x03,0x06,0x06,0x07,0x06,
+ 0x06,0x0e,0x06,0x06,0x1c,0x06,0x0e,0x38,0x07,0x0c,0x70,0x03,0x1c,0xe0,0x03,
+ 0x38,0xc0,0x01,0xf0,0xe0,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00,0x00,0x00,0x00 };
+
+static const uint8_t forbiddenm_bits[] = {
+ 0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xff,0x00,0xf8,0xff,0x01,0xfc,0xf0,0x03,
+ 0xfe,0xc0,0x07,0xfe,0x81,0x07,0xff,0x83,0x0f,0xcf,0x07,0x0f,0x8f,0x0f,0x0f,
+ 0x0f,0x1f,0x0f,0x0f,0x3e,0x0f,0x1f,0xfc,0x0f,0x1e,0xf8,0x07,0x3e,0xf0,0x07,
+ 0xfc,0xe0,0x03,0xf8,0xff,0x01,0xf0,0xff,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00};
+
+static const uint8_t openhand_bits[] = {
+ 0x80,0x01,0x58,0x0e,0x64,0x12,0x64,0x52,0x48,0xb2,0x48,0x92,
+ 0x16,0x90,0x19,0x80,0x11,0x40,0x02,0x40,0x04,0x40,0x04,0x20,
+ 0x08,0x20,0x10,0x10,0x20,0x10,0x00,0x00};
+static const uint8_t openhandm_bits[] = {
+ 0x80,0x01,0xd8,0x0f,0xfc,0x1f,0xfc,0x5f,0xf8,0xff,0xf8,0xff,
+ 0xf6,0xff,0xff,0xff,0xff,0x7f,0xfe,0x7f,0xfc,0x7f,0xfc,0x3f,
+ 0xf8,0x3f,0xf0,0x1f,0xe0,0x1f,0x00,0x00};
+static const uint8_t closedhand_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0x48,0x32,0x08,0x50,
+ 0x10,0x40,0x18,0x40,0x04,0x40,0x04,0x20,0x08,0x20,0x10,0x10,
+ 0x20,0x10,0x20,0x10,0x00,0x00,0x00,0x00};
+static const uint8_t closedhandm_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0xf8,0x3f,0xf8,0x7f,
+ 0xf0,0x7f,0xf8,0x7f,0xfc,0x7f,0xfc,0x3f,0xf8,0x3f,0xf0,0x1f,
+ 0xe0,0x1f,0xe0,0x1f,0x00,0x00,0x00,0x00};
+
+static const uint8_t * const cursor_bits20[] = {
+ forbidden_bits, forbiddenm_bits
+};
+
+static const char * const cursorNames[] = {
+ "left_ptr",
+ "up_arrow",
+ "cross",
+ "wait",
+ "ibeam",
+ "size_ver",
+ "size_hor",
+ "size_bdiag",
+ "size_fdiag",
+ "size_all",
+ "blank",
+ "split_v",
+ "split_h",
+ "pointing_hand",
+ "forbidden",
+ "whats_this",
+ "left_ptr_watch",
+ "openhand",
+ "closedhand",
+ "copy",
+ "move",
+ "link"
+};
+
+QXcbCursor::QXcbCursor(QXcbConnection *conn, QXcbScreen *screen)
+ : QXcbObject(conn), QPlatformCursor(screen), m_screen(screen)
+{
+ if (cursorCount++)
+ return;
+
+ cursorFont = xcb_generate_id(xcb_connection());
+ const char *cursorStr = "cursor";
+ xcb_open_font(xcb_connection(), cursorFont, strlen(cursorStr), cursorStr);
+
+#ifdef XCB_USE_XLIB
+ QLibrary xcursorLib(QLatin1String("Xcursor"), 1);
+ bool xcursorFound = xcursorLib.load();
+ if (!xcursorFound) { // try without the version number
+ xcursorLib.setFileName(QLatin1String("Xcursor"));
+ xcursorFound = xcursorLib.load();
+ }
+ if (xcursorFound)
+ ptrXcursorLibraryLoadCursor =
+ (PtrXcursorLibraryLoadCursor) xcursorLib.resolve("XcursorLibraryLoadCursor");
+#endif
+}
+
+QXcbCursor::~QXcbCursor()
+{
+ if (!--cursorCount)
+ xcb_close_font(xcb_connection(), cursorFont);
+}
+
+void QXcbCursor::changeCursor(QCursor *cursor, QWindow *widget)
+{
+ 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
+ return;
+
+ xcb_cursor_t c;
+ if (cursor->shape() == Qt::BitmapCursor) {
+ qint64 id = cursor->pixmap().cacheKey();
+ if (!m_bitmapCursorMap.contains(id))
+ m_bitmapCursorMap.insert(id, createBitmapCursor(cursor));
+ c = m_bitmapCursorMap.value(id);
+ } else {
+ int id = cursor->handle();
+ if (!m_shapeCursorMap.contains(id))
+ m_shapeCursorMap.insert(id, createFontCursor(cursor->shape()));
+ c = m_shapeCursorMap.value(id);
+ }
+
+ w->setCursor(c);
+}
+
+static int cursorIdForShape(int cshape)
+{
+ int cursorId = 0;
+ switch (cshape) {
+ case Qt::ArrowCursor:
+ cursorId = XC_left_ptr;
+ break;
+ case Qt::UpArrowCursor:
+ cursorId = XC_center_ptr;
+ break;
+ case Qt::CrossCursor:
+ cursorId = XC_crosshair;
+ break;
+ case Qt::WaitCursor:
+ cursorId = XC_watch;
+ break;
+ case Qt::IBeamCursor:
+ cursorId = XC_xterm;
+ break;
+ case Qt::SizeAllCursor:
+ cursorId = XC_fleur;
+ break;
+ case Qt::PointingHandCursor:
+ cursorId = XC_hand2;
+ break;
+ case Qt::SizeBDiagCursor:
+ cursorId = XC_top_right_corner;
+ break;
+ case Qt::SizeFDiagCursor:
+ cursorId = XC_bottom_right_corner;
+ break;
+ case Qt::SizeVerCursor:
+ case Qt::SplitVCursor:
+ cursorId = XC_sb_v_double_arrow;
+ break;
+ case Qt::SizeHorCursor:
+ case Qt::SplitHCursor:
+ cursorId = XC_sb_h_double_arrow;
+ break;
+ case Qt::WhatsThisCursor:
+ cursorId = XC_question_arrow;
+ break;
+ case Qt::ForbiddenCursor:
+ cursorId = XC_circle;
+ break;
+ case Qt::BusyCursor:
+ cursorId = XC_watch;
+ break;
+ default:
+ break;
+ }
+ return cursorId;
+}
+
+xcb_cursor_t QXcbCursor::createNonStandardCursor(int cshape)
+{
+ xcb_cursor_t cursor = 0;
+ xcb_connection_t *conn = xcb_connection();
+
+ if (cshape == Qt::BlankCursor) {
+ xcb_pixmap_t cp = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(), cur_blank_bits, 16, 16,
+ 1, 0, 0, 0);
+ xcb_pixmap_t mp = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(), cur_blank_bits, 16, 16,
+ 1, 0, 0, 0);
+ cursor = xcb_generate_id(conn);
+ xcb_create_cursor(conn, cursor, cp, mp, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 8, 8);
+ } else if (cshape >= Qt::SizeVerCursor && cshape < Qt::SizeAllCursor) {
+ int i = (cshape - Qt::SizeVerCursor) * 2;
+ xcb_pixmap_t pm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
+ const_cast<uint8_t*>(cursor_bits16[i]),
+ 16, 16, 1, 0, 0, 0);
+ xcb_pixmap_t pmm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
+ const_cast<uint8_t*>(cursor_bits16[i + 1]),
+ 16, 16, 1, 0, 0, 0);
+ cursor = xcb_generate_id(conn);
+ xcb_create_cursor(conn, cursor, pm, pmm, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 8, 8);
+ } else if ((cshape >= Qt::SplitVCursor && cshape <= Qt::SplitHCursor)
+ || cshape == Qt::WhatsThisCursor || cshape == Qt::BusyCursor) {
+ int i = (cshape - Qt::SplitVCursor) * 2;
+ xcb_pixmap_t pm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
+ const_cast<uint8_t*>(cursor_bits32[i]),
+ 32, 32, 1, 0, 0, 0);
+ xcb_pixmap_t pmm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
+ const_cast<uint8_t*>(cursor_bits32[i + 1]),
+ 32, 32, 1, 0, 0, 0);
+ int hs = (cshape == Qt::PointingHandCursor || cshape == Qt::WhatsThisCursor
+ || cshape == Qt::BusyCursor) ? 0 : 16;
+ cursor = xcb_generate_id(conn);
+ xcb_create_cursor(conn, cursor, pm, pmm, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, hs, hs);
+ } else if (cshape == Qt::ForbiddenCursor) {
+ int i = (cshape - Qt::ForbiddenCursor) * 2;
+ xcb_pixmap_t pm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
+ const_cast<uint8_t*>(cursor_bits20[i]),
+ 20, 20, 1, 0, 0, 0);
+ xcb_pixmap_t pmm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
+ const_cast<uint8_t*>(cursor_bits20[i + 1]),
+ 20, 20, 1, 0, 0, 0);
+ cursor = xcb_generate_id(conn);
+ xcb_create_cursor(conn, cursor, pm, pmm, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 10, 10);
+ } else if (cshape == Qt::OpenHandCursor || cshape == Qt::ClosedHandCursor) {
+ bool open = cshape == Qt::OpenHandCursor;
+ xcb_pixmap_t pm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
+ const_cast<uint8_t*>(open ? openhand_bits : closedhand_bits),
+ 16, 16, 1, 0, 0, 0);
+ xcb_pixmap_t pmm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
+ const_cast<uint8_t*>(open ? openhandm_bits : closedhandm_bits),
+ 16, 16, 1, 0, 0, 0);
+ cursor = xcb_generate_id(conn);
+ xcb_create_cursor(conn, cursor, pm, pmm, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 8, 8);
+ } else if (cshape == Qt::DragCopyCursor || cshape == Qt::DragMoveCursor
+ || cshape == Qt::DragLinkCursor) {
+ QImage image = QGuiApplicationPrivate::instance()->getPixmapCursor(static_cast<Qt::CursorShape>(cshape)).toImage();
+ xcb_pixmap_t pm = qt_xcb_XPixmapFromBitmap(m_screen, image);
+ xcb_pixmap_t pmm = qt_xcb_XPixmapFromBitmap(m_screen, image.createAlphaMask());
+ cursor = xcb_generate_id(conn);
+ xcb_create_cursor(conn, cursor, pm, pmm, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 8, 8);
+ }
+
+ return cursor;
+}
+
+xcb_cursor_t QXcbCursor::createFontCursor(int cshape)
+{
+ xcb_connection_t *conn = xcb_connection();
+ int cursorId = cursorIdForShape(cshape);
+ xcb_cursor_t cursor = XCB_NONE;
+
+ // Try Xcursor first
+#ifdef XCB_USE_XLIB
+ if (ptrXcursorLibraryLoadCursor && cshape >= 0 && cshape < Qt::LastCursor) {
+ void *dpy = connection()->xlib_display();
+ // special case for non-standard dnd-* cursors
+ switch (cshape) {
+ case Qt::DragCopyCursor:
+ cursor = ptrXcursorLibraryLoadCursor(dpy, "dnd-copy");
+ break;
+ case Qt::DragMoveCursor:
+ cursor = ptrXcursorLibraryLoadCursor(dpy, "dnd-move");
+ break;
+ case Qt::DragLinkCursor:
+ cursor = ptrXcursorLibraryLoadCursor(dpy, "dnd-link");
+ break;
+ default:
+ break;
+ }
+ if (!cursor)
+ cursor = ptrXcursorLibraryLoadCursor(dpy, cursorNames[cshape]);
+ }
+ if (cursor)
+ return cursor;
+#endif
+
+ // Non-standard X11 cursors are created from bitmaps
+ cursor = createNonStandardCursor(cshape);
+
+ // Create a glpyh cursor if everything else failed
+ if (!cursor && cursorId) {
+ cursor = xcb_generate_id(conn);
+ xcb_create_glyph_cursor(conn, cursor, cursorFont, cursorFont,
+ cursorId, cursorId + 1,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0, 0, 0);
+ }
+
+ if (cursor && cshape >= 0 && cshape < Qt::LastCursor) {
+ const char *name = cursorNames[cshape];
+ xcb_xfixes_set_cursor_name(conn, cursor, strlen(name), name);
+ }
+
+ return cursor;
+}
+
+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_free_pixmap(conn, mp);
+ return c;
+}
+
+static void getPosAndRoot(xcb_connection_t *conn, xcb_window_t *rootWin, QPoint *pos)
+{
+ if (pos)
+ *pos = QPoint();
+ xcb_screen_iterator_t it = xcb_setup_roots_iterator(xcb_get_setup(conn));
+ while (it.rem) {
+ xcb_window_t root = it.data->root;
+ xcb_query_pointer_cookie_t cookie = xcb_query_pointer(conn, root);
+ xcb_generic_error_t *err = 0;
+ xcb_query_pointer_reply_t *reply = xcb_query_pointer_reply(conn, cookie, &err);
+ if (!err && reply) {
+ if (pos)
+ *pos = QPoint(reply->root_x, reply->root_y);
+ if (rootWin)
+ *rootWin = root;
+ free(reply);
+ return;
+ }
+ free(err);
+ free(reply);
+ xcb_screen_next(&it);
+ }
+}
+
+QPoint QXcbCursor::pos() const
+{
+ QPoint p;
+ getPosAndRoot(xcb_connection(), 0, &p);
+ return p;
+}
+
+void QXcbCursor::setPos(const QPoint &pos)
+{
+ xcb_connection_t *conn = xcb_connection();
+ xcb_window_t root;
+ getPosAndRoot(conn, &root, 0);
+ xcb_warp_pointer(conn, XCB_NONE, root, 0, 0, 0, 0, pos.x(), pos.y());
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbcursor.h b/src/plugins/platforms/xcb/qxcbcursor.h
new file mode 100644
index 0000000000..4bbb9a928b
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbcursor.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXCBCURSOR_H
+#define QXCBCURSOR_H
+
+#include <QtGui/QPlatformCursor>
+#include "qxcbscreen.h"
+
+QT_BEGIN_NAMESPACE
+
+class QXcbCursor : public QXcbObject, public QPlatformCursor
+{
+public:
+ QXcbCursor(QXcbConnection *conn, QXcbScreen *screen);
+ ~QXcbCursor();
+ void changeCursor(QCursor *cursor, QWindow *widget);
+ QPoint pos() const;
+ void setPos(const QPoint &pos);
+
+private:
+ xcb_cursor_t createFontCursor(int cshape);
+ xcb_cursor_t createBitmapCursor(QCursor *cursor);
+ xcb_cursor_t createNonStandardCursor(int cshape);
+
+ QXcbScreen *m_screen;
+ QMap<int, xcb_cursor_t> m_shapeCursorMap;
+ QMap<qint64, xcb_cursor_t> m_bitmapCursorMap;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/xcb/qxcbimage.cpp b/src/plugins/platforms/xcb/qxcbimage.cpp
new file mode 100644
index 0000000000..6c8c4e32c8
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbimage.cpp
@@ -0,0 +1,180 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qxcbimage.h"
+#include <QtGui/QColor>
+#include <QtGui/private/qimage_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QImage::Format qt_xcb_imageFormatForVisual(QXcbConnection *connection, uint8_t depth,
+ const xcb_visualtype_t *visual)
+{
+ const xcb_format_t *format = connection->formatForDepth(depth);
+
+ if (!visual || !format)
+ return QImage::Format_Invalid;
+
+ if (depth == 32 && format->bits_per_pixel == 32 && visual->red_mask == 0xff0000
+ && visual->green_mask == 0xff00 && visual->blue_mask == 0xff)
+ return QImage::Format_ARGB32_Premultiplied;
+
+ if (depth == 24 && format->bits_per_pixel == 32 && visual->red_mask == 0xff0000
+ && visual->green_mask == 0xff00 && visual->blue_mask == 0xff)
+ return QImage::Format_RGB32;
+
+ if (depth == 16 && format->bits_per_pixel == 16 && visual->red_mask == 0xf800
+ && visual->green_mask == 0x7e0 && visual->blue_mask == 0x1f)
+ return QImage::Format_RGB16;
+
+ return QImage::Format_Invalid;
+}
+
+QPixmap qt_xcb_pixmapFromXPixmap(QXcbConnection *connection, xcb_pixmap_t pixmap,
+ int width, int height, int depth,
+ const xcb_visualtype_t *visual)
+{
+ xcb_connection_t *conn = connection->xcb_connection();
+ xcb_generic_error_t *error = 0;
+
+ xcb_get_image_cookie_t get_image_cookie =
+ xcb_get_image(conn, XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap,
+ 0, 0, width, height, 0xffffffff);
+
+ xcb_get_image_reply_t *image_reply =
+ xcb_get_image_reply(conn, get_image_cookie, &error);
+
+ if (!image_reply) {
+ if (error) {
+ connection->handleXcbError(error);
+ free(error);
+ }
+ return QPixmap();
+ }
+
+ uint8_t *data = xcb_get_image_data(image_reply);
+ uint32_t length = xcb_get_image_data_length(image_reply);
+
+ QPixmap result;
+
+ QImage::Format format = qt_xcb_imageFormatForVisual(connection, depth, visual);
+ if (format != QImage::Format_Invalid) {
+ uint32_t bytes_per_line = length / height;
+ QImage image(const_cast<uint8_t *>(data), width, height, bytes_per_line, format);
+ uint8_t image_byte_order = connection->setup()->image_byte_order;
+
+ // we may have to swap the byte order
+ if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && image_byte_order == XCB_IMAGE_ORDER_MSB_FIRST)
+ || (QSysInfo::ByteOrder == QSysInfo::BigEndian && image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST))
+ {
+ for (int i=0; i < image.height(); i++) {
+ switch (format) {
+ case QImage::Format_RGB16: {
+ ushort *p = (ushort*)image.scanLine(i);
+ ushort *end = p + image.width();
+ while (p < end) {
+ *p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff);
+ p++;
+ }
+ break;
+ }
+ case QImage::Format_RGB32: // fall-through
+ case QImage::Format_ARGB32_Premultiplied: {
+ uint *p = (uint*)image.scanLine(i);
+ uint *end = p + image.width();
+ while (p < end) {
+ *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000)
+ | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff);
+ p++;
+ }
+ break;
+ }
+ default:
+ Q_ASSERT(false);
+ }
+ }
+ }
+
+ // fix-up alpha channel
+ if (format == QImage::Format_RGB32) {
+ QRgb *p = (QRgb *)image.bits();
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; ++x)
+ p[x] |= 0xff000000;
+ p += bytes_per_line / 4;
+ }
+ }
+
+ result = QPixmap::fromImage(image.copy());
+ }
+
+ free(image_reply);
+ return result;
+}
+
+xcb_pixmap_t qt_xcb_XPixmapFromBitmap(QXcbScreen *screen, const QImage &image)
+{
+ xcb_connection_t *conn = screen->xcb_connection();
+ QImage bitmap = image.convertToFormat(QImage::Format_MonoLSB);
+ const QRgb c0 = QColor(Qt::black).rgb();
+ const QRgb c1 = QColor(Qt::white).rgb();
+ if (bitmap.color(0) == c0 && bitmap.color(1) == c1) {
+ bitmap.invertPixels();
+ bitmap.setColor(0, c1);
+ bitmap.setColor(1, c0);
+ }
+ const int width = bitmap.width();
+ const int height = bitmap.height();
+ const int bytesPerLine = bitmap.bytesPerLine();
+ int destLineSize = width / 8;
+ if (width % 8)
+ ++destLineSize;
+ const uchar *map = bitmap.bits();
+ uint8_t *buf = new uint8_t[height * destLineSize];
+ for (int i = 0; i < height; i++)
+ memcpy(buf + (destLineSize * i), map + (bytesPerLine * i), destLineSize);
+ xcb_pixmap_t pm = xcb_create_pixmap_from_bitmap_data(conn, screen->root(), buf,
+ width, height, 1, 0, 0, 0);
+ delete[] buf;
+ return pm;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbimage.h b/src/plugins/platforms/xcb/qxcbimage.h
new file mode 100644
index 0000000000..39a7abd315
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbimage.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXCBIMAGE_H
+#define QXCBIMAGE_H
+
+#include "qxcbscreen.h"
+#include <QtCore/QPair>
+#include <QtGui/QImage>
+#include <QtGui/QPixmap>
+#include <xcb/xcb_image.h>
+
+QT_BEGIN_NAMESPACE
+
+QImage::Format qt_xcb_imageFormatForVisual(QXcbConnection *connection,
+ uint8_t depth, const xcb_visualtype_t *visual);
+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);
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index a7d88e7741..aa11ba5cb0 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -47,6 +47,7 @@
#include "qxcbnativeinterface.h"
#include "qxcbclipboard.h"
#include "qxcbdrag.h"
+#include "qxcbimage.h"
#include <qgenericunixprintersupport.h>
@@ -123,28 +124,6 @@ QPlatformFontDatabase *QXcbIntegration::fontDatabase() const
return m_fontDatabase;
}
-static QImage::Format imageFormatForVisual(QXcbConnection *connection, uint8_t depth, const xcb_visualtype_t *visual)
-{
- const xcb_format_t *format = connection->formatForDepth(depth);
-
- if (!visual || !format)
- return QImage::Format_Invalid;
-
- if (depth == 32 && format->bits_per_pixel == 32 && visual->red_mask == 0xff0000
- && visual->green_mask == 0xff00 && visual->blue_mask == 0xff)
- return QImage::Format_ARGB32_Premultiplied;
-
- if (depth == 24 && format->bits_per_pixel == 32 && visual->red_mask == 0xff0000
- && visual->green_mask == 0xff00 && visual->blue_mask == 0xff)
- return QImage::Format_RGB32;
-
- if (depth == 16 && format->bits_per_pixel == 16 && visual->red_mask == 0xf800
- && visual->green_mask == 0x7e0 && visual->blue_mask == 0x1f)
- return QImage::Format_RGB16;
-
- return QImage::Format_Invalid;
-}
-
QPixmap QXcbIntegration::grabWindow(WId window, int x, int y, int width, int height) const
{
if (width == 0 || height == 0)
@@ -256,85 +235,12 @@ QPixmap QXcbIntegration::grabWindow(WId window, int x, int y, int width, int hei
free(error);
}
- xcb_get_image_cookie_t get_image_cookie =
- xcb_get_image(connection, XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, 0, 0, width, height, 0xffffffff);
-
- xcb_get_image_reply_t *image_reply =
- xcb_get_image_reply(connection, get_image_cookie, &error);
+ QPixmap result = qt_xcb_pixmapFromXPixmap(m_connection, pixmap, width, height, reply->depth, visual);
+ free(reply);
xcb_free_gc(connection, gc);
xcb_free_pixmap(connection, pixmap);
- uint8_t depth = reply->depth;
-
- free(reply);
-
- if (!image_reply) {
- if (error) {
- m_connection->handleXcbError(error);
- free(error);
- }
- return QPixmap();
- }
-
- uint8_t *data = xcb_get_image_data(image_reply);
- uint32_t length = xcb_get_image_data_length(image_reply);
-
- QPixmap result;
-
- QImage::Format format = imageFormatForVisual(m_connection, depth, visual);
- if (format != QImage::Format_Invalid) {
- uint32_t bytes_per_line = length / height;
- QImage image(const_cast<uint8_t *>(data), width, height, bytes_per_line, format);
- uint8_t image_byte_order = m_connection->setup()->image_byte_order;
-
- // we may have to swap the byte order
- if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && image_byte_order == XCB_IMAGE_ORDER_MSB_FIRST)
- || (QSysInfo::ByteOrder == QSysInfo::BigEndian && image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST))
- {
- for (int i=0; i < image.height(); i++) {
- switch (format) {
- case QImage::Format_RGB16: {
- ushort *p = (ushort*)image.scanLine(i);
- ushort *end = p + image.width();
- while (p < end) {
- *p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff);
- p++;
- }
- break;
- }
- case QImage::Format_RGB32: // fall-through
- case QImage::Format_ARGB32_Premultiplied: {
- uint *p = (uint*)image.scanLine(i);
- uint *end = p + image.width();
- while (p < end) {
- *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000)
- | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff);
- p++;
- }
- break;
- }
- default:
- Q_ASSERT(false);
- }
- }
- }
-
- // fix-up alpha channel
- if (format == QImage::Format_RGB32) {
- QRgb *p = (QRgb *)image.bits();
- for (int y = 0; y < height; ++y) {
- for (int x = 0; x < width; ++x)
- p[x] |= 0xff000000;
- p += bytes_per_line / 4;
- }
- }
-
- result = QPixmap::fromImage(image.copy());
- }
-
- free(image_reply);
-
return result;
}
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 0d0c4a5138..6c3d1813b0 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -41,6 +41,7 @@
#include "qxcbscreen.h"
#include "qxcbwindow.h"
+#include "qxcbcursor.h"
#include <stdio.h>
@@ -140,10 +141,13 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int num
xcb_depth_next(&depth_iterator);
}
+
+ m_cursor = new QXcbCursor(connection, this);
}
QXcbScreen::~QXcbScreen()
{
+ delete m_cursor;
}
QWindow *QXcbScreen::topLevelAt(const QPoint &p) const
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index cb84e55ccc..5b8492faa5 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -50,6 +50,7 @@
#include "qxcbobject.h"
class QXcbConnection;
+class QXcbCursor;
class QXcbScreen : public QXcbObject, public QPlatformScreen
{
@@ -83,6 +84,7 @@ private:
bool m_syncRequestSupported;
xcb_window_t m_clientLeader;
QMap<xcb_visualid_t, xcb_visualtype_t> m_visuals;
+ QXcbCursor *m_cursor;
};
#endif
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 09b92b2fbf..de48c83cd1 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -1234,3 +1234,9 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab)
free(err);
return result;
}
+
+void QXcbWindow::setCursor(xcb_cursor_t cursor)
+{
+ xcb_change_window_attributes(xcb_connection(), m_window, XCB_CW_CURSOR, &cursor);
+ xcb_flush(xcb_connection());
+}
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index 0412f4a75e..f6869c7937 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -79,6 +79,8 @@ public:
bool setKeyboardGrabEnabled(bool grab);
bool setMouseGrabEnabled(bool grab);
+ void setCursor(xcb_cursor_t cursor);
+
xcb_window_t xcb_window() const { return m_window; }
uint depth() const { return m_depth; }
QImage::Format format() const { return m_format; }
diff --git a/src/plugins/platforms/xcb/xcb.pro b/src/plugins/platforms/xcb/xcb.pro
index 2f70b659c9..0d9e969ddc 100644
--- a/src/plugins/platforms/xcb/xcb.pro
+++ b/src/plugins/platforms/xcb/xcb.pro
@@ -17,7 +17,9 @@ SOURCES = \
qxcbwindowsurface.cpp \
qxcbwmsupport.cpp \
main.cpp \
- qxcbnativeinterface.cpp
+ qxcbnativeinterface.cpp \
+ qxcbcursor.cpp \
+ qxcbimage.cpp
HEADERS = \
qxcbclipboard.h \
@@ -31,16 +33,21 @@ HEADERS = \
qxcbwindow.h \
qxcbwindowsurface.h \
qxcbwmsupport.h \
- qxcbnativeinterface.h
+ qxcbnativeinterface.h \
+ qxcbcursor.h \
+ qxcbimage.h
QT += gui-private core-private
+# needed by GLX, Xcursor, ...
+DEFINES += XCB_USE_XLIB
+
contains(QT_CONFIG, opengl) {
QT += opengl
# DEFINES += XCB_USE_DRI2
contains(DEFINES, XCB_USE_DRI2) {
- LIBS += -lxcb-dri2 -lxcb-xfixes -lEGL
+ LIBS += -lxcb-dri2 -lEGL
CONFIG += link_pkgconfig
PKGCONFIG += libdrm
@@ -49,9 +56,6 @@ contains(QT_CONFIG, opengl) {
SOURCES += qdri2context.cpp
} else {
- DEFINES += XCB_USE_XLIB
- LIBS += -lX11 -lX11-xcb
-
contains(QT_CONFIG, opengles2) {
DEFINES += XCB_USE_EGL
load(qpa/egl/convenience)
@@ -68,7 +72,8 @@ contains(QT_CONFIG, opengl) {
}
}
-LIBS += -lxcb -lxcb-image -lxcb-keysyms -lxcb-icccm -lxcb-sync
+LIBS += -lxcb -lxcb-image -lxcb-keysyms -lxcb-icccm -lxcb-sync -lxcb-xfixes
+contains(DEFINES, XCB_USE_XLIB): LIBS += -lX11 -lX11-xcb
DEFINES += $$QMAKE_DEFINES_XCB
LIBS += $$QMAKE_LIBS_XCB
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 6c92e0bb94..9a7ad9fc0c 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -3348,6 +3348,12 @@ void QWidgetPrivate::setEnabled_helper(bool enable)
// disabled widgets
qt_x11_enforce_cursor(q);
}
+#elif defined(Q_WS_QPA)
+ if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) {
+ // enforce the windows behavior of clearing the cursor on
+ // disabled widgets
+ qt_qpa_set_cursor(q, false);
+ }
#endif
#if defined(Q_WS_MAC)
setEnabled_helper_sys(enable);
diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
index cc894d514d..46c5ecfe33 100644
--- a/src/widgets/kernel/qwidget_p.h
+++ b/src/widgets/kernel/qwidget_p.h
@@ -903,9 +903,6 @@ public:
void setFullScreenSize_helper();
bool stealKeyboardGrab(bool grab);
bool stealMouseGrab(bool grab);
-#ifndef QT_NO_CURSOR
- void updateCursor() const;
-#endif
#elif defined(Q_OS_SYMBIAN) // <--------------------------------------------------------- SYMBIAN
static QWidget *mouseGrabber;
static QWidget *keyboardGrabber;
diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp
index 4bf8d5dd73..66a1a4ce35 100644
--- a/src/widgets/kernel/qwidget_qpa.cpp
+++ b/src/widgets/kernel/qwidget_qpa.cpp
@@ -299,20 +299,13 @@ void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
{
Q_UNUSED(cursor);
Q_Q(QWidget);
- if (q->isVisible())
- qt_qpa_set_cursor(q, false);
+ qt_qpa_set_cursor(q, false);
}
void QWidgetPrivate::unsetCursor_sys()
{
Q_Q(QWidget);
- if (q->isVisible())
- qt_qpa_set_cursor(q, false);
-}
-
-void QWidgetPrivate::updateCursor() const
-{
- // XXX
+ qt_qpa_set_cursor(q, false);
}
#endif //QT_NO_CURSOR
@@ -858,56 +851,55 @@ void QWidgetPrivate::setModal_sys()
}
#ifndef QT_NO_CURSOR
-void qt_qpa_set_cursor(QWidget * w, bool force)
+static void applyCursor(QWidget *w, const QCursor &c)
{
- static QCursor arrowCursor(Qt::ArrowCursor);
- static QPointer<QWidget> lastUnderMouse = 0;
-
- QCursor * override = QApplication::overrideCursor();
+ QCursor cc = c;
+ QList<QWeakPointer<QPlatformCursor> > cursors = QPlatformCursorPrivate::getInstances();
+ int cursorCount = cursors.count();
+ for (int i = 0; i < cursorCount; ++i) {
+ const QWeakPointer<QPlatformCursor> &cursor(cursors.at(i));
+ if (cursor)
+ cursor.data()->changeCursor(&cc, w->window()->windowHandle());
+ }
+}
- if (override && w != 0)
+void qt_qpa_set_cursor(QWidget *w, bool force)
+{
+ if (!w->testAttribute(Qt::WA_WState_Created))
return;
- QWidget *cursorWidget;
- QCursor cursorCursor;
-
- do {
- if (w == 0) {
- if (override) {
- cursorCursor = *override;
- cursorWidget = QApplication::topLevelAt(QCursor::pos());
- break;
- }
- w = QApplication::widgetAt(QCursor::pos());
- if (w == 0) // clear the override cursor while over empty space
- w = QApplication::desktop();
- } else if (force) {
- lastUnderMouse = w;
- } else if (w->testAttribute(Qt::WA_WState_Created) && lastUnderMouse
- && lastUnderMouse->effectiveWinId() == w->effectiveWinId()) {
- w = lastUnderMouse;
- }
- if (w == QApplication::desktop() && !override) {
- cursorCursor = arrowCursor;
- cursorWidget = w;
- break;
- }
+ static QPointer<QWidget> lastUnderMouse = 0;
+ if (force) {
+ lastUnderMouse = w;
+ } else if (lastUnderMouse && lastUnderMouse->effectiveWinId() == w->effectiveWinId()) {
+ w = lastUnderMouse;
+ } else if (!w->internalWinId()) {
+ return; // The mouse is not under this widget, and it's not native, so don't change it.
+ }
- QWidget * curWin = QApplication::activeWindow();
- if (!curWin && w && w->internalWinId())
- return;
- QWidget* cW = w && !w->internalWinId() ? w : curWin;
+ while (!w->internalWinId() && w->parentWidget() && !w->isWindow()
+ && !w->testAttribute(Qt::WA_SetCursor))
+ w = w->parentWidget();
- if (!cW || cW->window() != w->window() ||
- !cW->isVisible() || !cW->underMouse() || override)
- return;
+ QWidget *nativeParent = w;
+ if (!w->internalWinId())
+ nativeParent = w->nativeParentWidget();
+ if (!nativeParent || !nativeParent->internalWinId())
+ return;
- cursorCursor = w->cursor();
- cursorWidget = w;
- } while (0);
- foreach (QWeakPointer<QPlatformCursor> cursor, QPlatformCursorPrivate::getInstances())
- if (cursor)
- cursor.data()->changeCursor(&cursorCursor, cursorWidget->windowHandle());
+ if (w->isWindow() || w->testAttribute(Qt::WA_SetCursor)) {
+ QCursor *oc = QApplication::overrideCursor();
+ if (oc)
+ applyCursor(nativeParent, *oc);
+ else if (w->isEnabled())
+ applyCursor(nativeParent, w->cursor());
+ else
+ // Enforce the windows behavior of clearing the cursor on
+ // disabled widgets.
+ applyCursor(nativeParent, Qt::ArrowCursor);
+ } else {
+ applyCursor(nativeParent, Qt::ArrowCursor);
+ }
}
#endif //QT_NO_CURSOR