Cancel drag when Qt doesn't detect that mouse was released

On Windows there can be a case where Qt doesn't receive the mouse
release event. When releasing very fast after starting the drag.

Fixes #166
This commit is contained in:
Sergio Martins
2021-05-04 23:36:50 +01:00
parent b338f183e1
commit 18dbbb291a
2 changed files with 30 additions and 1 deletions

View File

@@ -132,7 +132,11 @@ State *MinimalStateMachine::currentState() const
void MinimalStateMachine::setCurrentState(State *state)
{
if (state != m_currentState) {
if (m_currentState)
m_currentState->onExit();
m_currentState = state;
if (state)
state->onEntry();
}
@@ -238,12 +242,28 @@ bool StatePreDrag::handleMouseDoubleClick()
StateDragging::StateDragging(DragController *parent)
: StateBase(parent)
{
#if defined(Q_OS_WIN)
m_maybeCancelDrag.setInterval(100);
QObject::connect(&m_maybeCancelDrag, &QTimer::timeout, this, [this] {
// Workaround bug #166 , where Qt doesn't agree with Window's mouse button state.
// Looking in the Qt bug tracker there's many hits, so do a quick workaround here:
const bool mouseButtonIsReallyDown = (GetKeyState(VK_LBUTTON) & 0x8000);
if (!mouseButtonIsReallyDown && isLeftButtonPressed()) {
qCDebug(state) << "Canceling drag, Qt thinks mouse button is pressed"
<< "but Windows knows it's not";
Q_EMIT q->dragCanceled();
}
});
#endif
}
StateDragging::~StateDragging() = default;
void StateDragging::onEntry()
{
m_maybeCancelDrag.start();
if (DockWidgetBase *dw = q->m_draggable->singleDockWidget()) {
// When we start to drag a floating window which has a single dock widget, we save the position
if (dw->isFloating())
@@ -296,6 +316,11 @@ void StateDragging::onEntry()
}
}
void StateDragging::onExit()
{
m_maybeCancelDrag.stop();
}
bool StateDragging::handleMouseButtonRelease(QPoint globalPos)
{
qCDebug(state) << "StateDragging: handleMouseButtonRelease";
@@ -345,7 +370,6 @@ bool StateDragging::handleMouseMove(QPoint globalPos)
if (!q->m_nonClientDrag)
fw->windowHandle()->setPosition(globalPos - q->m_offset);
if (fw->anyNonDockable()) {
qCDebug(state) << "StateDragging: Ignoring non dockable floating window";
return true;