diff --git a/CodenameOne/src/com/codename1/ui/Component.java b/CodenameOne/src/com/codename1/ui/Component.java index 368e0ec7e3..d25adfa0e1 100644 --- a/CodenameOne/src/com/codename1/ui/Component.java +++ b/CodenameOne/src/com/codename1/ui/Component.java @@ -7000,7 +7000,7 @@ public boolean animate() { Painter bgp = getStyle().getBgPainter(); boolean animateBackgroundB = bgp != null && - bgp.getClass() != BGPainter.class && + !(bgp instanceof BGPainter) && bgp instanceof Animation && ((Animation) bgp).animate(); animateBackground = animateBackgroundB || animateBackground; diff --git a/Ports/iOSPort/nativeSources/CN1TapGestureRecognizer.m b/Ports/iOSPort/nativeSources/CN1TapGestureRecognizer.m index a7ef051572..21edcea83a 100644 --- a/Ports/iOSPort/nativeSources/CN1TapGestureRecognizer.m +++ b/Ports/iOSPort/nativeSources/CN1TapGestureRecognizer.m @@ -50,8 +50,6 @@ - (void) install:(CodenameOne_GLViewController*)ctrl { self.delegate = self; [ctrl.view.window addGestureRecognizer:self]; CN1useTapGestureRecognizer = YES; - - } - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer @@ -62,6 +60,24 @@ - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer return false; } +// iOS 26 auto-installs a UITapGestureRecognizer on every UIWindow with +// _keyboardDismissalGestureRecognized: as its action. Its default +// cancelsTouchesInView=YES, plus its position in the window-level recognizer +// chain ahead of ours, means it can consume tap-down events before CN1TapGR +// ever sees touchesBegan -- the simulator's indirect-pointer-as-touch +// dispatch tickles this path. Insist that CN1TapGR is required to fail +// before any window-level UITapGestureRecognizer can recognise, so we keep +// first crack at every touch regardless of what iOS installed. +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer + shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { + if (gestureRecognizer == self + && [otherGestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] + && otherGestureRecognizer.view == self.view) { + return YES; + } + return NO; +} + /** * Some events need to be ignored. We only want to receive events originating from our view hierarchy * that is controlled by the GLViewController. @@ -87,7 +103,7 @@ -(BOOL)ignoreEvent:(UITouch*)touch { } - (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event -{ +{ [super touchesBegan:touches withEvent:event]; POOL_BEGIN(); if(touchesArray == nil) { diff --git a/Ports/iOSPort/nativeSources/CodenameOne_GLViewController.m b/Ports/iOSPort/nativeSources/CodenameOne_GLViewController.m index c612a92d49..4942a3cd56 100644 --- a/Ports/iOSPort/nativeSources/CodenameOne_GLViewController.m +++ b/Ports/iOSPort/nativeSources/CodenameOne_GLViewController.m @@ -2785,6 +2785,13 @@ - (void)cn1InstallHoverRecognizer { UIHoverGestureRecognizer *hover = [[UIHoverGestureRecognizer alloc] initWithTarget:self action:@selector(cn1HandleHover:)]; + // UIGestureRecognizer defaults cancelsTouchesInView to YES, which on + // simulator builds where the host-mac mouse cursor is always hovering + // over the window can cancel taps before they reach touchesBegan:. + // Hover is independent of touch; don't let it preempt. + hover.cancelsTouchesInView = NO; + hover.delaysTouchesBegan = NO; + hover.delaysTouchesEnded = NO; [self.view addGestureRecognizer:hover]; #ifndef CN1_USE_ARC [hover release];