Skip to content

🐛 [iOS] Present the camera from a dedicated window by default - #639

Open
PierreVieira wants to merge 1 commit into
vinceglb:mainfrom
PierreVieira:fix/camera-default-presenter-window
Open

🐛 [iOS] Present the camera from a dedicated window by default#639
PierreVieira wants to merge 1 commit into
vinceglb:mainfrom
PierreVieira:fix/camera-default-presenter-window

Conversation

@PierreVieira

Copy link
Copy Markdown
Contributor

Fixes #638.

Problem

When no explicit presenter is supplied, openCameraPicker presents the in-process fullscreen UIImagePickerController from topMostViewController() — i.e. in the app's main window. Hosts whose dialogs live in their own UIWindow above modal view controllers — Compose Multiplatform since 1.11 (JetBrains/compose-multiplatform-core#2270, CMP-9772) — end up with the camera presented underneath the dialog window. After the picker dismissal, touch handling is corrupted app-wide: every tap shows the press indication but never completes a click, until process restart. The gallery path never hits this because PHPickerViewController is out-of-process.

The deliver-after-dismissal fix from #619 is necessary but not sufficient here: the corruption comes from the presentation itself happening below the dialog window.

Fix

CameraPresenterWindow hosts the camera presentation in a FileKit-managed transparent UIWindow: created on the active scene, made key above UIWindowLevelAlert, attached right before presenting, and detached — restoring the previous key window — once the capture flow finishes. The try/finally covers every exit: photo delivered, cancellation, and prepareAppleCameraPresentation failures (camera unavailable, requested facing unavailable).

Apps passing an explicit presenter through FileKitOpenCameraSettings(presenter = ...) keep the exact previous behavior — the managed window is only created when presenter is null. This matches the JetBrains-recommended pattern of presenting native modals from an app-managed window when CMP dialog windows are involved.

Testing

:filekit-dialogs:compileKotlinIosSimulatorArm64 and :filekit-dialogs:iosSimulatorArm64Test pass. The dedicated-window presentation recipe itself is confirmed on a physical iPhone 15 (iOS 17, Compose Multiplatform 1.11.1): an equivalent implementation applied through FileKitOpenCameraSettings(presenter = ...) in our app fully resolves the touch corruption described in #638, with the camera, cancellation and error paths all restoring the previous key window correctly.

When no explicit presenter is supplied, openCameraPicker used to present
the fullscreen UIImagePickerController from the top-most view controller
of the main window. Hosts whose dialogs live in their own UIWindow above
modal view controllers — Compose Multiplatform since 1.11 — end up with
the camera presented underneath that dialog window, which corrupts touch
handling app-wide after the picker dismissal (vinceglb#638).

The camera presentation is now hosted in a FileKit-managed transparent
UIWindow made key above alerts, attached right before presenting and
detached — restoring the previous key window — once the capture flow
finishes, including failure paths. Apps passing an explicit presenter
through FileKitOpenCameraSettings keep the previous behavior.
@PierreVieira
PierreVieira force-pushed the fix/camera-default-presenter-window branch from 2f11f30 to eca703c Compare August 11, 2026 21:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[iOS] Default camera presenter breaks touch handling when launched from a Compose Multiplatform 1.11+ Dialog

1 participant