Cocoa: Forward masked out mouse events.

Forward mouse events hitting the a masked out window
area to the next responder by calling the superclass
event handler.

Implement "inverse mouse grabbing": Qt will not take
dragged and up events if the mouseDown was in a masked
out area.

Change-Id: Ie86281245513cad515b77a468ac63f31ae41bfe0
Task-number: QTBUG-41839
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@theqtcompany.com>
This commit is contained in:
Morten Johan Sørvig 2015-11-11 22:19:16 +01:00 committed by Timur Pocheptsov
parent 68987d5454
commit 0694751c33
2 changed files with 29 additions and 4 deletions

View File

@ -60,6 +60,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
@interface QT_MANGLE_NAMESPACE(QNSView) : NSView <NSTextInputClient> {
QCocoaBackingStore* m_backingStore;
QPoint m_backingStoreOffset;
QRegion m_maskRegion;
CGImageRef m_maskImage;
uchar *m_maskData;
bool m_shouldInvalidateWindowShadow;
@ -67,6 +68,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
QCocoaWindow *m_platformWindow;
NSTrackingArea *m_trackingArea;
Qt::MouseButtons m_buttons;
Qt::MouseButtons m_acceptedMouseDowns;
Qt::MouseButtons m_frameStrutButtons;
QString m_composingText;
bool m_sendKeyEvent;

View File

@ -145,6 +145,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
m_shouldInvalidateWindowShadow = false;
m_window = 0;
m_buttons = Qt::NoButton;
m_acceptedMouseDowns = Qt::NoButton;
m_frameStrutButtons = Qt::NoButton;
m_sendKeyEvent = false;
m_subscribesForGlobalFrameNotifications = false;
@ -529,7 +530,7 @@ QT_WARNING_POP
- (BOOL) hasMask
{
return m_maskImage != 0;
return !m_maskRegion.isEmpty();
}
- (BOOL) isOpaque
@ -542,6 +543,7 @@ QT_WARNING_POP
- (void) setMaskRegion:(const QRegion *)region
{
m_shouldInvalidateWindowShadow = true;
m_maskRegion = *region;
if (m_maskImage)
CGImageRelease(m_maskImage);
if (region->isEmpty()) {
@ -825,6 +827,22 @@ QT_WARNING_POP
Qt::MouseButton button = cocoaButton2QtButton([theEvent buttonNumber]);
QPointF qtWindowPoint;
QPointF qtScreenPoint;
[self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint];
Q_UNUSED(qtScreenPoint);
// Maintain masked state for the button for use by MouseDragged and MouseUp.
const bool masked = m_maskRegion.contains(qtWindowPoint.toPoint());
if (masked)
m_acceptedMouseDowns &= ~button;
else
m_acceptedMouseDowns |= button;
// Forward masked out events to the next responder
if (masked)
return false;
if (button == Qt::RightButton)
m_sendUpAsRightButton = true;
@ -843,7 +861,7 @@ QT_WARNING_POP
// Forward the event to the next responder if Qt did not accept the
// corresponding mouse down for this button
if (!m_acceptedMouseDowns.contains(button))
if (!(m_acceptedMouseDowns & button) == button)
return false;
if (!(m_buttons & (m_sendUpAsRightButton ? Qt::RightButton : Qt::LeftButton))) {
@ -862,6 +880,11 @@ QT_WARNING_POP
Qt::MouseButton button = cocoaButton2QtButton([theEvent buttonNumber]);
// Forward the event to the next responder if Qt did not accept the
// corresponding mouse down for this button
if (!(m_acceptedMouseDowns & button) == button)
return false;
if (m_sendUpAsRightButton && button == Qt::LeftButton)
button = Qt::RightButton;
if (button == Qt::RightButton)
@ -920,9 +943,9 @@ QT_WARNING_POP
// Maintain masked state for the button for use by MouseDragged and Up.
if (masked)
m_acceptedMouseDowns.remove(Qt::LeftButton);
m_acceptedMouseDowns &= ~Qt::LeftButton;
else
m_acceptedMouseDowns.insert(Qt::LeftButton);
m_acceptedMouseDowns |= Qt::LeftButton;
// Forward masked out events to the next responder
if (masked) {