Cocoa: Forward rejected key events.
Forward rejected key events to the next responder by checking the return value from QWindowSystemInterface and calling the superclass event handler. This is useful when Qt is running as a plugin in a host application; the host can now react to key events even if Qt has focus. Qt will often not accept keyUp events, even if the corresponding keyDown was accepted, for example in the case of text controls. We don't want to forward 'bare' keyUps, so keep track of which keyDowns have been seen. Change-Id: I976448a5d305a657a0e91aeb271b158f8b598286 Task-number: QTBUG-45768 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@theqtcompany.com>bb10
parent
820e69d6c2
commit
68987d5454
|
|
@ -43,6 +43,7 @@
|
|||
#include <AppKit/AppKit.h>
|
||||
|
||||
#include <QtCore/QPointer>
|
||||
#include <QtCore/QSet>
|
||||
#include <QtGui/QImage>
|
||||
#include <QtGui/QAccessible>
|
||||
|
||||
|
|
@ -85,6 +86,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
|
|||
bool m_exposedOnMoveToWindow;
|
||||
NSEvent *m_currentlyInterpretedKeyEvent;
|
||||
bool m_isMenuView;
|
||||
QSet<quint32> m_acceptedKeyDowns;
|
||||
}
|
||||
|
||||
- (id)init;
|
||||
|
|
@ -142,7 +144,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
|
|||
|
||||
- (int) convertKeyCode : (QChar)keyCode;
|
||||
+ (Qt::KeyboardModifiers) convertKeyModifiers : (ulong)modifierFlags;
|
||||
- (void)handleKeyEvent:(NSEvent *)theEvent eventType:(int)eventType;
|
||||
- (bool)handleKeyEvent:(NSEvent *)theEvent eventType:(int)eventType;
|
||||
- (void)keyDown:(NSEvent *)theEvent;
|
||||
- (void)keyUp:(NSEvent *)theEvent;
|
||||
|
||||
|
|
|
|||
|
|
@ -911,6 +911,25 @@ QT_WARNING_POP
|
|||
}
|
||||
}
|
||||
|
||||
QPointF qtWindowPoint;
|
||||
QPointF qtScreenPoint;
|
||||
[self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint];
|
||||
Q_UNUSED(qtScreenPoint);
|
||||
|
||||
bool masked = m_maskRegion.contains(qtWindowPoint.toPoint());
|
||||
|
||||
// Maintain masked state for the button for use by MouseDragged and Up.
|
||||
if (masked)
|
||||
m_acceptedMouseDowns.remove(Qt::LeftButton);
|
||||
else
|
||||
m_acceptedMouseDowns.insert(Qt::LeftButton);
|
||||
|
||||
// Forward masked out events to the next responder
|
||||
if (masked) {
|
||||
[super mouseDown:theEvent];
|
||||
return;
|
||||
}
|
||||
|
||||
if ([self hasMarkedText]) {
|
||||
[[NSTextInputContext currentInputContext] handleEvent:theEvent];
|
||||
} else {
|
||||
|
|
@ -1483,7 +1502,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
|
|||
return qtMods;
|
||||
}
|
||||
|
||||
- (void)handleKeyEvent:(NSEvent *)nsevent eventType:(int)eventType
|
||||
- (bool)handleKeyEvent:(NSEvent *)nsevent eventType:(int)eventType
|
||||
{
|
||||
ulong timestamp = [nsevent timestamp] * 1000;
|
||||
ulong nativeModifiers = [nsevent modifierFlags];
|
||||
|
|
@ -1553,26 +1572,46 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
|
|||
m_sendKeyEvent = true;
|
||||
}
|
||||
|
||||
if (m_sendKeyEvent && m_composingText.isEmpty())
|
||||
bool accepted = true;
|
||||
if (m_sendKeyEvent && m_composingText.isEmpty()) {
|
||||
QWindowSystemInterface::handleExtendedKeyEvent(window, timestamp, QEvent::Type(eventType), keyCode, modifiers,
|
||||
nativeScanCode, nativeVirtualKey, nativeModifiers, text, [nsevent isARepeat], 1, false);
|
||||
|
||||
accepted = QWindowSystemInterface::flushWindowSystemEvents();
|
||||
}
|
||||
m_sendKeyEvent = false;
|
||||
m_resendKeyEvent = false;
|
||||
return accepted;
|
||||
}
|
||||
|
||||
- (void)keyDown:(NSEvent *)nsevent
|
||||
{
|
||||
if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) )
|
||||
return [super keyDown:nsevent];
|
||||
[self handleKeyEvent:nsevent eventType:int(QEvent::KeyPress)];
|
||||
|
||||
const bool accepted = [self handleKeyEvent:nsevent eventType:int(QEvent::KeyPress)];
|
||||
|
||||
// Track keyDown acceptance state for later acceptance of the keyUp.
|
||||
if (accepted)
|
||||
m_acceptedKeyDowns.insert([nsevent keyCode]);
|
||||
|
||||
// Propagate the keyDown to the next responder if Qt did not accept it.
|
||||
if (!accepted)
|
||||
[super keyDown:nsevent];
|
||||
}
|
||||
|
||||
- (void)keyUp:(NSEvent *)nsevent
|
||||
{
|
||||
if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) )
|
||||
return [super keyUp:nsevent];
|
||||
[self handleKeyEvent:nsevent eventType:int(QEvent::KeyRelease)];
|
||||
|
||||
const bool keyUpAccepted = [self handleKeyEvent:nsevent eventType:int(QEvent::KeyRelease)];
|
||||
|
||||
// Propagate the keyUp if neither Qt accepted it nor the corresponding KeyDown was
|
||||
// accepted. Qt text controls wil often not use and ignore keyUp events, but we
|
||||
// want to avoid propagating unmatched keyUps.
|
||||
const bool keyDownAccepted = m_acceptedKeyDowns.remove([nsevent keyCode]);
|
||||
if (!keyUpAccepted && !keyDownAccepted)
|
||||
[super keyUp:nsevent];
|
||||
}
|
||||
|
||||
- (void)cancelOperation:(id)sender
|
||||
|
|
|
|||
Loading…
Reference in New Issue