diff options
author | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2021-05-11 13:22:57 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2021-05-24 09:31:23 +0000 |
commit | 2db6c0967b9522a95fbfc7b648ef90eba9e73676 (patch) | |
tree | 5eec649fc825cbc4f7c2e833d549750df6a73842 /src | |
parent | 8319b54b9ff895002483d61559d754e83780cf56 (diff) |
cocoa: be more careful about rejecting frame strut events
The m_buttons property is meant to hold the currently pressed mouse
buttons done on the contents part of a QNSView. But m_buttons can
sometimes get out of sync with AppKit (NSEvent.pressedMouseButtons).
One way this is shown to happen is if you do a mouse press on a native
child widget (that is backed by it's own QNSView), and then convert the
widget to a top-level window before the release. In that case, the
underlying QNSView will be reparented from one NSWindow to another,
which will result in the old NSWindow getting the mouseUp call instead
of the new window. The result is that we don't update m_buttons for
the reparented QNSView, which will instead be left as "pressed".
As a result of m_buttons being stuck in a faulty state, we also refuse
to send out QEvent::NonClientAreaMouseMove events to the top-level
widget. This because QNSView thinks that it's already in a dragging
state that started on the content part of the view (and not on the
strut). As a result, it can sometimes be impossible to dock a
QDockWidget back into a QMainWindow, since we basically don't send
out any frame-drag events to Qt for the new dock window.
We can reason that if you start a mouse press on the frame strut, you
cannot at the same time have an active mouse press on the view contents.
This patch will therefore remove the buttons that we know was pressed
on the frame strut from m_buttons. This will at least (be one way to)
clear the faulty pressed state, and will let us send mouse
press/drag/release (and after that, move) frame strut events to Qt.
Task-number: QTBUG-70137
Change-Id: If51e1fe57d2531b659d39de85658893dae6391e3
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
(cherry picked from commit 78b6050d60ba97ffb66e79bcde6ea306108e41dd)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/platforms/cocoa/qnsview_mouse.mm | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/src/plugins/platforms/cocoa/qnsview_mouse.mm b/src/plugins/platforms/cocoa/qnsview_mouse.mm index 9d33b933b0..3c98bcb3b7 100644 --- a/src/plugins/platforms/cocoa/qnsview_mouse.mm +++ b/src/plugins/platforms/cocoa/qnsview_mouse.mm @@ -103,21 +103,14 @@ if (!m_platformWindow) return; - // get m_buttons in sync - // Don't send frme strut events if we are in the middle of a mouse drag. - if (m_buttons != Qt::NoButton) - return; - switch (theEvent.type) { case NSEventTypeLeftMouseDown: - case NSEventTypeLeftMouseDragged: m_frameStrutButtons |= Qt::LeftButton; break; case NSEventTypeLeftMouseUp: m_frameStrutButtons &= ~Qt::LeftButton; break; case NSEventTypeRightMouseDown: - case NSEventTypeRightMouseDragged: m_frameStrutButtons |= Qt::RightButton; break; case NSEventTypeRightMouseUp: @@ -132,6 +125,22 @@ break; } + // m_buttons can sometimes get out of sync with the button state in AppKit + // E.g if the QNSView where a drag starts is reparented to another window + // while the drag is ongoing, it will not get the corresponding mouseUp + // call. This will result in m_buttons to be stuck on Qt::LeftButton. + // Since we know which buttons was pressed/released directly on the frame + // strut, we can rectify m_buttons here so that we at least don't return early + // from the drag test underneath because of the faulty m_buttons state. + // FIXME: get m_buttons in sync with AppKit/NSEvent all over in QNSView. + m_buttons &= ~m_frameStrutButtons; + + if (m_buttons != Qt::NoButton) { + // Don't send frame strut events if we are in the middle of + // a mouse drag that didn't start on the frame strut. + return; + } + NSWindow *window = [self window]; NSPoint windowPoint = [theEvent locationInWindow]; |