Cursor support in xcb plug-in.
authorLaszlo Agocs <laszlo.p.agocs@nokia.com>
Tue, 7 Jun 2011 13:38:45 +0000 (15:38 +0200)
committerLaszlo Agocs <laszlo.p.agocs@nokia.com>
Wed, 8 Jun 2011 12:47:22 +0000 (14:47 +0200)
Custom cursor pixmaps with depth greater than 1 are not yet supported
and will be converted to monochrome always.

Reviewed-by: Samuel Rødal
19 files changed:
src/gui/kernel/qcursor_qpa.cpp
src/gui/kernel/qguiapplication.cpp
src/gui/kernel/qplatformcursor_qpa.cpp
src/gui/kernel/qplatformcursor_qpa.h
src/plugins/platforms/xcb/qxcbconnection.cpp
src/plugins/platforms/xcb/qxcbconnection.h
src/plugins/platforms/xcb/qxcbcursor.cpp [new file with mode: 0644]
src/plugins/platforms/xcb/qxcbcursor.h [new file with mode: 0644]
src/plugins/platforms/xcb/qxcbimage.cpp [new file with mode: 0644]
src/plugins/platforms/xcb/qxcbimage.h [new file with mode: 0644]
src/plugins/platforms/xcb/qxcbintegration.cpp
src/plugins/platforms/xcb/qxcbscreen.cpp
src/plugins/platforms/xcb/qxcbscreen.h
src/plugins/platforms/xcb/qxcbwindow.cpp
src/plugins/platforms/xcb/qxcbwindow.h
src/plugins/platforms/xcb/xcb.pro
src/widgets/kernel/qwidget.cpp
src/widgets/kernel/qwidget_p.h
src/widgets/kernel/qwidget_qpa.cpp

index c0b27be..a292760 100644 (file)
@@ -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
index 80b4aa3..468e8c3 100644 (file)
@@ -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);
index b399410..4c98098 100644 (file)
@@ -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
index 89091b5..af40c7d 100644 (file)
@@ -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
index 94c30a9..1f966b1 100644 (file)
@@ -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) {
index aa54229..b148b56 100644 (file)
@@ -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 (file)
index 0000000..cf1e527
--- /dev/null
@@ -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 (file)
index 0000000..4bbb9a9
--- /dev/null
@@ -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 (file)
index 0000000..6c8c4e3
--- /dev/null
@@ -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 (file)
index 0000000..39a7abd
--- /dev/null
@@ -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
index a7d88e7..aa11ba5 100644 (file)
@@ -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;
 }
 
index 0d0c4a5..6c3d181 100644 (file)
@@ -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
index cb84e55..5b8492f 100644 (file)
@@ -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
index 09b92b2..de48c83 100644 (file)
@@ -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());
+}
index 0412f4a..f6869c7 100644 (file)
@@ -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; }
index 2f70b65..0d9e969 100644 (file)
@@ -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
index 6c92e0b..9a7ad9f 100644 (file)
@@ -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);
index cc894d5..46c5ecf 100644 (file)
@@ -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;
index 4bf8d5d..66a1a4c 100644 (file)
@@ -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