Fix Windows DnD: Wrong qApp mouse buttons state after external DnD
An QApplication::mouseButtons() value could stay outdated after external DnD operations, e.g. dragging an object outside Qt application or vice versa. Also user can cancel DnD with Escape key. Task-number: QTBUG-55885 Task-number: QTBUG-59539 Change-Id: Ia6deb4ae5ccfe77e6d6c2464de40cd06fc71f9b8 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
This commit is contained in:
parent
38a55c7813
commit
9ef14bcc3a
@ -412,34 +412,39 @@ QWindowsOleDropSource::Release(void)
|
|||||||
QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
|
QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
|
||||||
QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
|
QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
Qt::MouseButtons buttons = toQtMouseButtons(grfKeyState);
|
||||||
do {
|
|
||||||
if (fEscapePressed || QWindowsDrag::isCanceled()) {
|
|
||||||
hr = ResultFromScode(DRAGDROP_S_CANCEL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Qt::MouseButtons buttons = toQtMouseButtons(grfKeyState);
|
SCODE result = S_OK;
|
||||||
if (m_currentButtons == Qt::NoButton) {
|
if (fEscapePressed || QWindowsDrag::isCanceled()) {
|
||||||
m_currentButtons = buttons;
|
result = DRAGDROP_S_CANCEL;
|
||||||
|
buttons = Qt::NoButton;
|
||||||
} else {
|
} else {
|
||||||
// Button changed: Complete Drop operation.
|
if (buttons && !m_currentButtons) {
|
||||||
if (!(m_currentButtons & buttons)) {
|
m_currentButtons = buttons;
|
||||||
hr = ResultFromScode(DRAGDROP_S_DROP);
|
} else if (!(m_currentButtons & buttons)) { // Button changed: Complete Drop operation.
|
||||||
break;
|
result = DRAGDROP_S_DROP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QGuiApplication::processEvents();
|
switch (result) {
|
||||||
|
case DRAGDROP_S_DROP:
|
||||||
|
case DRAGDROP_S_CANCEL:
|
||||||
|
QGuiApplicationPrivate::modifier_buttons = toQtKeyboardModifiers(grfKeyState);
|
||||||
|
QGuiApplicationPrivate::mouse_buttons = buttons;
|
||||||
|
m_currentButtons = Qt::NoButton;
|
||||||
|
break;
|
||||||
|
|
||||||
} while (false);
|
default:
|
||||||
|
QGuiApplication::processEvents();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (QWindowsContext::verbose > 1 || hr != S_OK) {
|
if (QWindowsContext::verbose > 1 || result != S_OK) {
|
||||||
qCDebug(lcQpaMime) << __FUNCTION__ << "fEscapePressed=" << fEscapePressed
|
qCDebug(lcQpaMime) << __FUNCTION__ << "fEscapePressed=" << fEscapePressed
|
||||||
<< "grfKeyState=" << grfKeyState << "buttons" << m_currentButtons
|
<< "grfKeyState=" << grfKeyState << "buttons" << m_currentButtons
|
||||||
<< "returns 0x" << hex <<int(hr) << dec;
|
<< "returns 0x" << hex << int(result) << dec;
|
||||||
}
|
}
|
||||||
return hr;
|
return ResultFromScode(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -610,6 +615,12 @@ QWindowsOleDropTarget::DragLeave()
|
|||||||
qCDebug(lcQpaMime) << __FUNCTION__ << ' ' << m_window;
|
qCDebug(lcQpaMime) << __FUNCTION__ << ' ' << m_window;
|
||||||
|
|
||||||
QWindowSystemInterface::handleDrag(m_window, 0, QPoint(), Qt::IgnoreAction);
|
QWindowSystemInterface::handleDrag(m_window, 0, QPoint(), Qt::IgnoreAction);
|
||||||
|
|
||||||
|
if (!QDragManager::self()->source()) {
|
||||||
|
QGuiApplicationPrivate::modifier_buttons = Qt::NoModifier;
|
||||||
|
QGuiApplicationPrivate::mouse_buttons = Qt::NoButton;
|
||||||
|
m_lastKeyState = 0;
|
||||||
|
}
|
||||||
QWindowsDrag::instance()->releaseDropDataObject();
|
QWindowsDrag::instance()->releaseDropDataObject();
|
||||||
|
|
||||||
return NOERROR;
|
return NOERROR;
|
||||||
@ -628,11 +639,9 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState,
|
|||||||
<< "keys=" << grfKeyState << "pt=" << pt.x << ',' << pt.y;
|
<< "keys=" << grfKeyState << "pt=" << pt.x << ',' << pt.y;
|
||||||
|
|
||||||
m_lastPoint = QWindowsGeometryHint::mapFromGlobal(m_window, QPoint(pt.x,pt.y));
|
m_lastPoint = QWindowsGeometryHint::mapFromGlobal(m_window, QPoint(pt.x,pt.y));
|
||||||
// grfKeyState does not all ways contain button state in the drop so if
|
// grfKeyState does not all ways contain button state in the drop
|
||||||
// it doesn't then use the last known button state;
|
QGuiApplicationPrivate::mouse_buttons = toQtMouseButtons(m_lastKeyState);
|
||||||
if ((grfKeyState & KEY_STATE_BUTTON_MASK) == 0)
|
QGuiApplicationPrivate::modifier_buttons = toQtKeyboardModifiers(grfKeyState);
|
||||||
grfKeyState |= m_lastKeyState & KEY_STATE_BUTTON_MASK;
|
|
||||||
m_lastKeyState = grfKeyState;
|
|
||||||
|
|
||||||
QWindowsDrag *windowsDrag = QWindowsDrag::instance();
|
QWindowsDrag *windowsDrag = QWindowsDrag::instance();
|
||||||
|
|
||||||
@ -640,6 +649,10 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState,
|
|||||||
QWindowSystemInterface::handleDrop(m_window, windowsDrag->dropData(),
|
QWindowSystemInterface::handleDrop(m_window, windowsDrag->dropData(),
|
||||||
m_lastPoint,
|
m_lastPoint,
|
||||||
translateToQDragDropActions(*pdwEffect));
|
translateToQDragDropActions(*pdwEffect));
|
||||||
|
|
||||||
|
QGuiApplicationPrivate::mouse_buttons = toQtMouseButtons(grfKeyState);
|
||||||
|
m_lastKeyState = grfKeyState;
|
||||||
|
|
||||||
if (response.isAccepted()) {
|
if (response.isAccepted()) {
|
||||||
const Qt::DropAction action = response.acceptedAction();
|
const Qt::DropAction action = response.acceptedAction();
|
||||||
if (action == Qt::MoveAction || action == Qt::TargetMoveAction) {
|
if (action == Qt::MoveAction || action == Qt::TargetMoveAction) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user