iOS: Detect window deactivation without waiting for next runloop iteration

Since we know and control whether or not we are making a new QUIView first
responder, we can take not of this at that point, and use that information
when another view is resigning first responder.

Change-Id: I508720d418c92dc8a8011b489cc5cace8fc82633
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@digia.com>
This commit is contained in:
Tor Arne Vestbø 2014-10-16 15:37:48 +02:00
parent 5a4fad1479
commit 50cadb87e8
3 changed files with 58 additions and 17 deletions

View File

@ -71,4 +71,14 @@ QT_END_NAMESPACE
+(id)currentFirstResponder;
@end
class FirstResponderCandidate : public QScopedValueRollback<UIResponder *>
{
public:
FirstResponderCandidate(UIResponder *);
static UIResponder *currentCandidate() { return s_firstResponderCandidate; }
private:
static UIResponder *s_firstResponderCandidate;
};
#endif // QIOSGLOBAL_H

View File

@ -168,5 +168,12 @@ int infoPlistValue(NSString* key, int defaultValue)
}
@end
FirstResponderCandidate::FirstResponderCandidate(UIResponder *responder)
: QScopedValueRollback<UIResponder *>(s_firstResponderCandidate, responder)
{
}
UIResponder *FirstResponderCandidate::s_firstResponderCandidate = 0;
QT_END_NAMESPACE

View File

@ -191,33 +191,57 @@
- (BOOL)becomeFirstResponder
{
if ([super becomeFirstResponder]) {
QWindowSystemInterface::handleWindowActivated(m_qioswindow->window());
QWindowSystemInterface::flushWindowSystemEvents();
FirstResponderCandidate firstResponderCandidate(self);
return YES;
qImDebug() << "win:" << m_qioswindow->window() << "self:" << self
<< "first:" << [UIResponder currentFirstResponder];
if (![super becomeFirstResponder]) {
qImDebug() << m_qioswindow->window()
<< "was not allowed to become first responder";
return NO;
}
return NO;
qImDebug() << m_qioswindow->window() << "became first responder";
if (qGuiApp->focusWindow() != m_qioswindow->window()) {
QWindowSystemInterface::handleWindowActivated(m_qioswindow->window());
QWindowSystemInterface::flushWindowSystemEvents();
} else {
qImDebug() << m_qioswindow->window()
<< "already active, not sending window activation";
}
return YES;
}
- (BOOL)responderShouldTriggerWindowDeactivation:(UIResponder *)responder
{
// We don't want to send window deactivation in case the resign
// was a result of another Qt window becoming first responder.
if ([responder isKindOfClass:[QUIView class]])
return NO;
return YES;
}
- (BOOL)resignFirstResponder
{
if ([super resignFirstResponder]) {
// We don't want to send window deactivation in case we're in the process
// of activating another window. The handleWindowActivated of the activation
// will take care of both.
dispatch_async(dispatch_get_main_queue (), ^{
if (![[UIResponder currentFirstResponder] isKindOfClass:[QUIView class]]) {
QWindowSystemInterface::handleWindowActivated(0);
QWindowSystemInterface::flushWindowSystemEvents();
}
});
qImDebug() << "win:" << m_qioswindow->window() << "self:" << self
<< "first:" << [UIResponder currentFirstResponder];
return YES;
if (![super resignFirstResponder])
return NO;
qImDebug() << m_qioswindow->window() << "resigned first responder";
UIResponder *newResponder = FirstResponderCandidate::currentCandidate();
if ([self responderShouldTriggerWindowDeactivation:newResponder]) {
QWindowSystemInterface::handleWindowActivated(0);
QWindowSystemInterface::flushWindowSystemEvents();
}
return NO;
return YES;
}
// -------------------------------------------------------------------------