improve inset handling

This commit is contained in:
Fabian Freund
2026-07-07 12:11:26 +02:00
parent dc8ca693f5
commit 2989d5e824
2 changed files with 19 additions and 4 deletions
@@ -732,9 +732,16 @@ class BrowserScreen extends HookConsumerWidget {
[selectedTabId], [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 = final stableToolbarHeight =
autoHideTabBar && !toolbarDismissed.value && !tabInFullScreen autoHideTabBar && !toolbarDismissed.value && !tabInFullScreen
? bottomAppBarTotalHeight ? autoHideToolbarHeight
: 0.0; : 0.0;
final stableToolbarHeightPx = (stableToolbarHeight * pixelRatio).round(); final stableToolbarHeightPx = (stableToolbarHeight * pixelRatio).round();
@@ -814,9 +821,14 @@ class BrowserScreen extends HookConsumerWidget {
final effectiveVisible = toolbarState == ToolbarVisibility.visible; final effectiveVisible = toolbarState == ToolbarVisibility.visible;
final dismissed = toolbarState == ToolbarVisibility.dismissed; final dismissed = toolbarState == ToolbarVisibility.dismissed;
// When hidden: clip from bottom by toolbar height so GeckoView // Dynamic toolbar clipping is bottom-inset-only; top toolbar layout is
// can compute its layout while Flutter animates. // handled by Flutter's topOffset instead of Gecko's bottom inset channel.
// When visible/dismissed or overridden by keyboard/loading: no clipping. // 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 = final targetClippingPx =
autoHideTabBar && autoHideTabBar &&
!dismissed && !dismissed &&
@@ -824,7 +836,7 @@ class BrowserScreen extends HookConsumerWidget {
!keyboardVisible && !keyboardVisible &&
!tabIsLoading && !tabIsLoading &&
!tabInFullScreen !tabInFullScreen
? -(bottomAppBarTotalHeight * pixelRatio).round() ? hiddenToolbarClippingPx
: 0; : 0;
if (targetClippingPx != lastClippingPx.value) { if (targetClippingPx != lastClippingPx.value) {
@@ -871,6 +883,7 @@ class BrowserScreen extends HookConsumerWidget {
bottomAppBarTotalHeight, bottomAppBarTotalHeight,
pixelRatio, pixelRatio,
selectedTabId, selectedTabId,
tabBarPosition,
], ],
); );
@@ -579,6 +579,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
GlobalComponents.viewportEvents?.let { viewportEvents -> GlobalComponents.viewportEvents?.let { viewportEvents ->
keyboardVisibilityFeature = KeyboardVisibilityFeature(viewportEvents).also { keyboardVisibilityFeature = KeyboardVisibilityFeature(viewportEvents).also {
it.start(binding.root) it.start(binding.root)
binding.root.post { it.checkKeyboardState() }
} }
if (shouldStartBrowserHandlingScrollFeature) { if (shouldStartBrowserHandlingScrollFeature) {
@@ -687,6 +688,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
fragmentEngineView?.let { fragmentEngineView?.let {
components.activeEngineView = it components.activeEngineView = it
} }
keyboardVisibilityFeature?.checkKeyboardState()
} }
override fun onDestroyView() { override fun onDestroyView() {