summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel/qsimpledrag.cpp
diff options
context:
space:
mode:
authorGatis Paeglis <gatis.paeglis@qt.io>2017-05-15 16:23:49 +0200
committerGatis Paeglis <gatis.paeglis@qt.io>2018-05-04 10:44:15 +0000
commit10b3286313c78fa380b5fe676a7c14f3ae84f017 (patch)
treec42b5d2173c2b31775bfaa4185e9c59f55f22f0e /src/gui/kernel/qsimpledrag.cpp
parentbd52d9d73be83d5e4d2e16e45fe369dc79ae2117 (diff)
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>
Diffstat (limited to 'src/gui/kernel/qsimpledrag.cpp')
-rw-r--r--src/gui/kernel/qsimpledrag.cpp41
1 files changed, 28 insertions, 13 deletions
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 {