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:
parent
bd52d9d73b
commit
10b3286313
@ -1679,7 +1679,7 @@ Qt::KeyboardModifiers QGuiApplication::queryKeyboardModifiers()
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns the current state of the buttons on the mouse. The current state is
|
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
|
spontaneously change the mouse state (QEvent::MouseButtonPress and
|
||||||
QEvent::MouseButtonRelease events).
|
QEvent::MouseButtonRelease events).
|
||||||
|
|
||||||
@ -3036,8 +3036,56 @@ void QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::E
|
|||||||
|
|
||||||
#ifndef QT_NO_DRAGANDDROP
|
#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 QPointer<QWindow> currentDragWindow;
|
||||||
static Qt::DropAction lastAcceptedDropAction = Qt::IgnoreAction;
|
static Qt::DropAction lastAcceptedDropAction = Qt::IgnoreAction;
|
||||||
QPlatformDrag *platformDrag = platformIntegration()->drag();
|
QPlatformDrag *platformDrag = platformIntegration()->drag();
|
||||||
@ -3054,8 +3102,7 @@ QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QM
|
|||||||
lastAcceptedDropAction = Qt::IgnoreAction;
|
lastAcceptedDropAction = Qt::IgnoreAction;
|
||||||
return QPlatformDragQtResponse(false, lastAcceptedDropAction, QRect());
|
return QPlatformDragQtResponse(false, lastAcceptedDropAction, QRect());
|
||||||
}
|
}
|
||||||
QDragMoveEvent me(p, supportedActions, dropData,
|
QDragMoveEvent me(p, supportedActions, dropData, buttons, modifiers);
|
||||||
QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
|
|
||||||
|
|
||||||
if (w != currentDragWindow) {
|
if (w != currentDragWindow) {
|
||||||
lastAcceptedDropAction = Qt::IgnoreAction;
|
lastAcceptedDropAction = Qt::IgnoreAction;
|
||||||
@ -3064,8 +3111,7 @@ QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QM
|
|||||||
QGuiApplication::sendEvent(currentDragWindow, &e);
|
QGuiApplication::sendEvent(currentDragWindow, &e);
|
||||||
}
|
}
|
||||||
currentDragWindow = w;
|
currentDragWindow = w;
|
||||||
QDragEnterEvent e(p, supportedActions, dropData,
|
QDragEnterEvent e(p, supportedActions, dropData, buttons, modifiers);
|
||||||
QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
|
|
||||||
QGuiApplication::sendEvent(w, &e);
|
QGuiApplication::sendEvent(w, &e);
|
||||||
if (e.isAccepted() && e.dropAction() != Qt::IgnoreAction)
|
if (e.isAccepted() && e.dropAction() != Qt::IgnoreAction)
|
||||||
lastAcceptedDropAction = e.dropAction();
|
lastAcceptedDropAction = e.dropAction();
|
||||||
@ -3083,10 +3129,13 @@ QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QM
|
|||||||
return QPlatformDragQtResponse(me.isAccepted(), lastAcceptedDropAction, me.answerRect());
|
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,
|
updateMouseAndModifierButtonState(buttons, modifiers);
|
||||||
QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
|
|
||||||
|
QDropEvent de(p, supportedActions, dropData, buttons, modifiers);
|
||||||
QGuiApplication::sendEvent(w, &de);
|
QGuiApplication::sendEvent(w, &de);
|
||||||
|
|
||||||
Qt::DropAction acceptedAction = de.isAccepted() ? de.dropAction() : Qt::IgnoreAction;
|
Qt::DropAction acceptedAction = de.isAccepted() ? de.dropAction() : Qt::IgnoreAction;
|
||||||
|
@ -163,8 +163,12 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef QT_NO_DRAGANDDROP
|
#ifndef QT_NO_DRAGANDDROP
|
||||||
static QPlatformDragQtResponse processDrag(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions);
|
static QPlatformDragQtResponse processDrag(QWindow *w, const QMimeData *dropData,
|
||||||
static QPlatformDropQtResponse processDrop(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions);
|
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
|
#endif
|
||||||
|
|
||||||
static bool processNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result);
|
static bool processNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result);
|
||||||
|
@ -160,7 +160,8 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e)
|
|||||||
case QEvent::MouseMove:
|
case QEvent::MouseMove:
|
||||||
{
|
{
|
||||||
QPoint nativePosition = getNativeMousePos(e, m_drag_icon_window);
|
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
|
return true; // Eat all mouse move events
|
||||||
}
|
}
|
||||||
case QEvent::MouseButtonRelease:
|
case QEvent::MouseButtonRelease:
|
||||||
@ -168,7 +169,8 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e)
|
|||||||
disableEventFilter();
|
disableEventFilter();
|
||||||
if (canDrop()) {
|
if (canDrop()) {
|
||||||
QPoint nativePosition = getNativeMousePos(e, m_drag_icon_window);
|
QPoint nativePosition = getNativeMousePos(e, m_drag_icon_window);
|
||||||
drop(nativePosition);
|
auto mouseRelease = static_cast<QMouseEvent *>(e);
|
||||||
|
drop(nativePosition, mouseRelease->buttons(), mouseRelease->modifiers());
|
||||||
} else {
|
} else {
|
||||||
cancel();
|
cancel();
|
||||||
}
|
}
|
||||||
@ -289,7 +291,7 @@ void QBasicDrag::moveShapedPixmapWindow(const QPoint &globalPos)
|
|||||||
m_drag_icon_window->updateGeometry(globalPos);
|
m_drag_icon_window->updateGeometry(globalPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QBasicDrag::drop(const QPoint &)
|
void QBasicDrag::drop(const QPoint &, Qt::MouseButtons, Qt::KeyboardModifiers)
|
||||||
{
|
{
|
||||||
disableEventFilter();
|
disableEventFilter();
|
||||||
restoreCursor();
|
restoreCursor();
|
||||||
@ -377,9 +379,18 @@ QSimpleDrag::QSimpleDrag()
|
|||||||
void QSimpleDrag::startDrag()
|
void QSimpleDrag::startDrag()
|
||||||
{
|
{
|
||||||
QBasicDrag::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());
|
m_current_window = topLevelAt(QCursor::pos());
|
||||||
if (m_current_window) {
|
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());
|
setCanDrop(response.isAccepted());
|
||||||
updateCursor(response.acceptedAction());
|
updateCursor(response.acceptedAction());
|
||||||
} else {
|
} else {
|
||||||
@ -394,12 +405,13 @@ void QSimpleDrag::cancel()
|
|||||||
{
|
{
|
||||||
QBasicDrag::cancel();
|
QBasicDrag::cancel();
|
||||||
if (drag() && m_current_window) {
|
if (drag() && m_current_window) {
|
||||||
QWindowSystemInterface::handleDrag(m_current_window, 0, QPoint(), Qt::IgnoreAction);
|
QWindowSystemInterface::handleDrag(m_current_window, nullptr, QPoint(), Qt::IgnoreAction, 0, 0);
|
||||||
m_current_window = 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);
|
QPoint globalPos = fromNativeGlobalPixels(nativeGlobalPos);
|
||||||
moveShapedPixmapWindow(globalPos);
|
moveShapedPixmapWindow(globalPos);
|
||||||
@ -408,25 +420,28 @@ void QSimpleDrag::move(const QPoint &nativeGlobalPos)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
const QPoint pos = nativeGlobalPos - window->handle()->geometry().topLeft();
|
const QPoint pos = nativeGlobalPos - window->handle()->geometry().topLeft();
|
||||||
const QPlatformDragQtResponse qt_response =
|
const QPlatformDragQtResponse qt_response = QWindowSystemInterface::handleDrag(
|
||||||
QWindowSystemInterface::handleDrag(window, drag()->mimeData(), pos, drag()->supportedActions());
|
window, drag()->mimeData(), pos, drag()->supportedActions(),
|
||||||
|
buttons, modifiers);
|
||||||
|
|
||||||
updateCursor(qt_response.acceptedAction());
|
updateCursor(qt_response.acceptedAction());
|
||||||
setCanDrop(qt_response.isAccepted());
|
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);
|
QPoint globalPos = fromNativeGlobalPixels(nativeGlobalPos);
|
||||||
|
|
||||||
QBasicDrag::drop(nativeGlobalPos);
|
QBasicDrag::drop(nativeGlobalPos, buttons, modifiers);
|
||||||
QWindow *window = topLevelAt(globalPos);
|
QWindow *window = topLevelAt(globalPos);
|
||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const QPoint pos = nativeGlobalPos - window->handle()->geometry().topLeft();
|
const QPoint pos = nativeGlobalPos - window->handle()->geometry().topLeft();
|
||||||
const QPlatformDropQtResponse response =
|
const QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(
|
||||||
QWindowSystemInterface::handleDrop(window, drag()->mimeData(),pos, drag()->supportedActions());
|
window, drag()->mimeData(), pos, drag()->supportedActions(),
|
||||||
|
buttons, modifiers);
|
||||||
if (response.isAccepted()) {
|
if (response.isAccepted()) {
|
||||||
setExecutedDropAction(response.acceptedAction());
|
setExecutedDropAction(response.acceptedAction());
|
||||||
} else {
|
} else {
|
||||||
|
@ -82,8 +82,8 @@ protected:
|
|||||||
|
|
||||||
virtual void startDrag();
|
virtual void startDrag();
|
||||||
virtual void cancel();
|
virtual void cancel();
|
||||||
virtual void move(const QPoint &globalPos) = 0;
|
virtual void move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) = 0;
|
||||||
virtual void drop(const QPoint &globalPos) = 0;
|
virtual void drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) = 0;
|
||||||
virtual void endDrag();
|
virtual void endDrag();
|
||||||
|
|
||||||
|
|
||||||
@ -132,8 +132,8 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual void startDrag() override;
|
virtual void startDrag() override;
|
||||||
virtual void cancel() override;
|
virtual void cancel() override;
|
||||||
virtual void move(const QPoint &globalPos) override;
|
virtual void move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) override;
|
||||||
virtual void drop(const QPoint &globalPos) override;
|
virtual void drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QT_NO_DRAGANDDROP
|
#endif // QT_NO_DRAGANDDROP
|
||||||
|
@ -791,14 +791,44 @@ void QWindowSystemInterface::handleThemeChange(QWindow *window)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_DRAGANDDROP
|
#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
|
#endif // QT_NO_DRAGANDDROP
|
||||||
|
|
||||||
|
@ -215,10 +215,19 @@ public:
|
|||||||
static void handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate = false);
|
static void handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate = false);
|
||||||
|
|
||||||
#ifndef QT_NO_DRAGANDDROP
|
#ifndef QT_NO_DRAGANDDROP
|
||||||
// Drag and drop. These events are sent immediately.
|
#if QT_DEPRECATED_SINCE(5, 11)
|
||||||
static QPlatformDragQtResponse handleDrag(QWindow *window, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions);
|
QT_DEPRECATED static QPlatformDragQtResponse handleDrag(QWindow *window, const QMimeData *dropData,
|
||||||
static QPlatformDropQtResponse handleDrop(QWindow *window, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions);
|
const QPoint &p, Qt::DropActions supportedActions);
|
||||||
#endif
|
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);
|
static bool handleNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result);
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
#include "qxcbsystemtraytracker.h"
|
#include "qxcbsystemtraytracker.h"
|
||||||
#include "qxcbglintegrationfactory.h"
|
#include "qxcbglintegrationfactory.h"
|
||||||
#include "qxcbglintegration.h"
|
#include "qxcbglintegration.h"
|
||||||
|
#include "qxcbcursor.h"
|
||||||
|
|
||||||
#include <QSocketNotifier>
|
#include <QSocketNotifier>
|
||||||
#include <QAbstractEventDispatcher>
|
#include <QAbstractEventDispatcher>
|
||||||
@ -2275,6 +2276,20 @@ bool QXcbConnection::xEmbedSystemTrayVisualHasAlphaChannel()
|
|||||||
return connection->systemTrayTracker() && connection->systemTrayTracker()->visualHasAlphaChannel();
|
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)
|
bool QXcbConnection::event(QEvent *e)
|
||||||
{
|
{
|
||||||
if (e->type() == QEvent::User + 1) {
|
if (e->type() == QEvent::User + 1) {
|
||||||
|
@ -506,6 +506,9 @@ public:
|
|||||||
static bool xEmbedSystemTrayAvailable();
|
static bool xEmbedSystemTrayAvailable();
|
||||||
static bool xEmbedSystemTrayVisualHasAlphaChannel();
|
static bool xEmbedSystemTrayVisualHasAlphaChannel();
|
||||||
|
|
||||||
|
Qt::MouseButtons queryMouseButtons() const;
|
||||||
|
Qt::KeyboardModifiers queryKeyboardModifiers() const;
|
||||||
|
|
||||||
#if QT_CONFIG(xcb_xinput)
|
#if QT_CONFIG(xcb_xinput)
|
||||||
void xi2SelectStateEvents();
|
void xi2SelectStateEvents();
|
||||||
void xi2SelectDeviceEvents(xcb_window_t window);
|
void xi2SelectDeviceEvents(xcb_window_t window);
|
||||||
|
@ -626,6 +626,12 @@ xcb_cursor_t QXcbCursor::createBitmapCursor(QCursor *cursor)
|
|||||||
}
|
}
|
||||||
#endif
|
#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)
|
void QXcbCursor::queryPointer(QXcbConnection *c, QXcbVirtualDesktop **virtualDesktop, QPoint *pos, int *keybMask)
|
||||||
{
|
{
|
||||||
if (pos)
|
if (pos)
|
||||||
|
@ -309,7 +309,7 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md
|
|||||||
return 0;
|
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())
|
if (source_sameanswer.contains(globalPos) && source_sameanswer.isValid())
|
||||||
@ -470,15 +470,15 @@ void QXcbDrag::move(const QPoint &globalPos)
|
|||||||
source_time = connection()->time();
|
source_time = connection()->time();
|
||||||
|
|
||||||
if (w)
|
if (w)
|
||||||
handle_xdnd_position(w, &move);
|
handle_xdnd_position(w, &move, b, mods);
|
||||||
else
|
else
|
||||||
xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&move);
|
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)
|
if (!current_target)
|
||||||
return;
|
return;
|
||||||
@ -522,7 +522,7 @@ void QXcbDrag::drop(const QPoint &globalPos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (w) {
|
if (w) {
|
||||||
handleDrop(w, &drop);
|
handleDrop(w, &drop, b, mods);
|
||||||
} else {
|
} else {
|
||||||
xcb_send_event(xcb_connection(), false, current_proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&drop);
|
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));
|
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);
|
QPoint p((e->data.data32[2] & 0xffff0000) >> 16, e->data.data32[2] & 0x0000ffff);
|
||||||
Q_ASSERT(w);
|
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]));
|
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));
|
QRect answerRect(p + geometry.topLeft(), QSize(1,1));
|
||||||
answerRect = qt_response.answerRect().translated(geometry.topLeft()).intersected(geometry);
|
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);
|
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_dragsource = 0;
|
||||||
xdnd_types.clear();
|
xdnd_types.clear();
|
||||||
@ -899,7 +905,6 @@ void QXcbDrag::send_leave()
|
|||||||
if (!current_target)
|
if (!current_target)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
xcb_client_message_event_t leave;
|
xcb_client_message_event_t leave;
|
||||||
leave.response_type = XCB_CLIENT_MESSAGE;
|
leave.response_type = XCB_CLIENT_MESSAGE;
|
||||||
leave.sequence = 0;
|
leave.sequence = 0;
|
||||||
@ -933,7 +938,8 @@ void QXcbDrag::send_leave()
|
|||||||
waiting_for_status = false;
|
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");
|
DEBUG("xdndHandleDrop");
|
||||||
if (!currentWindow) {
|
if (!currentWindow) {
|
||||||
@ -962,9 +968,6 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e
|
|||||||
} else {
|
} else {
|
||||||
dropData = m_dropData;
|
dropData = m_dropData;
|
||||||
supported_drop_actions = accepted_drop_action;
|
supported_drop_actions = accepted_drop_action;
|
||||||
|
|
||||||
// Drop coming from another app? Update keyboard modifiers.
|
|
||||||
QGuiApplicationPrivate::modifier_buttons = QGuiApplication::queryKeyboardModifiers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dropData)
|
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;
|
// dropData = QDragManager::dragPrivate(X11->dndDropTransactions.at(at).object)->data;
|
||||||
// if we can't find it, then use the data in the drag manager
|
// 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());
|
setExecutedDropAction(response.acceptedAction());
|
||||||
|
|
||||||
xcb_client_message_event_t finished;
|
xcb_client_message_event_t finished;
|
||||||
|
@ -78,14 +78,15 @@ public:
|
|||||||
|
|
||||||
void startDrag() override;
|
void startDrag() override;
|
||||||
void cancel() override;
|
void cancel() override;
|
||||||
void move(const QPoint &globalPos) override;
|
void move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) override;
|
||||||
void drop(const QPoint &globalPos) override;
|
void drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) override;
|
||||||
void endDrag() override;
|
void endDrag() override;
|
||||||
|
|
||||||
void handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event, xcb_window_t proxy = 0);
|
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 handlePosition(QPlatformWindow *w, const xcb_client_message_event_t *event);
|
||||||
void handleLeave(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 handleStatus(const xcb_client_message_event_t *event);
|
||||||
void handleSelectionRequest(const xcb_selection_request_event_t *event);
|
void handleSelectionRequest(const xcb_selection_request_event_t *event);
|
||||||
@ -105,7 +106,8 @@ private:
|
|||||||
|
|
||||||
void init();
|
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 handle_xdnd_status(const xcb_client_message_event_t *event);
|
||||||
void send_leave();
|
void send_leave();
|
||||||
|
|
||||||
|
@ -410,10 +410,7 @@ QPlatformServices *QXcbIntegration::services() const
|
|||||||
|
|
||||||
Qt::KeyboardModifiers QXcbIntegration::queryKeyboardModifiers() const
|
Qt::KeyboardModifiers QXcbIntegration::queryKeyboardModifiers() const
|
||||||
{
|
{
|
||||||
int keybMask = 0;
|
return m_connections.at(0)->queryKeyboardModifiers();
|
||||||
QXcbConnection *conn = m_connections.at(0);
|
|
||||||
QXcbCursor::queryPointer(conn, 0, 0, &keybMask);
|
|
||||||
return conn->keyboard()->translateModifiers(keybMask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<int> QXcbIntegration::possibleKeys(const QKeyEvent *e) const
|
QList<int> QXcbIntegration::possibleKeys(const QKeyEvent *e) const
|
||||||
|
Loading…
Reference in New Issue
Block a user