diff options
author | Friedemann Kleint <Friedemann.Kleint@digia.com> | 2013-01-14 10:00:12 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-01-21 21:50:45 +0100 |
commit | c24a7377dd9cfb503b43ef3f5a2d5cac9a4e1b8c (patch) | |
tree | 6b1edaa34485618cc1bec879899a8eadffe2bd2a /src/gui | |
parent | 1029049e1d8aa84f19fe344e605849c36522a97f (diff) |
Regression: Fix setting of custom cursors for native widgets.
Currently, there is no concept of not having a cursor set on
a Window. Qt::ArrowCursor is always set instead. This causes
bugs when native child widgets are involved, for example setting
a cursor on the native widget's parent no longer works since
the child's Qt::ArrowCursor applies.
Introduce QWindowPrivate::hasCursor tracking whether a cursor
has been explicitly set and clear in QWindow::unsetCursor().
Handle 0 in QPlatformCursor::changeCursor() to mean
"unsetCursor()":
- Windows: Introduce default constructor for QWindowsWindowCursor
meaning "0". Search for applicable parent cursor in applyCursor.
- XCB: No big changes required, set XCB_CURSOR_NONE for no cursor.
- Other platforms: Assume Qt::ArrowCursor when cursor = 0 is
passed for now.
Task-number: QTBUG-28879
Change-Id: Id82722592f3cd5fe577a5b64dcc600c85cfea484
Reviewed-by: Jonathan Liu <net147@gmail.com>
Reviewed-by: Morten Johan Sørvig <morten.sorvig@digia.com>
Reviewed-by: Samuel Rødal <samuel.rodal@digia.com>
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/kernel/qguiapplication.cpp | 16 | ||||
-rw-r--r-- | src/gui/kernel/qplatformcursor.cpp | 4 | ||||
-rw-r--r-- | src/gui/kernel/qwindow.cpp | 44 | ||||
-rw-r--r-- | src/gui/kernel/qwindow_p.h | 3 |
4 files changed, 53 insertions, 14 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 190d52776a..aa3bb0ed60 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -2629,6 +2629,13 @@ static inline void applyCursor(QWindow *w, QCursor c) cursor->changeCursor(&c, w); } +static inline void unsetCursor(QWindow *w) +{ + if (const QScreen *screen = w->screen()) + if (QPlatformCursor *cursor = screen->handle()->cursor()) + cursor->changeCursor(0, w); +} + static inline void applyCursor(const QList<QWindow *> &l, const QCursor &c) { for (int i = 0; i < l.size(); ++i) { @@ -2642,8 +2649,13 @@ static inline void applyWindowCursor(const QList<QWindow *> &l) { for (int i = 0; i < l.size(); ++i) { QWindow *w = l.at(i); - if (w->handle() && w->type() != Qt::Desktop) - applyCursor(w, w->cursor()); + if (w->handle() && w->type() != Qt::Desktop) { + if (qt_window_private(w)->hasCursor) { + applyCursor(w, w->cursor()); + } else { + unsetCursor(w); + } + } } } diff --git a/src/gui/kernel/qplatformcursor.cpp b/src/gui/kernel/qplatformcursor.cpp index 6e2c12bf39..a28617cb37 100644 --- a/src/gui/kernel/qplatformcursor.cpp +++ b/src/gui/kernel/qplatformcursor.cpp @@ -95,6 +95,10 @@ QList<QPlatformCursor *> QPlatformCursorPrivate::getInstances() \a windowCursor is a pointer to the QCursor that should be displayed. + To unset the cursor of \a window, 0 is passed. This means \a window does not have + a cursor set and the cursor of a the first parent window which has a cursor explicitly + set or the system default cursor should take effect. + \a window is a pointer to the window currently displayed at QCursor::pos(). Note that this may be 0 if the current position is not occupied by a displayed widget. diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 22ad748fb5..b05d6c577e 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -284,7 +284,7 @@ void QWindow::setVisible(bool visible) } #ifndef QT_NO_CURSOR - if (visible) + if (visible && d->hasCursor) d->applyCursor(); #endif d->platformWindow->setVisible(visible); @@ -1947,13 +1947,7 @@ void QWindowPrivate::maybeQuitOnLastWindowClosed() void QWindow::setCursor(const QCursor &cursor) { Q_D(QWindow); - d->cursor = cursor; - // Only attempt to set cursor and emit signal if there is an actual platform cursor - if (d->screen->handle()->cursor()) { - d->applyCursor(); - QEvent event(QEvent::CursorChange); - QGuiApplication::sendEvent(this, &event); - } + d->setCursor(&cursor); } /*! @@ -1961,7 +1955,8 @@ void QWindow::setCursor(const QCursor &cursor) */ void QWindow::unsetCursor() { - setCursor(Qt::ArrowCursor); + Q_D(QWindow); + d->setCursor(0); } /*! @@ -1975,14 +1970,39 @@ QCursor QWindow::cursor() const return d->cursor; } +void QWindowPrivate::setCursor(const QCursor *newCursor) +{ + + Q_Q(QWindow); + if (newCursor) { + const Qt::CursorShape newShape = newCursor->shape(); + if (newShape <= Qt::LastCursor && hasCursor && newShape == cursor.shape()) + return; // Unchanged and no bitmap/custom cursor. + cursor = *newCursor; + hasCursor = true; + } else { + if (!hasCursor) + return; + cursor = QCursor(Qt::ArrowCursor); + hasCursor = false; + } + // Only attempt to set cursor and emit signal if there is an actual platform cursor + if (screen->handle()->cursor()) { + applyCursor(); + QEvent event(QEvent::CursorChange); + QGuiApplication::sendEvent(q, &event); + } +} + void QWindowPrivate::applyCursor() { Q_Q(QWindow); if (platformWindow) { if (QPlatformCursor *platformCursor = screen->handle()->cursor()) { - QCursor *oc = QGuiApplication::overrideCursor(); - QCursor c = oc ? *oc : cursor; - platformCursor->changeCursor(&c, q); + QCursor *c = QGuiApplication::overrideCursor(); + if (!c && hasCursor) + c = &cursor; + platformCursor->changeCursor(c, q); } } } diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h index 305888d02c..5282c60640 100644 --- a/src/gui/kernel/qwindow_p.h +++ b/src/gui/kernel/qwindow_p.h @@ -98,6 +98,7 @@ public: , screen(0) #ifndef QT_NO_CURSOR , cursor(Qt::ArrowCursor) + , hasCursor(false) #endif { isWindow = true; @@ -109,6 +110,7 @@ public: void maybeQuitOnLastWindowClosed(); #ifndef QT_NO_CURSOR + void setCursor(const QCursor *c = 0); void applyCursor(); #endif @@ -151,6 +153,7 @@ public: #ifndef QT_NO_CURSOR QCursor cursor; + bool hasCursor; #endif }; |