macOS: Don't close popups in Cocoa plugin for most mouse events
QWidget and QApplication handle popup closing for most events at the
right time for the Qt-internal state logic. On other platforms popup
QWindows are never closed automatically when clicking outside.
So don't close any popups in the Cocoa plugin either, and let the Qt
logic take care of it. This ensures that window activation is done at
the right time, that Qt's modal popup stack is consistent, and that
mouse replay for events closing a popup works.
There are however two exceptions: mouse events in the window frame don't
produce a QMouseEvent for Qt; and mouse events in a modally blocked (by
Cocoa) window don't reach Qt at all. For those case, the logic in QWidget
and QApplication is not enough.
For the former, leave the change introduced in 70b94eea10
to explicitly close popups for LMB down in the frame. This still needs
to happen before the event is delivered.
For the latter case, deliver the event explicitly to Qt when we discover
that the target window is modally blocked while a popup is active. The
handleMouseEvent implementation then takes care of the redirect to the
active popup, and Qt will further respect the modal stack in the
QApplication::isWindowBlocked implementation.
Change-Id: I578eb5e6aebc897a0ff1f69bc5c53bcaa05d138d
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
parent
1093562d08
commit
73753ee3af
@ -56,6 +56,7 @@ QT_DECLARE_NAMESPACED_OBJC_INTERFACE(QNSView, NSView
|
||||
|
||||
#if defined(__OBJC__)
|
||||
@interface QNSView (MouseAPI)
|
||||
- (void)handleMouseEvent:(NSEvent *)theEvent;
|
||||
- (void)handleFrameStrutMouseEvent:(NSEvent *)theEvent;
|
||||
- (bool)closePopups:(NSEvent *)theEvent;
|
||||
- (void)resetMouseButtons;
|
||||
|
@ -446,16 +446,6 @@ static const QPointingDevice *pointingDeviceFor(qint64 deviceID)
|
||||
return [super mouseDown:theEvent];
|
||||
m_sendUpAsRightButton = false;
|
||||
|
||||
// Handle any active poup windows; clicking outisde them should close them
|
||||
// all. Don't do anything or clicks inside one of the menus, let Cocoa
|
||||
// handle that case. Note that in practice many windows of the Qt::Popup type
|
||||
// will actually close themselves in this case using logic implemented in
|
||||
// that particular poup type (for example context menus). However, Qt expects
|
||||
// that plain popup QWindows will also be closed, so we implement the logic
|
||||
// here as well.
|
||||
if ([self closePopups:theEvent])
|
||||
return;
|
||||
|
||||
QPointF qtWindowPoint;
|
||||
QPointF qtScreenPoint;
|
||||
[self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint];
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "qcocoawindow.h"
|
||||
#include "qcocoahelpers.h"
|
||||
#include "qcocoaeventdispatcher.h"
|
||||
#include "qcocoaintegration.h"
|
||||
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
#include <qoperatingsystemversion.h>
|
||||
@ -370,6 +371,17 @@ OSStatus CGSClearWindowTags(const CGSConnectionID, const CGSWindowID, int *, int
|
||||
if (!m_platformWindow)
|
||||
return; // Platform window went away while processing event
|
||||
|
||||
// Cocoa will not deliver mouse events to a window that is modally blocked (by Cocoa,
|
||||
// not Qt). However, an active popup is expected to grab any mouse event within the
|
||||
// application, so we need to handle those explicitly and trust Qt's isWindowBlocked
|
||||
// implementation to eat events that shouldn't be delivered anyway.
|
||||
if (isMouseEvent(theEvent) && QCocoaIntegration::instance()->activePopupWindow()
|
||||
&& QGuiApplicationPrivate::instance()->isWindowBlocked(m_platformWindow->window(), nullptr)) {
|
||||
qCDebug(lcQpaWindow) << "Mouse event over modally blocked window" << m_platformWindow->window()
|
||||
<< "while popup" << QCocoaIntegration::instance()->activePopupWindow()
|
||||
<< "is open - redirecting";
|
||||
[qnsview_cast(m_platformWindow->view()) handleMouseEvent:theEvent];
|
||||
}
|
||||
if (m_platformWindow->frameStrutEventsEnabled() && mouseEventInFrameStrut)
|
||||
[qnsview_cast(m_platformWindow->view()) handleFrameStrutMouseEvent:theEvent];
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user