summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/ios/qiosinputcontext.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/ios/qiosinputcontext.mm')
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm64
1 files changed, 58 insertions, 6 deletions
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index 13a0b46745..9a2c55f7f2 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -47,6 +47,7 @@
#include "qioswindow.h"
#include "quiview.h"
#include <QGuiApplication>
+#include <QtGui/private/qwindow_p.h>
@interface QIOSKeyboardListener : UIGestureRecognizer {
@public
@@ -54,6 +55,8 @@
BOOL m_keyboardVisible;
BOOL m_keyboardVisibleAndDocked;
BOOL m_ignoreKeyboardChanges;
+ BOOL m_touchPressWhileKeyboardVisible;
+ BOOL m_keyboardHiddenByGesture;
QRectF m_keyboardRect;
QRectF m_keyboardEndRect;
NSTimeInterval m_duration;
@@ -72,6 +75,8 @@
m_keyboardVisible = NO;
m_keyboardVisibleAndDocked = NO;
m_ignoreKeyboardChanges = NO;
+ m_touchPressWhileKeyboardVisible = NO;
+ m_keyboardHiddenByGesture = NO;
m_duration = 0;
m_curve = UIViewAnimationCurveEaseOut;
m_viewController = 0;
@@ -145,9 +150,6 @@
- (void) keyboardDidChangeFrame:(NSNotification *)notification
{
Q_UNUSED(notification);
- if (m_ignoreKeyboardChanges)
- return;
-
[self handleKeyboardRectChanged];
// If the keyboard was visible and docked from before, this is just a geometry
@@ -178,7 +180,11 @@
// Note that UIKeyboardWillHideNotification is also sendt when the keyboard is undocked.
m_keyboardVisibleAndDocked = NO;
m_keyboardEndRect = [self getKeyboardRect:notification];
- self.enabled = NO;
+ if (!m_keyboardHiddenByGesture) {
+ // Only disable the gesture if the hiding of the keyboard was not caused by it.
+ // Otherwise we need to await the final touchEnd callback for doing some clean-up.
+ self.enabled = NO;
+ }
m_context->scroll(0);
}
@@ -201,12 +207,45 @@
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
QPointF p = fromCGPoint([[touches anyObject] locationInView:m_viewController.view]);
- if (m_keyboardRect.contains(p))
+ if (m_keyboardRect.contains(p)) {
+ m_keyboardHiddenByGesture = YES;
m_context->hideInputPanel();
+ }
[super touchesMoved:touches withEvent:event];
}
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ Q_ASSERT(m_keyboardVisibleAndDocked);
+ m_touchPressWhileKeyboardVisible = YES;
+ [super touchesBegan:touches withEvent:event];
+}
+
+- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ m_touchPressWhileKeyboardVisible = NO;
+ [self performSelectorOnMainThread:@selector(touchesEndedPostDelivery) withObject:nil waitUntilDone:NO];
+ [super touchesEnded:touches withEvent:event];
+}
+
+- (void)touchesEndedPostDelivery
+{
+ // Do some clean-up _after_ touchEnd has been delivered to QUIView
+ m_keyboardHiddenByGesture = NO;
+ if (!m_keyboardVisibleAndDocked) {
+ self.enabled = NO;
+ if (qApp->focusObject()) {
+ // UI Controls are told to gain focus on touch release. So when the 'hide keyboard' gesture
+ // finishes, the final touch end can trigger a control to gain focus. This is in conflict with
+ // the gesture, so we clear focus once more as a work-around.
+ static_cast<QWindowPrivate *>(QObjectPrivate::get(qApp->focusWindow()))->clearFocusObject();
+ }
+ } else {
+ m_context->scrollToCursor();
+ }
+}
+
@end
QIOSInputContext::QIOSInputContext()
@@ -233,6 +272,12 @@ QRectF QIOSInputContext::keyboardRect() const
void QIOSInputContext::showInputPanel()
{
+ if (m_keyboardListener->m_keyboardHiddenByGesture) {
+ // We refuse to re-show the keyboard until the touch
+ // sequence that triggered the gesture has ended.
+ return;
+ }
+
// Documentation tells that one should call (and recall, if necessary) becomeFirstResponder/resignFirstResponder
// to show/hide the keyboard. This is slightly inconvenient, since there exist no API to get the current first
// responder. Rather than searching for it from the top, we let the active QIOSWindow tell us which view to use.
@@ -306,6 +351,13 @@ void QIOSInputContext::scrollToCursor()
if (!isQtApplication() || !m_focusView)
return;
+ if (m_keyboardListener->m_touchPressWhileKeyboardVisible) {
+ // Don't scroll to the cursor if the user is touching the screen. This
+ // interferes with selection and the 'hide keyboard' gesture. Instead
+ // we update scrolling upon touchEnd.
+ return;
+ }
+
UIView *view = m_keyboardListener->m_viewController.view;
if (view.window != m_focusView.window)
return;
@@ -332,7 +384,7 @@ void QIOSInputContext::scroll(int y)
newBounds.origin.y = y;
QPointer<QIOSInputContext> self = this;
[UIView animateWithDuration:m_keyboardListener->m_duration delay:0
- options:m_keyboardListener->m_curve
+ options:m_keyboardListener->m_curve | UIViewAnimationOptionBeginFromCurrentState
animations:^{ view.bounds = newBounds; }
completion:^(BOOL){
if (self)