diff options
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/kernel/qguiapplication.cpp | 67 | ||||
-rw-r--r-- | src/gui/kernel/qguiapplication_p.h | 8 | ||||
-rw-r--r-- | src/gui/kernel/qsimpledrag.cpp | 41 | ||||
-rw-r--r-- | src/gui/kernel/qsimpledrag_p.h | 8 | ||||
-rw-r--r-- | src/gui/kernel/qwindowsysteminterface.cpp | 38 | ||||
-rw-r--r-- | src/gui/kernel/qwindowsysteminterface.h | 17 |
6 files changed, 143 insertions, 36 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index caa8aaca4b..22f4cdeaa3 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1679,7 +1679,7 @@ Qt::KeyboardModifiers QGuiApplication::queryKeyboardModifiers() /*! Returns the current state of the buttons on the mouse. The current state is - updated syncronously as the event queue is emptied of events that will + updated synchronously as the event queue is emptied of events that will spontaneously change the mouse state (QEvent::MouseButtonPress and QEvent::MouseButtonRelease events). @@ -3036,8 +3036,56 @@ void QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::E #ifndef QT_NO_DRAGANDDROP -QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions) +/*! \internal + + This function updates an internal state to keep the source compatibility. Documentation of + QGuiApplication::mouseButtons() states - "The current state is updated synchronously as + the event queue is emptied of events that will spontaneously change the mouse state + (QEvent::MouseButtonPress and QEvent::MouseButtonRelease events)". But internally we have + been updating these state variables from various places to keep buttons returned by + mouseButtons() in sync with the systems state. This is not the documented behavior. + + ### Qt6 - Remove QGuiApplication::mouseButtons()/keyboardModifiers() API? And here + are the reasons: + + - It is an easy to misuse API by: + + a) Application developers: The only place where the values of this API can be trusted is + when using within mouse handling callbacks. In these callbacks we work with the state + that was provided directly by the windowing system. Anywhere else it might not reflect what + user wrongly expects. We might not always receive a matching mouse release for a press event + (e.g. When dismissing a popup window on X11. Or when dnd enter Qt application with mouse + button down, we update mouse_buttons and then dnd leaves Qt application and does a drop + somewhere else) and hence mouseButtons() will be out-of-sync from users perspective, see + for example QTBUG-33161. BUT THIS IS NOT HOW THE API IS SUPPOSED TO BE USED. Since the only + safe place to use this API is from mouse event handlers, we might as well deprecate it and + pass down the button state if we are not already doing that everywhere where it matters. + + b) Qt framework developers: + + We see users complaining, we start adding hacks everywhere just to keep buttons in sync ;) + There are corner cases that can not be solved and adding this kind of hacks is never ending + task. + + - Real mouse events, tablet mouse events, etc: all go through QGuiApplication::processMouseEvent, + and all share mouse_buttons. What if we want to support multiple mice in future? The API must + go. + + - Motivation why this API is public is not clear. Could the same be achieved by a user by + installing an event filter? +*/ +static void updateMouseAndModifierButtonState(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) +{ + QGuiApplicationPrivate::mouse_buttons = buttons; + QGuiApplicationPrivate::modifier_buttons = modifiers; +} + +QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QMimeData *dropData, + const QPoint &p, Qt::DropActions supportedActions, + Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) { + updateMouseAndModifierButtonState(buttons, modifiers); + static QPointer<QWindow> currentDragWindow; static Qt::DropAction lastAcceptedDropAction = Qt::IgnoreAction; QPlatformDrag *platformDrag = platformIntegration()->drag(); @@ -3054,8 +3102,7 @@ QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QM lastAcceptedDropAction = Qt::IgnoreAction; return QPlatformDragQtResponse(false, lastAcceptedDropAction, QRect()); } - QDragMoveEvent me(p, supportedActions, dropData, - QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers()); + QDragMoveEvent me(p, supportedActions, dropData, buttons, modifiers); if (w != currentDragWindow) { lastAcceptedDropAction = Qt::IgnoreAction; @@ -3064,8 +3111,7 @@ QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QM QGuiApplication::sendEvent(currentDragWindow, &e); } currentDragWindow = w; - QDragEnterEvent e(p, supportedActions, dropData, - QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers()); + QDragEnterEvent e(p, supportedActions, dropData, buttons, modifiers); QGuiApplication::sendEvent(w, &e); if (e.isAccepted() && e.dropAction() != Qt::IgnoreAction) lastAcceptedDropAction = e.dropAction(); @@ -3083,10 +3129,13 @@ QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QM return QPlatformDragQtResponse(me.isAccepted(), lastAcceptedDropAction, me.answerRect()); } -QPlatformDropQtResponse QGuiApplicationPrivate::processDrop(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions) +QPlatformDropQtResponse QGuiApplicationPrivate::processDrop(QWindow *w, const QMimeData *dropData, + const QPoint &p, Qt::DropActions supportedActions, + Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) { - QDropEvent de(p, supportedActions, dropData, - QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers()); + updateMouseAndModifierButtonState(buttons, modifiers); + + QDropEvent de(p, supportedActions, dropData, buttons, modifiers); QGuiApplication::sendEvent(w, &de); Qt::DropAction acceptedAction = de.isAccepted() ? de.dropAction() : Qt::IgnoreAction; diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index 75cbc7abde..243cbde8af 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -163,8 +163,12 @@ public: #endif #ifndef QT_NO_DRAGANDDROP - static QPlatformDragQtResponse processDrag(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions); - static QPlatformDropQtResponse processDrop(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions); + static QPlatformDragQtResponse processDrag(QWindow *w, const QMimeData *dropData, + const QPoint &p, Qt::DropActions supportedActions, + Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers); + static QPlatformDropQtResponse processDrop(QWindow *w, const QMimeData *dropData, + const QPoint &p, Qt::DropActions supportedActions, + Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers); #endif static bool processNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result); diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp index c98b879a15..ed96584597 100644 --- a/src/gui/kernel/qsimpledrag.cpp +++ b/src/gui/kernel/qsimpledrag.cpp @@ -160,7 +160,8 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e) case QEvent::MouseMove: { QPoint nativePosition = getNativeMousePos(e, m_drag_icon_window); - move(nativePosition); + auto mouseMove = static_cast<QMouseEvent *>(e); + move(nativePosition, mouseMove->buttons(), mouseMove->modifiers()); return true; // Eat all mouse move events } case QEvent::MouseButtonRelease: @@ -168,7 +169,8 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e) disableEventFilter(); if (canDrop()) { QPoint nativePosition = getNativeMousePos(e, m_drag_icon_window); - drop(nativePosition); + auto mouseRelease = static_cast<QMouseEvent *>(e); + drop(nativePosition, mouseRelease->buttons(), mouseRelease->modifiers()); } else { cancel(); } @@ -289,7 +291,7 @@ void QBasicDrag::moveShapedPixmapWindow(const QPoint &globalPos) m_drag_icon_window->updateGeometry(globalPos); } -void QBasicDrag::drop(const QPoint &) +void QBasicDrag::drop(const QPoint &, Qt::MouseButtons, Qt::KeyboardModifiers) { disableEventFilter(); restoreCursor(); @@ -377,9 +379,18 @@ QSimpleDrag::QSimpleDrag() void QSimpleDrag::startDrag() { QBasicDrag::startDrag(); + // Here we can be fairly sure that QGuiApplication::mouseButtons/keyboardModifiers() will + // contain sensible values as startDrag() normally is called from mouse event handlers + // by QDrag::exec(). A better API would be if we could pass something like "input device + // pointer" to QDrag::exec(). My guess is that something like that might be required for + // QTBUG-52430. m_current_window = topLevelAt(QCursor::pos()); if (m_current_window) { - QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_current_window, drag()->mimeData(), QHighDpi::toNativePixels(QCursor::pos(), m_current_window), drag()->supportedActions()); + auto nativePixelPos = QHighDpi::toNativePixels(QCursor::pos(), m_current_window); + QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag( + m_current_window, drag()->mimeData(), nativePixelPos, + drag()->supportedActions(), QGuiApplication::mouseButtons(), + QGuiApplication::keyboardModifiers()); setCanDrop(response.isAccepted()); updateCursor(response.acceptedAction()); } else { @@ -394,12 +405,13 @@ void QSimpleDrag::cancel() { QBasicDrag::cancel(); if (drag() && m_current_window) { - QWindowSystemInterface::handleDrag(m_current_window, 0, QPoint(), Qt::IgnoreAction); - m_current_window = 0; + QWindowSystemInterface::handleDrag(m_current_window, nullptr, QPoint(), Qt::IgnoreAction, 0, 0); + m_current_window = nullptr; } } -void QSimpleDrag::move(const QPoint &nativeGlobalPos) +void QSimpleDrag::move(const QPoint &nativeGlobalPos, Qt::MouseButtons buttons, + Qt::KeyboardModifiers modifiers) { QPoint globalPos = fromNativeGlobalPixels(nativeGlobalPos); moveShapedPixmapWindow(globalPos); @@ -408,25 +420,28 @@ void QSimpleDrag::move(const QPoint &nativeGlobalPos) return; const QPoint pos = nativeGlobalPos - window->handle()->geometry().topLeft(); - const QPlatformDragQtResponse qt_response = - QWindowSystemInterface::handleDrag(window, drag()->mimeData(), pos, drag()->supportedActions()); + const QPlatformDragQtResponse qt_response = QWindowSystemInterface::handleDrag( + window, drag()->mimeData(), pos, drag()->supportedActions(), + buttons, modifiers); updateCursor(qt_response.acceptedAction()); setCanDrop(qt_response.isAccepted()); } -void QSimpleDrag::drop(const QPoint &nativeGlobalPos) +void QSimpleDrag::drop(const QPoint &nativeGlobalPos, Qt::MouseButtons buttons, + Qt::KeyboardModifiers modifiers) { QPoint globalPos = fromNativeGlobalPixels(nativeGlobalPos); - QBasicDrag::drop(nativeGlobalPos); + QBasicDrag::drop(nativeGlobalPos, buttons, modifiers); QWindow *window = topLevelAt(globalPos); if (!window) return; const QPoint pos = nativeGlobalPos - window->handle()->geometry().topLeft(); - const QPlatformDropQtResponse response = - QWindowSystemInterface::handleDrop(window, drag()->mimeData(),pos, drag()->supportedActions()); + const QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop( + window, drag()->mimeData(), pos, drag()->supportedActions(), + buttons, modifiers); if (response.isAccepted()) { setExecutedDropAction(response.acceptedAction()); } else { diff --git a/src/gui/kernel/qsimpledrag_p.h b/src/gui/kernel/qsimpledrag_p.h index e56c7bf306..44b8ee2488 100644 --- a/src/gui/kernel/qsimpledrag_p.h +++ b/src/gui/kernel/qsimpledrag_p.h @@ -82,8 +82,8 @@ protected: virtual void startDrag(); virtual void cancel(); - virtual void move(const QPoint &globalPos) = 0; - virtual void drop(const QPoint &globalPos) = 0; + virtual void move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) = 0; + virtual void drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) = 0; virtual void endDrag(); @@ -132,8 +132,8 @@ public: protected: virtual void startDrag() override; virtual void cancel() override; - virtual void move(const QPoint &globalPos) override; - virtual void drop(const QPoint &globalPos) override; + virtual void move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) override; + virtual void drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) override; }; #endif // QT_NO_DRAGANDDROP diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 1b964ba913..cf3d13e670 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -791,14 +791,44 @@ void QWindowSystemInterface::handleThemeChange(QWindow *window) } #ifndef QT_NO_DRAGANDDROP -QPlatformDragQtResponse QWindowSystemInterface::handleDrag(QWindow *window, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions) +#if QT_DEPRECATED_SINCE(5, 11) +QPlatformDragQtResponse QWindowSystemInterface::handleDrag(QWindow *window, const QMimeData *dropData, + const QPoint &p, Qt::DropActions supportedActions) +{ + return QGuiApplicationPrivate::processDrag(window, dropData, p, supportedActions, + QGuiApplication::mouseButtons(), + QGuiApplication::keyboardModifiers()); +} + +QPlatformDropQtResponse QWindowSystemInterface::handleDrop(QWindow *window, const QMimeData *dropData, + const QPoint &p, Qt::DropActions supportedActions) +{ + return QGuiApplicationPrivate::processDrop(window, dropData, p, supportedActions, + QGuiApplication::mouseButtons(), + QGuiApplication::keyboardModifiers()); +} +#endif // QT_DEPRECATED_SINCE(5, 11) +/*! + Drag and drop events are sent immediately. + + ### FIXME? Perhaps DnD API should add some convenience APIs that are more + intuitive for the possible DND operations. Here passing nullptr as drop data is used to + indicate that drop was canceled and QDragLeaveEvent should be sent as a result. +*/ +QPlatformDragQtResponse QWindowSystemInterface::handleDrag(QWindow *window, const QMimeData *dropData, + const QPoint &p, Qt::DropActions supportedActions, + Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) { - return QGuiApplicationPrivate::processDrag(window, dropData, QHighDpi::fromNativeLocalPosition(p, window) ,supportedActions); + auto pos = QHighDpi::fromNativeLocalPosition(p, window); + return QGuiApplicationPrivate::processDrag(window, dropData, pos, supportedActions, buttons, modifiers); } -QPlatformDropQtResponse QWindowSystemInterface::handleDrop(QWindow *window, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions) +QPlatformDropQtResponse QWindowSystemInterface::handleDrop(QWindow *window, const QMimeData *dropData, + const QPoint &p, Qt::DropActions supportedActions, + Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) { - return QGuiApplicationPrivate::processDrop(window, dropData, QHighDpi::fromNativeLocalPosition(p, window),supportedActions); + auto pos = QHighDpi::fromNativeLocalPosition(p, window); + return QGuiApplicationPrivate::processDrop(window, dropData, pos, supportedActions, buttons, modifiers); } #endif // QT_NO_DRAGANDDROP diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index d584374fca..16337e1986 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -215,10 +215,19 @@ public: static void handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate = false); #ifndef QT_NO_DRAGANDDROP - // Drag and drop. These events are sent immediately. - static QPlatformDragQtResponse handleDrag(QWindow *window, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions); - static QPlatformDropQtResponse handleDrop(QWindow *window, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions); -#endif +#if QT_DEPRECATED_SINCE(5, 11) + QT_DEPRECATED static QPlatformDragQtResponse handleDrag(QWindow *window, const QMimeData *dropData, + const QPoint &p, Qt::DropActions supportedActions); + QT_DEPRECATED static QPlatformDropQtResponse handleDrop(QWindow *window, const QMimeData *dropData, + const QPoint &p, Qt::DropActions supportedActions); +#endif // #if QT_DEPRECATED_SINCE(5, 11) + static QPlatformDragQtResponse handleDrag(QWindow *window, const QMimeData *dropData, + const QPoint &p, Qt::DropActions supportedActions, + Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers); + static QPlatformDropQtResponse handleDrop(QWindow *window, const QMimeData *dropData, + const QPoint &p, Qt::DropActions supportedActions, + Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers); +#endif // QT_NO_DRAGANDDROP static bool handleNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result); |