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 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(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(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, QHighDpi::fromNativeLocalPosition(p, window) ,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) +QPlatformDropQtResponse QWindowSystemInterface::handleDrop(QWindow *window, const QMimeData *dropData, + const QPoint &p, Qt::DropActions supportedActions) { - return QGuiApplicationPrivate::processDrop(window, dropData, QHighDpi::fromNativeLocalPosition(p, window),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) +{ + 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, + Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) +{ + 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); diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 6f1a3e3c19..7d59496db3 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -53,6 +53,7 @@ #include "qxcbsystemtraytracker.h" #include "qxcbglintegrationfactory.h" #include "qxcbglintegration.h" +#include "qxcbcursor.h" #include #include @@ -2275,6 +2276,20 @@ bool QXcbConnection::xEmbedSystemTrayVisualHasAlphaChannel() return connection->systemTrayTracker() && connection->systemTrayTracker()->visualHasAlphaChannel(); } +Qt::MouseButtons QXcbConnection::queryMouseButtons() const +{ + int stateMask = 0; + QXcbCursor::queryPointer(connection(), 0, 0, &stateMask); + return translateMouseButtons(stateMask); +} + +Qt::KeyboardModifiers QXcbConnection::queryKeyboardModifiers() const +{ + int stateMask = 0; + QXcbCursor::queryPointer(connection(), 0, 0, &stateMask); + return keyboard()->translateModifiers(stateMask); +} + bool QXcbConnection::event(QEvent *e) { if (e->type() == QEvent::User + 1) { diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 3b42d7cf22..6bf4ad0b6c 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -506,6 +506,9 @@ public: static bool xEmbedSystemTrayAvailable(); static bool xEmbedSystemTrayVisualHasAlphaChannel(); + Qt::MouseButtons queryMouseButtons() const; + Qt::KeyboardModifiers queryKeyboardModifiers() const; + #if QT_CONFIG(xcb_xinput) void xi2SelectStateEvents(); void xi2SelectDeviceEvents(xcb_window_t window); diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp index 8d151b760b..6795cb8905 100644 --- a/src/plugins/platforms/xcb/qxcbcursor.cpp +++ b/src/plugins/platforms/xcb/qxcbcursor.cpp @@ -626,6 +626,12 @@ xcb_cursor_t QXcbCursor::createBitmapCursor(QCursor *cursor) } #endif +/*! \internal + + Note that the logical state of a device (as seen by means of the protocol) may + lag the physical state if device event processing is frozen. See QueryPointer + in X11 protocol specification. +*/ void QXcbCursor::queryPointer(QXcbConnection *c, QXcbVirtualDesktop **virtualDesktop, QPoint *pos, int *keybMask) { if (pos) diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index 8ea0ebf966..10a827cfd9 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -309,7 +309,7 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md return 0; } -void QXcbDrag::move(const QPoint &globalPos) +void QXcbDrag::move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) { if (source_sameanswer.contains(globalPos) && source_sameanswer.isValid()) @@ -470,15 +470,15 @@ void QXcbDrag::move(const QPoint &globalPos) source_time = connection()->time(); if (w) - handle_xdnd_position(w, &move); + handle_xdnd_position(w, &move, b, mods); else xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&move); } } -void QXcbDrag::drop(const QPoint &globalPos) +void QXcbDrag::drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) { - QBasicDrag::drop(globalPos); + QBasicDrag::drop(globalPos, b, mods); if (!current_target) return; @@ -522,7 +522,7 @@ void QXcbDrag::drop(const QPoint &globalPos) } if (w) { - handleDrop(w, &drop); + handleDrop(w, &drop, b, mods); } else { xcb_send_event(xcb_connection(), false, current_proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&drop); } @@ -710,7 +710,8 @@ void QXcbDrag::handleEnter(QPlatformWindow *window, const xcb_client_message_eve DEBUG() << " " << connection()->atomName(xdnd_types.at(i)); } -void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message_event_t *e) +void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message_event_t *e, + Qt::MouseButtons b, Qt::KeyboardModifiers mods) { QPoint p((e->data.data32[2] & 0xffff0000) >> 16, e->data.data32[2] & 0x0000ffff); Q_ASSERT(w); @@ -743,7 +744,12 @@ void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message supported_actions = Qt::DropActions(toDropAction(e->data.data32[4])); } - QPlatformDragQtResponse qt_response = QWindowSystemInterface::handleDrag(w->window(),dropData,p,supported_actions); + auto buttons = currentDrag() ? b : connection()->queryMouseButtons(); + auto modifiers = currentDrag() ? mods : connection()->queryKeyboardModifiers(); + + QPlatformDragQtResponse qt_response = QWindowSystemInterface::handleDrag( + w->window(), dropData, p, supported_actions, buttons, modifiers); + QRect answerRect(p + geometry.topLeft(), QSize(1,1)); answerRect = qt_response.answerRect().translated(geometry.topLeft()).intersected(geometry); @@ -887,7 +893,7 @@ void QXcbDrag::handleLeave(QPlatformWindow *w, const xcb_client_message_event_t DEBUG("xdnd drag leave from unexpected source (%x not %x", event->data.data32[0], xdnd_dragsource); } - QWindowSystemInterface::handleDrag(w->window(),0,QPoint(),Qt::IgnoreAction); + QWindowSystemInterface::handleDrag(w->window(), nullptr, QPoint(), Qt::IgnoreAction, 0, 0); xdnd_dragsource = 0; xdnd_types.clear(); @@ -899,7 +905,6 @@ void QXcbDrag::send_leave() if (!current_target) return; - xcb_client_message_event_t leave; leave.response_type = XCB_CLIENT_MESSAGE; leave.sequence = 0; @@ -933,7 +938,8 @@ void QXcbDrag::send_leave() waiting_for_status = false; } -void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *event) +void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *event, + Qt::MouseButtons b, Qt::KeyboardModifiers mods) { DEBUG("xdndHandleDrop"); if (!currentWindow) { @@ -962,9 +968,6 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e } else { dropData = m_dropData; supported_drop_actions = accepted_drop_action; - - // Drop coming from another app? Update keyboard modifiers. - QGuiApplicationPrivate::modifier_buttons = QGuiApplication::queryKeyboardModifiers(); } if (!dropData) @@ -975,7 +978,13 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e // dropData = QDragManager::dragPrivate(X11->dndDropTransactions.at(at).object)->data; // if we can't find it, then use the data in the drag manager - QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(currentWindow.data(),dropData,currentPosition,supported_drop_actions); + auto buttons = currentDrag() ? b : connection()->queryMouseButtons(); + auto modifiers = currentDrag() ? mods : connection()->queryKeyboardModifiers(); + + QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop( + currentWindow.data(), dropData, currentPosition, supported_drop_actions, + buttons, modifiers); + setExecutedDropAction(response.acceptedAction()); xcb_client_message_event_t finished; diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h index 31f1c47d83..138625476a 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.h +++ b/src/plugins/platforms/xcb/qxcbdrag.h @@ -78,14 +78,15 @@ public: void startDrag() override; void cancel() override; - void move(const QPoint &globalPos) override; - void drop(const QPoint &globalPos) override; + void move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) override; + void drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) override; void endDrag() override; void handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event, xcb_window_t proxy = 0); void handlePosition(QPlatformWindow *w, const xcb_client_message_event_t *event); void handleLeave(QPlatformWindow *w, const xcb_client_message_event_t *event); - void handleDrop(QPlatformWindow *, const xcb_client_message_event_t *event); + void handleDrop(QPlatformWindow *, const xcb_client_message_event_t *event, + Qt::MouseButtons b = 0, Qt::KeyboardModifiers mods = 0); void handleStatus(const xcb_client_message_event_t *event); void handleSelectionRequest(const xcb_selection_request_event_t *event); @@ -105,7 +106,8 @@ private: void init(); - void handle_xdnd_position(QPlatformWindow *w, const xcb_client_message_event_t *event); + void handle_xdnd_position(QPlatformWindow *w, const xcb_client_message_event_t *event, + Qt::MouseButtons b = 0, Qt::KeyboardModifiers mods = 0); void handle_xdnd_status(const xcb_client_message_event_t *event); void send_leave(); diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 143ea799b0..9e553666b2 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -410,10 +410,7 @@ QPlatformServices *QXcbIntegration::services() const Qt::KeyboardModifiers QXcbIntegration::queryKeyboardModifiers() const { - int keybMask = 0; - QXcbConnection *conn = m_connections.at(0); - QXcbCursor::queryPointer(conn, 0, 0, &keybMask); - return conn->keyboard()->translateModifiers(keybMask); + return m_connections.at(0)->queryKeyboardModifiers(); } QList QXcbIntegration::possibleKeys(const QKeyEvent *e) const