-
Notifications
You must be signed in to change notification settings - Fork 6.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Android] Fix popup bounds to honor top and bottom controls
(Copy and continuation of https://crrev.com/c/4101981) This CL makes the anchored popup view check the webcontents rect if one is available. This prevents overlay of the keyboard or the Omnibox as shown in https://crbug.com/856040#c9 and reacts to live changes of the available space (e.g. after rotation or accessory animation). Additionally, it ensures a minimal Popup size of 50x50dip which prevents the popup to show up and be selectable when contents are not readable. Known issues: - Fairly large for a potential merge. - If web contents scroll, the popup disappears; seems pre-existing. Images and video in https://crbug.com/856040#c10 and #c9 Fixed: 856040, 1274887, 1398579 Change-Id: I0f4f2f3091392dddfb309d4abd405ad8df49cd40 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4123739 Reviewed-by: David Trainor <dtrainor@chromium.org> Reviewed-by: Dominic Battré <battre@chromium.org> Commit-Queue: Friedrich Horschig <fhorschig@chromium.org> Reviewed-by: Bo Liu <boliu@chromium.org> Cr-Commit-Position: refs/heads/main@{#1095024}
- Loading branch information
Showing
12 changed files
with
349 additions
and
45 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
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
132 changes: 132 additions & 0 deletions
132
...me/android/java/src/org/chromium/chrome/browser/autofill/WebContentsViewRectProvider.java
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,132 @@ | ||
// Copyright 2023 The Chromium Authors | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
package org.chromium.chrome.browser.autofill; | ||
|
||
import android.graphics.Rect; | ||
|
||
import androidx.annotation.Nullable; | ||
|
||
import org.chromium.base.Callback; | ||
import org.chromium.base.supplier.ObservableSupplier; | ||
import org.chromium.base.supplier.Supplier; | ||
import org.chromium.chrome.browser.fullscreen.BrowserControlsManager; | ||
import org.chromium.chrome.browser.keyboard_accessory.ManualFillingComponent; | ||
import org.chromium.content_public.browser.WebContents; | ||
import org.chromium.ui.base.ViewAndroidDelegate; | ||
import org.chromium.ui.widget.RectProvider; | ||
|
||
/** | ||
* Helper class that computes the visible rect of a given {@link WebContents} objects. It observes | ||
* the given {@link WebContents} object to update the observed suppliers of browser controls and | ||
* filling component. Use like a standard {@link RectProvider}. | ||
* | ||
* Examples for observed changes: | ||
* - {@link BrowserControlsManager} providing height for elements like the Omnibox. | ||
* - {@link ManualFillingComponent} providing filling surface height like Keyboard Accessory. | ||
* - A Bottom Inset supplier for the Soft-keyboard. | ||
*/ | ||
class WebContentsViewRectProvider extends RectProvider { | ||
private final WebContents mWebContents; | ||
private ObservableSupplier<BrowserControlsManager> mBrowserControlsSupplier; | ||
private ObservableSupplier<ManualFillingComponent> mManualFillingComponentSupplier; | ||
private ObservableSupplier<Integer> mBottomInsetSupplier; | ||
|
||
private final Callback<ManualFillingComponent> mOnManualFillingComponentChanged = | ||
fillComponent -> observeBottomInsetSupplier(fillComponent.getBottomInsetSupplier()); | ||
private final Callback<Integer> mOnBottomInsetChanged = bottomInset | ||
-> updateVisibleRectForPopup(bottomInset, getValueOrNull(mBrowserControlsSupplier)); | ||
private final Callback<BrowserControlsManager> mOnBrowserControlsChanged = | ||
ctrlMgr -> updateVisibleRectForPopup(getValueOrNull(mBottomInsetSupplier), ctrlMgr); | ||
|
||
/** | ||
* Creates a new RectProvider and starts observing given parameters. If they provide a valid | ||
* rect, it's immediately computed. | ||
* | ||
* @param webContents A required, non-null {@link WebContents} object. | ||
* @param browserControlsSupplier A {@link ObservableSupplier<BrowserControlsManager>}. | ||
* @param manualFillingComponentSupplier A {@link ObservableSupplier<ManualFillingComponent>}. | ||
*/ | ||
public WebContentsViewRectProvider(WebContents webContents, | ||
ObservableSupplier<BrowserControlsManager> browserControlsSupplier, | ||
ObservableSupplier<ManualFillingComponent> manualFillingComponentSupplier) { | ||
assert webContents != null; | ||
assert webContents.getViewAndroidDelegate() != null; | ||
assert webContents.getViewAndroidDelegate().getContainerView() != null; | ||
|
||
mWebContents = webContents; | ||
observeManualFillingComponentSupplier(manualFillingComponentSupplier); | ||
observeBrowserControlsSupplier(browserControlsSupplier); | ||
} | ||
|
||
/** | ||
* Stops observing the suppliers given in the constructor. | ||
*/ | ||
public void dismiss() { | ||
observeManualFillingComponentSupplier(null); | ||
observeBrowserControlsSupplier(null); | ||
} | ||
|
||
private void observeBrowserControlsSupplier( | ||
@Nullable ObservableSupplier<BrowserControlsManager> supplier) { | ||
if (mBrowserControlsSupplier != null) { | ||
mBrowserControlsSupplier.removeObserver(mOnBrowserControlsChanged); | ||
} | ||
mBrowserControlsSupplier = supplier; | ||
if (mBrowserControlsSupplier != null) { | ||
mBrowserControlsSupplier.addObserver(mOnBrowserControlsChanged); | ||
} | ||
updateVisibleRectForPopup( | ||
getValueOrNull(mBottomInsetSupplier), getValueOrNull(mBrowserControlsSupplier)); | ||
} | ||
|
||
private void observeManualFillingComponentSupplier( | ||
@Nullable ObservableSupplier<ManualFillingComponent> supplier) { | ||
if (mManualFillingComponentSupplier != null) { | ||
observeBottomInsetSupplier(null); | ||
mManualFillingComponentSupplier.removeObserver(mOnManualFillingComponentChanged); | ||
} | ||
mManualFillingComponentSupplier = supplier; | ||
if (mManualFillingComponentSupplier != null) { | ||
mManualFillingComponentSupplier.addObserver(mOnManualFillingComponentChanged); | ||
observeBottomInsetSupplier(mManualFillingComponentSupplier.hasValue() | ||
? mManualFillingComponentSupplier.get().getBottomInsetSupplier() | ||
: null); | ||
} | ||
} | ||
|
||
private void observeBottomInsetSupplier(@Nullable ObservableSupplier<Integer> supplier) { | ||
if (mBottomInsetSupplier != null) { | ||
mBottomInsetSupplier.removeObserver(mOnBottomInsetChanged); | ||
} | ||
mBottomInsetSupplier = supplier; | ||
if (mBottomInsetSupplier != null) { | ||
mBottomInsetSupplier.addObserver(mOnBottomInsetChanged); | ||
} | ||
updateVisibleRectForPopup( | ||
getValueOrNull(mBottomInsetSupplier), getValueOrNull(mBrowserControlsSupplier)); | ||
} | ||
|
||
private void updateVisibleRectForPopup( | ||
@Nullable Integer bottomInset, @Nullable BrowserControlsManager browserControls) { | ||
ViewAndroidDelegate viewDelegate = mWebContents.getViewAndroidDelegate(); | ||
|
||
// Stop computing a rect if the WebContents view is gone for some reason. | ||
if (viewDelegate == null || viewDelegate.getContainerView() == null) return; | ||
|
||
Rect rect = new Rect(); | ||
viewDelegate.getContainerView().getGlobalVisibleRect(rect); | ||
if (browserControls != null) { | ||
rect.top += browserControls.getTopControlsHeight(); | ||
rect.bottom -= browserControls.getBottomControlOffset(); | ||
} | ||
if (bottomInset != null) rect.bottom -= bottomInset; | ||
|
||
if (!mRect.equals(rect)) setRect(rect); // Update and notify only if the rect changes. | ||
} | ||
|
||
private static @Nullable<T> T getValueOrNull(@Nullable Supplier<T> supplier) { | ||
return supplier != null ? supplier.get() : null; | ||
} | ||
} |
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
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
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
Oops, something went wrong.