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:
Serge Lysenko 2016-09-21 21:52:52 +03:00 committed by Serge Lysenko
parent 38a55c7813
commit 9ef14bcc3a

View File

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