From aba5f6d9be8ff0a6d83c32f56d8d3a02f59d2a88 Mon Sep 17 00:00:00 2001 From: Sergey Minakov Date: Tue, 11 Jan 2022 13:56:45 +0300 Subject: [PATCH] [iOS] Fix touch handling for overlay views Workaround for GodotView touches being called from UIWindow on different UIView input --- platform/iphone/godot_view.h | 5 +++ platform/iphone/godot_view.mm | 8 ++--- .../iphone/godot_view_gesture_recognizer.mm | 31 +++++++++++++------ 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/platform/iphone/godot_view.h b/platform/iphone/godot_view.h index a8d10d9fc7b..76316b91802 100644 --- a/platform/iphone/godot_view.h +++ b/platform/iphone/godot_view.h @@ -65,4 +65,9 @@ class String; @property(nonatomic, assign) BOOL useCADisplayLink; +- (void)godotTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; +- (void)godotTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; +- (void)godotTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; +- (void)godotTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event; + @end diff --git a/platform/iphone/godot_view.mm b/platform/iphone/godot_view.mm index df55aebd0f1..dc6623cb531 100644 --- a/platform/iphone/godot_view.mm +++ b/platform/iphone/godot_view.mm @@ -331,7 +331,7 @@ static const int max_touches = 8; } } -- (void)touchesBegan:(NSSet *)touchesSet withEvent:(UIEvent *)event { +- (void)godotTouchesBegan:(NSSet *)touchesSet withEvent:(UIEvent *)event { NSArray *tlist = [event.allTouches allObjects]; for (unsigned int i = 0; i < [tlist count]; i++) { if ([touchesSet containsObject:[tlist objectAtIndex:i]]) { @@ -349,7 +349,7 @@ static const int max_touches = 8; } } -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { +- (void)godotTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { NSArray *tlist = [event.allTouches allObjects]; for (unsigned int i = 0; i < [tlist count]; i++) { if ([touches containsObject:[tlist objectAtIndex:i]]) { @@ -370,7 +370,7 @@ static const int max_touches = 8; } } -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { +- (void)godotTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { NSArray *tlist = [event.allTouches allObjects]; for (unsigned int i = 0; i < [tlist count]; i++) { if ([touches containsObject:[tlist objectAtIndex:i]]) { @@ -388,7 +388,7 @@ static const int max_touches = 8; } } -- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { +- (void)godotTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { NSArray *tlist = [event.allTouches allObjects]; for (unsigned int i = 0; i < [tlist count]; i++) { if ([touches containsObject:[tlist objectAtIndex:i]]) { diff --git a/platform/iphone/godot_view_gesture_recognizer.mm b/platform/iphone/godot_view_gesture_recognizer.mm index d1cc06e7c5d..3e351cb6cb1 100644 --- a/platform/iphone/godot_view_gesture_recognizer.mm +++ b/platform/iphone/godot_view_gesture_recognizer.mm @@ -29,6 +29,7 @@ /*************************************************************************/ #import "godot_view_gesture_recognizer.h" +#import "godot_view.h" #include "core/project_settings.h" @@ -46,6 +47,10 @@ const CGFloat kGLGestureMovementDistance = 0.5; @implementation GodotViewGestureRecognizer +- (GodotView *)godotView { + return (GodotView *)self.view; +} + - (instancetype)init { self = [super init]; @@ -72,7 +77,7 @@ const CGFloat kGLGestureMovementDistance = 0.5; delayTimer = nil; if (delayedTouches) { - [self.view touchesBegan:delayedTouches withEvent:delayedEvent]; + [self.godotView godotTouchesBegan:delayedTouches withEvent:delayedEvent]; } delayedTouches = nil; @@ -82,6 +87,8 @@ const CGFloat kGLGestureMovementDistance = 0.5; - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseBegan]; [self delayTouches:cleared andEvent:event]; + + [super touchesBegan:touches withEvent:event]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { @@ -91,8 +98,8 @@ const CGFloat kGLGestureMovementDistance = 0.5; // We should check if movement was significant enough to fire an event // for dragging to work correctly. for (UITouch *touch in cleared) { - CGPoint from = [touch locationInView:self.view]; - CGPoint to = [touch previousLocationInView:self.view]; + CGPoint from = [touch locationInView:self.godotView]; + CGPoint to = [touch previousLocationInView:self.godotView]; CGFloat xDistance = from.x - to.x; CGFloat yDistance = from.y - to.y; @@ -101,33 +108,39 @@ const CGFloat kGLGestureMovementDistance = 0.5; // Early exit, since one of touches has moved enough to fire a drag event. if (distance > kGLGestureMovementDistance) { [delayTimer fire]; - [self.view touchesMoved:cleared withEvent:event]; + [self.godotView godotTouchesMoved:cleared withEvent:event]; return; } } return; } - [self.view touchesMoved:cleared withEvent:event]; + [self.godotView touchesMoved:cleared withEvent:event]; + + [super touchesMoved:touches withEvent:event]; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { [delayTimer fire]; NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseEnded]; - [self.view touchesEnded:cleared withEvent:event]; + [self.godotView godotTouchesEnded:cleared withEvent:event]; + + [super touchesEnded:touches withEvent:event]; } - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { [delayTimer fire]; - [self.view touchesCancelled:touches withEvent:event]; -}; + [self.godotView godotTouchesCancelled:touches withEvent:event]; + + [super touchesCancelled:touches withEvent:event]; +} - (NSSet *)copyClearedTouches:(NSSet *)touches phase:(UITouchPhase)phaseToSave { NSMutableSet *cleared = [touches mutableCopy]; for (UITouch *touch in touches) { - if (touch.phase != phaseToSave) { + if (touch.view != self.view || touch.phase != phaseToSave) { [cleared removeObject:touch]; } }