qpa: improve API to support DnDs from other processes

... instead of using a hack of directly accessing QGuiApplication
members.

The current QPA API was bad for two reasons:

1) It expects platform plugin authors to know about
internals of Qt Gui, particularly that QGuiApplication
uses QGuiApplication::{mouseButtons,keyboardModifiers}
to construct QDragMoveEvent and QDropEvent events. Which
results in the second reason why this is bad.

2) Platform plugins should not directly access member
variables of QGuiApplication, just to make sure that
QDragMoveEvent and QDropEvent events contain correct state.
Platform plugins should instead use QWindowSystemInterface
to communicate with Qt Gui (which is also the solution here).

The solution is to extend QWindowSystemInterface::handle{Drag,Drop}
to require mouse/keyboard state. We already do this for
some of the other methods, so it is nothing extraordinary.
This type of interface is also _required_ to support
drag-n-drops from other processes. We can't use
QGuiApplication::{mouseButtons,keyboardModifiers} when the
drag originates from another process, instead we need to
query mouse/keyboard state from the system.

This patch fixes drag-n-drops from others processes on XCB
platform plugin.

Task-number: QTBUG-57168
Change-Id: I3f8b0d2f76e9a32ae157622fef801829d629921d
Reviewed-by: Mikhail Svetkin <mikhail.svetkin@qt.io>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
This commit is contained in:
Gatis Paeglis 2017-05-15 16:23:49 +02:00
parent bd52d9d73b
commit 10b3286313
12 changed files with 197 additions and 58 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -53,6 +53,7 @@
#include "qxcbsystemtraytracker.h"
#include "qxcbglintegrationfactory.h"
#include "qxcbglintegration.h"
#include "qxcbcursor.h"
#include <QSocketNotifier>
#include <QAbstractEventDispatcher>
@ -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) {

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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();

View File

@ -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<int> QXcbIntegration::possibleKeys(const QKeyEvent *e) const