Skip to content

Combine multiple UIView sources to get window insets#2946

Merged
Vendula Švastalová (svastven) merged 3 commits into
jb-mainfrom
svastven/window-insets
Apr 10, 2026
Merged

Combine multiple UIView sources to get window insets#2946
Vendula Švastalová (svastven) merged 3 commits into
jb-mainfrom
svastven/window-insets

Conversation

@svastven

Copy link
Copy Markdown

Combine multiple UIView sources to get correct window insets. Fixes support for embedding compose views in UIKit navigation view with UIKit navigation bar and iPad insets for traffic light controls.

Fixes CMP-9931 iOS: WindowInsets.safeDrawing does not include UINavigationBar safe area insets (regression in 1.11.0-alpha04)

Testing

Test CMP-8922 on iPad in combination with sample provided in CMP-9931

This should be tested by QA

Release Notes

Fixes - iOS

  • (prerelease fix) Fix UINavigationBar safe area insets not included in WindowInsets.safeDrawing

@ASalavei Andrei Salavei (ASalavei) left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, waiting for green tests

@svastven Vendula Švastalová (svastven) merged commit 42d25ff into jb-main Apr 10, 2026
17 checks passed
@svastven Vendula Švastalová (svastven) deleted the svastven/window-insets branch April 10, 2026 09:24
Vendula Švastalová (svastven) added a commit that referenced this pull request Apr 10, 2026
Combine multiple UIView sources to get correct window insets. Fixes
support for embedding compose views in UIKit navigation view with UIKit
navigation bar and iPad insets for traffic light controls.

Fixes [CMP-9931](https://youtrack.jetbrains.com/issue/CMP-9931) iOS:
WindowInsets.safeDrawing does not include UINavigationBar safe area
insets (regression in 1.11.0-alpha04)

Test [CMP-8922](https://youtrack.jetbrains.com/issue/CMP-8922) on iPad
in combination with sample provided in
[CMP-9931](https://youtrack.jetbrains.com/issue/CMP-9931)

This should be tested by QA

- _(prerelease fix)_ Fix `UINavigationBar` safe area insets not included
in `WindowInsets.safeDrawing`
Vendula Švastalová (svastven) added a commit that referenced this pull request Apr 10, 2026
Combine multiple UIView sources to get correct window insets. Fixes
support for embedding compose views in UIKit navigation view with UIKit
navigation bar and iPad insets for traffic light controls.

Fixes [CMP-9931](https://youtrack.jetbrains.com/issue/CMP-9931) iOS:
WindowInsets.safeDrawing does not include UINavigationBar safe area
insets (regression in 1.11.0-alpha04)

Test [CMP-8922](https://youtrack.jetbrains.com/issue/CMP-8922) on iPad
in combination with sample provided in
[CMP-9931](https://youtrack.jetbrains.com/issue/CMP-9931)

This should be tested by QA

- _(prerelease fix)_ Fix `UINavigationBar` safe area insets not included
in `WindowInsets.safeDrawing`
Ekaterina Zaitseva (sekater) added a commit that referenced this pull request Apr 10, 2026
…2946) (#2965)

Combine multiple UIView sources to get correct window insets. Fixes
support for embedding compose views in UIKit navigation view with UIKit
navigation bar and iPad insets for traffic light controls.

Fixes [CMP-9931](https://youtrack.jetbrains.com/issue/CMP-9931) iOS:
WindowInsets.safeDrawing does not include UINavigationBar safe area
insets (regression in 1.11.0-alpha04)

## Testing

Test [CMP-8922](https://youtrack.jetbrains.com/issue/CMP-8922) on iPad
in combination with sample provided in
[CMP-9931](https://youtrack.jetbrains.com/issue/CMP-9931)

This should be tested by QA

## Release Notes
### Fixes - iOS
- _(prerelease fix)_ Fix `UINavigationBar` safe area insets not included
in `WindowInsets.safeDrawing`
Jacob Rhoda (jadar) pushed a commit to jadar/compose-multiplatform-core that referenced this pull request May 25, 2026
…ered surfaces

Fixes [CMP-10230](https://youtrack.jetbrains.com/issue/CMP-10230)

`UIKitWindowInsetsManager` per-edge `union()`s safe-area insets from the
local `_overlayView` with those from `window.rootViewController.view`.
This was added in JetBrains#2946 to cover CMP-9931 (missing `UINavigationBar`
height) and CMP-8922 (iPad Stage Manager traffic-light controls), but
over-reports whenever the Compose surface is positioned below window-
level chrome that does not intersect `_overlayView`, or whose ancestor
chain filters safe-area propagation (`UIHostingController.safeAreaRegions
= .keyboard`, parent `additionalSafeAreaInsets`, manual frame placement).
The local view correctly reports zero for the affected edge, but the
window root reports the global value and `max()` wins.

This commit:

1. Removes the `window.rootViewController.view` source from
   `windowInsetsViews`. Standard UIKit safe-area propagation already
   incorporates ancestor chrome into a child view's `safeAreaInsets`
   for typical hosting setups, so the CMP-9931 navbar case should
   still be covered. Worth re-validating against the original repro.

2. Adds a dedicated `onSafeAreaInsetsDidChange` callback on
   `BackgroundInputView` (parallel to the existing `onLayoutSubviews`)
   wired to a new `internal fun onSafeAreaInsetsDidChange()` on the
   mediator. The callback is invoked directly from
   `safeAreaInsetsDidChange`, without going through `setNeedsLayout`,
   so Compose re-reads insets even when the parent reposition leaves
   the input view's local frame unchanged.

3. Adds an Obj-C bridge on `CMPViewController` to expose
   `viewSafeAreaInsetsDidChange` for Kotlin override (matches the
   existing `userInterfaceStyleDidChange` pattern). The new
   `safeAreaInsetsDidUpdate` hook is implemented in
   `ComposeHostingViewController` and forwards through
   `container.onSafeAreaInsetsDidChange()`. This is defense-in-depth
   alongside the view-level hook. Each path is a no-op when the value
   hasn't changed (`mutableStateOf` only triggers recompose on actual
   change), so redundant delivery is cheap.

The existing `WindowInsetsPaddingTest.testWindowInsetsPaddingAppliedTo
NonFullscreenComposeUIViewContent` encoded the union semantics; it has
been renamed and inverted to assert the new contract (no padding on a
non-fullscreen embedded `ComposeUIView`). The fullscreen-outer test is
unchanged.

Known limitation not addressed by this commit: iOS does not deliver
`safeAreaInsetsDidChange` (UIView) or `viewSafeAreaInsetsDidChange`
(UIViewController) to a view/VC occluded by a presented sheet,
including during interactive sheet dismissal ("peek"). Confirmed
empirically with both hooks wired. Per-frame `CADisplayLink` polling
does not help because the read returns the same stale value iOS is
caching; geometric inset computation from window-space position
handles peek but over-subtracts the legitimate navbar contribution in
standard `UINavigationController` setups.

## Release Notes
### Fixes - iOS
- Fix `WindowInsets` over-reported on Compose surfaces positioned below
  window-level chrome that does not intersect the host view (e.g. under
  a `UIHostingController` with `safeAreaRegions = .keyboard`).
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.

3 participants