From 2989d5e824b927bfcf2c9428b3bb3980b74d5b12 Mon Sep 17 00:00:00 2001 From: Fabian Freund Date: Tue, 7 Jul 2026 12:11:26 +0200 Subject: [PATCH] improve inset handling --- .../browser/presentation/screens/browser.dart | 21 +++++++++++++++---- .../BaseBrowserFragment.kt | 2 ++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/apps/weblibre/lib/features/geckoview/features/browser/presentation/screens/browser.dart b/apps/weblibre/lib/features/geckoview/features/browser/presentation/screens/browser.dart index 857a7564..d1e7ea6c 100644 --- a/apps/weblibre/lib/features/geckoview/features/browser/presentation/screens/browser.dart +++ b/apps/weblibre/lib/features/geckoview/features/browser/presentation/screens/browser.dart @@ -732,9 +732,16 @@ class BrowserScreen extends HookConsumerWidget { [selectedTabId], ); + final autoHideToolbarHeight = switch (tabBarPosition) { + // Gecko's dynamic toolbar value is consumed as a bottom inset by Dart and + // native UI. The top toolbar itself is positioned with Flutter's topOffset. + TabBarPosition.top || TabBarPosition.bottom => bottomAppBarTotalHeight, + TabBarPosition.left || TabBarPosition.right => 0.0, + }; + final stableToolbarHeight = autoHideTabBar && !toolbarDismissed.value && !tabInFullScreen - ? bottomAppBarTotalHeight + ? autoHideToolbarHeight : 0.0; final stableToolbarHeightPx = (stableToolbarHeight * pixelRatio).round(); @@ -814,9 +821,14 @@ class BrowserScreen extends HookConsumerWidget { final effectiveVisible = toolbarState == ToolbarVisibility.visible; final dismissed = toolbarState == ToolbarVisibility.dismissed; - // When hidden: clip from bottom by toolbar height so GeckoView - // can compute its layout while Flutter animates. + // Dynamic toolbar clipping is bottom-inset-only; top toolbar layout is + // handled by Flutter's topOffset instead of Gecko's bottom inset channel. // When visible/dismissed or overridden by keyboard/loading: no clipping. + final hiddenToolbarClippingPx = switch (tabBarPosition) { + TabBarPosition.top || TabBarPosition.bottom => + -(bottomAppBarTotalHeight * pixelRatio).round(), + TabBarPosition.left || TabBarPosition.right => 0, + }; final targetClippingPx = autoHideTabBar && !dismissed && @@ -824,7 +836,7 @@ class BrowserScreen extends HookConsumerWidget { !keyboardVisible && !tabIsLoading && !tabInFullScreen - ? -(bottomAppBarTotalHeight * pixelRatio).round() + ? hiddenToolbarClippingPx : 0; if (targetClippingPx != lastClippingPx.value) { @@ -871,6 +883,7 @@ class BrowserScreen extends HookConsumerWidget { bottomAppBarTotalHeight, pixelRatio, selectedTabId, + tabBarPosition, ], ); diff --git a/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/BaseBrowserFragment.kt b/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/BaseBrowserFragment.kt index 3a7dcb9f..bf8faaed 100644 --- a/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/BaseBrowserFragment.kt +++ b/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/BaseBrowserFragment.kt @@ -579,6 +579,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit GlobalComponents.viewportEvents?.let { viewportEvents -> keyboardVisibilityFeature = KeyboardVisibilityFeature(viewportEvents).also { it.start(binding.root) + binding.root.post { it.checkKeyboardState() } } if (shouldStartBrowserHandlingScrollFeature) { @@ -687,6 +688,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit fragmentEngineView?.let { components.activeEngineView = it } + keyboardVisibilityFeature?.checkKeyboardState() } override fun onDestroyView() {