forked from androidx/androidx
-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Touches forwarding to underlying interop views on iOS (#1426)
First approach to allow touches to be processed by both Compose and nested interop views. Other UX improvements will follow. 1. `actual typealias InteropView = UIView` 2. Change `ComposeScene` API to allow hit testing specific `InteropView`. 3. Make `InteractionUIView` a `container` view of `InteropContainer` to enforce it being in the same responder chain as interop views. 4. Remove `InteractionUIView.Delegate` and replace it with callbacks to avoid `by lazy` reentry in `ComposeSceneMediator`, make `InteractionUIView` construction eager. 5. Use `event.allTouches` instead of `event.touchesForView` to avoid receiving an empty list in case `InteractionUIView` is part of responder chain but not the hit test result itself. 6. Remove `KeyboardEventHandler.uikit.kt` to avoid `by lazy` reentry, stick everything in a single lambda. Fixes some of the cases from the domain of JetBrains/compose-multiplatform#4818 ## Testing `Demo/IosBugs/UIKitRenderSync` now properly registers touches to allow LazyColumn scrolling and native view reaction. ## Release Notes ### iOS - Fixes - Touches inside interop views are not exclusive to them and are processed on Compose side as well. ### Multiple Platforms - Breaking changes - ComposeScene `fun hitTestInteropView(position: Offset): Boolean` changed to `fun hitTestInteropView(position: Offset): InteropView?` --------- Co-authored-by: Ivan Matkov <ivan.matkov@jetbrains.com>
- Loading branch information
1 parent
26b4dee
commit a78dd41
Showing
25 changed files
with
606 additions
and
275 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
compose/ui/ui-uikit/src/uikitMain/objc/CMPUIKitUtils/CMPUIKitUtils/CMPGestureRecognizer.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// | ||
// CMPGestureRecognizer.h | ||
// CMPUIKitUtils | ||
// | ||
// Created by Ilia.Semenov on 28/06/2024. | ||
// | ||
|
||
#import <UIKit/UIKit.h> | ||
#import <UIKit/UIGestureRecognizerSubclass.h> | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
@protocol CMPGestureRecognizerHandler <NSObject> | ||
|
||
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent * _Nullable)event; | ||
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent * _Nullable)event; | ||
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent * _Nullable)event; | ||
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent * _Nullable)event; | ||
- (BOOL)shouldRecognizeSimultaneously:(UIGestureRecognizer *)first withOther:(UIGestureRecognizer *)second; | ||
|
||
@end | ||
|
||
@interface CMPGestureRecognizer : UIGestureRecognizer <UIGestureRecognizerDelegate> | ||
|
||
@property (weak, nonatomic) id <CMPGestureRecognizerHandler> handler; | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
88 changes: 88 additions & 0 deletions
88
compose/ui/ui-uikit/src/uikitMain/objc/CMPUIKitUtils/CMPUIKitUtils/CMPGestureRecognizer.m
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
// | ||
// CMPGestureRecognizer.m | ||
// CMPUIKitUtils | ||
// | ||
// Created by Ilia.Semenov on 28/06/2024. | ||
// | ||
|
||
#import "CMPGestureRecognizer.h" | ||
|
||
@implementation CMPGestureRecognizer | ||
|
||
- (instancetype)init { | ||
self = [super init]; | ||
|
||
if (self) { | ||
self.cancelsTouchesInView = false; | ||
self.delegate = self; | ||
} | ||
|
||
return self; | ||
} | ||
|
||
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { | ||
id <CMPGestureRecognizerHandler> handler = self.handler; | ||
|
||
if (handler) { | ||
return [handler shouldRecognizeSimultaneously:gestureRecognizer withOther:otherGestureRecognizer]; | ||
} else { | ||
return NO; | ||
} | ||
} | ||
|
||
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { | ||
[self.handler touchesBegan:touches withEvent:event]; | ||
|
||
if (self.state == UIGestureRecognizerStatePossible) { | ||
self.state = UIGestureRecognizerStateBegan; | ||
} | ||
} | ||
|
||
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { | ||
[self.handler touchesMoved:touches withEvent:event]; | ||
|
||
switch (self.state) { | ||
case UIGestureRecognizerStateBegan: | ||
case UIGestureRecognizerStateChanged: | ||
self.state = UIGestureRecognizerStateChanged; | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
|
||
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { | ||
[self.handler touchesEnded:touches withEvent:event]; | ||
|
||
switch (self.state) { | ||
case UIGestureRecognizerStateBegan: | ||
case UIGestureRecognizerStateChanged: | ||
if (self.numberOfTouches == 0) { | ||
self.state = UIGestureRecognizerStateEnded; | ||
} else { | ||
self.state = UIGestureRecognizerStateChanged; | ||
} | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
|
||
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { | ||
[self.handler touchesCancelled:touches withEvent:event]; | ||
|
||
switch (self.state) { | ||
case UIGestureRecognizerStateBegan: | ||
case UIGestureRecognizerStateChanged: | ||
if (self.numberOfTouches == 0) { | ||
self.state = UIGestureRecognizerStateCancelled; | ||
} else { | ||
self.state = UIGestureRecognizerStateChanged; | ||
} | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/viewinterop/InteropView.desktop.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* | ||
* Copyright 2024 The Android Open Source Project | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package androidx.compose.ui.viewinterop | ||
|
||
/** | ||
* A typealias for the platform's built-in View type, which may be hosted inside of a Compose UI | ||
* hierarchy to allow for interoperability. Not all platforms support interoperability in this way, | ||
* in which case the typealias will resolve to [Any]. | ||
*/ | ||
actual typealias InteropView = Any |
24 changes: 24 additions & 0 deletions
24
compose/ui/ui/src/jsWasmMain/kotlin/androidx/compose/ui/viewinterop/InteropView.jsWasm.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* | ||
* Copyright 2024 The Android Open Source Project | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package androidx.compose.ui.viewinterop | ||
|
||
/** | ||
* A typealias for the platform's built-in View type, which may be hosted inside of a Compose UI | ||
* hierarchy to allow for interoperability. Not all platforms support interoperability in this way, | ||
* in which case the typealias will resolve to [Any]. | ||
*/ | ||
actual typealias InteropView = Any |
24 changes: 24 additions & 0 deletions
24
compose/ui/ui/src/macosMain/kotlin/androidx/compose/ui/viewinterop/InteropView.macos.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* | ||
* Copyright 2024 The Android Open Source Project | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package androidx.compose.ui.viewinterop | ||
|
||
/** | ||
* A typealias for the platform's built-in View type, which may be hosted inside of a Compose UI | ||
* hierarchy to allow for interoperability. Not all platforms support interoperability in this way, | ||
* in which case the typealias will resolve to [Any]. | ||
*/ | ||
actual typealias InteropView = Any |
40 changes: 0 additions & 40 deletions
40
...src/skikoMain/kotlin/androidx/compose/ui/input/pointer/InteropViewCatchPointerModifier.kt
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.