2978 lines
156 KiB
Diff
2978 lines
156 KiB
Diff
From: uazo <uazo@users.noreply.github.com>
|
|
Date: Tue, 18 Jan 2022 07:43:32 +0000
|
|
Subject: Move navigation bar to bottom
|
|
|
|
Adds an accessibility flag that allows navigation bar to be moved to the bottom.
|
|
Unlike what is present in other browsers, this actually moves the bar below,
|
|
without creating other elements.
|
|
The bottom bar will also be colored as the navigation bar to make the interface
|
|
more pleasant and fixes upstream bug 1285311.
|
|
Support for tablet mode is also included.
|
|
|
|
Need: bromite-build-utils.patch
|
|
Original License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html
|
|
License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html
|
|
---
|
|
cc/base/features.cc | 8 +
|
|
cc/base/features.h | 2 +
|
|
cc/input/browser_controls_offset_manager.cc | 6 +
|
|
cc/trees/layer_tree_host_impl.cc | 3 +
|
|
.../start_surface/StartSurfaceMediator.java | 4 +
|
|
.../tab_management/TabGroupUiCoordinator.java | 7 +-
|
|
.../tab_management/TabGroupUiMediator.java | 56 ++++++-
|
|
.../tab_management/TabGroupUiProperties.java | 7 +-
|
|
.../tab_management/TabGroupUiToolbarView.java | 17 ++
|
|
.../tab_management/TabGroupUiViewBinder.java | 3 +
|
|
.../tab_management/TabListCoordinator.java | 153 +++++++++++++++++-
|
|
.../TabListEmptyCoordinator.java | 17 +-
|
|
.../settings/AccessibilitySettings.java | 26 +++
|
|
.../ChromeAccessibilitySettingsDelegate.java | 69 ++++++++
|
|
.../chrome/browser/app/ChromeActivity.java | 3 +
|
|
.../compositor/CompositorViewHolder.java | 7 +
|
|
.../layouts/LayoutManagerChrome.java | 19 ++-
|
|
.../layouts/LayoutManagerChromeTablet.java | 4 +-
|
|
.../layouts/ToolbarSwipeLayout.java | 14 +-
|
|
.../overlays/strip/StripLayoutHelper.java | 2 +-
|
|
.../strip/StripLayoutHelperManager.java | 38 ++++-
|
|
.../scene_layer/StaticTabSceneLayer.java | 7 +-
|
|
.../scene_layer/TabListSceneLayer.java | 8 +
|
|
.../scene_layer/TabStripSceneLayer.java | 19 ++-
|
|
.../browser/findinpage/FindToolbarTablet.java | 10 +-
|
|
.../fullscreen/BrowserControlsManager.java | 12 ++
|
|
.../messages/MessageContainerCoordinator.java | 16 +-
|
|
.../modaldialog/ChromeTabModalPresenter.java | 2 +-
|
|
.../chrome/browser/ntp/NewTabPage.java | 14 +-
|
|
.../chrome/browser/ntp/NewTabPageLayout.java | 12 +-
|
|
.../chrome/browser/ntp/RecentTabsPage.java | 30 +++-
|
|
.../browser/searchwidget/SearchActivity.java | 11 ++
|
|
.../browser/settings/SettingsActivity.java | 5 +
|
|
.../StatusIndicatorCoordinator.java | 9 ++
|
|
.../StatusIndicatorSceneLayer.java | 6 +-
|
|
.../browser/toolbar/ToolbarManager.java | 37 ++++-
|
|
.../chrome/browser/ui/BottomContainer.java | 18 +++
|
|
.../ui/system/StatusBarColorController.java | 9 ++
|
|
.../android/compositor/layer/toolbar_layer.cc | 10 +-
|
|
.../scene_layer/tab_strip_scene_layer.cc | 16 +-
|
|
.../BottomControlsStacker.java | 2 +-
|
|
.../BrowserControlsMarginSupplier.java | 5 +
|
|
.../BrowserControlsStateProvider.java | 6 +
|
|
.../browser/feed/FeedListContentManager.java | 6 +-
|
|
.../flags/android/chrome_feature_list.cc | 3 +
|
|
.../browser/flags/ChromeFeatureList.java | 10 ++
|
|
chrome/browser/hub/internal/BUILD.gn | 5 +
|
|
.../chrome/browser/hub/HubCoordinator.java | 8 +
|
|
.../chrome/browser/hub/HubManagerImpl.java | 17 +-
|
|
.../browser/hub/ReversedLinearLayout.java | 42 +++++
|
|
.../android/res/layout/hub_layout.xml | 4 +-
|
|
.../android/res/layout/hub_toolbar_layout.xml | 2 +-
|
|
chrome/browser/prefs/browser_prefs.cc | 2 +-
|
|
.../chrome/browser/ui/appmenu/AppMenu.java | 40 ++++-
|
|
.../ui/appmenu/AppMenuHandlerImpl.java | 10 ++
|
|
...mniboxSuggestionsDropdownEmbedderImpl.java | 18 +++
|
|
.../suggestions/AutocompleteCoordinator.java | 13 ++
|
|
.../suggestions/AutocompleteMediator.java | 6 +-
|
|
.../DropdownItemViewInfoListManager.java | 7 +-
|
|
.../OmniboxSuggestionsDropdown.java | 11 +-
|
|
.../OmniboxSuggestionsDropdownEmbedder.java | 4 +
|
|
.../strings/android_chrome_strings.grd | 6 +
|
|
chrome/browser/ui/android/toolbar/BUILD.gn | 1 +
|
|
.../toolbar/LocationBarFocusScrimHandler.java | 5 +
|
|
.../bottom/BottomControlsContentDelegate.java | 9 +-
|
|
.../bottom/BottomControlsCoordinator.java | 11 +-
|
|
.../bottom/BottomControlsMediator.java | 18 ++-
|
|
.../bottom/BottomControlsProperties.java | 6 +-
|
|
.../bottom/BottomControlsViewBinder.java | 2 +
|
|
.../bottom/ScrollingBottomViewSceneLayer.java | 19 ++-
|
|
.../toolbar/top/ToolbarControlContainer.java | 9 ++
|
|
.../top/TopToolbarOverlayCoordinator.java | 10 ++
|
|
.../top/TopToolbarOverlayProperties.java | 8 +-
|
|
.../toolbar/top/TopToolbarSceneLayer.java | 10 +-
|
|
.../res/xml/accessibility_preferences.xml | 8 +
|
|
.../AccessibilitySettingsDelegate.java | 7 +
|
|
.../render_widget_host_view_android.cc | 3 +
|
|
.../Move-navigation-bar-to-bottom.inc | 17 ++
|
|
78 files changed, 1006 insertions(+), 80 deletions(-)
|
|
create mode 100644 chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/ReversedLinearLayout.java
|
|
create mode 100644 cromite_flags/chrome/browser/about_flags_cc/Move-navigation-bar-to-bottom.inc
|
|
|
|
diff --git a/cc/base/features.cc b/cc/base/features.cc
|
|
--- a/cc/base/features.cc
|
|
+++ b/cc/base/features.cc
|
|
@@ -38,6 +38,14 @@ BASE_FEATURE(kSynchronizedScrolling,
|
|
base::FEATURE_ENABLED_BY_DEFAULT);
|
|
#endif
|
|
|
|
+BASE_FEATURE(kMoveTopToolbarToBottom,
|
|
+ "MoveTopToolbarToBottom",
|
|
+ base::FEATURE_DISABLED_BY_DEFAULT);
|
|
+
|
|
+BASE_FEATURE(kDisableToolbarSwipeUp,
|
|
+ "DisableToolbarSwipeUp",
|
|
+ base::FEATURE_DISABLED_BY_DEFAULT);
|
|
+
|
|
BASE_FEATURE(kRemoveMobileViewportDoubleTap,
|
|
"RemoveMobileViewportDoubleTap",
|
|
base::FEATURE_ENABLED_BY_DEFAULT);
|
|
diff --git a/cc/base/features.h b/cc/base/features.h
|
|
--- a/cc/base/features.h
|
|
+++ b/cc/base/features.h
|
|
@@ -17,6 +17,8 @@ namespace features {
|
|
CC_BASE_EXPORT BASE_DECLARE_FEATURE(kAnimatedImageResume);
|
|
CC_BASE_EXPORT extern bool IsImpulseScrollAnimationEnabled();
|
|
CC_BASE_EXPORT BASE_DECLARE_FEATURE(kSynchronizedScrolling);
|
|
+CC_BASE_EXPORT BASE_DECLARE_FEATURE(kMoveTopToolbarToBottom);
|
|
+CC_BASE_EXPORT BASE_DECLARE_FEATURE(kDisableToolbarSwipeUp);
|
|
|
|
// When enabled, the double tap to zoom will be disabled when the viewport
|
|
// meta tag is properly set for mobile using content=width=device-width
|
|
diff --git a/cc/input/browser_controls_offset_manager.cc b/cc/input/browser_controls_offset_manager.cc
|
|
--- a/cc/input/browser_controls_offset_manager.cc
|
|
+++ b/cc/input/browser_controls_offset_manager.cc
|
|
@@ -20,6 +20,7 @@
|
|
#include "ui/gfx/animation/tween.h"
|
|
#include "ui/gfx/geometry/transform.h"
|
|
#include "ui/gfx/geometry/vector2d_f.h"
|
|
+#include "cc/base/features.h"
|
|
|
|
namespace cc {
|
|
namespace {
|
|
@@ -496,6 +497,11 @@ gfx::Vector2dF BrowserControlsOffsetManager::ScrollBy(
|
|
// content. If the top controls have no height, the content should scroll
|
|
// immediately.
|
|
gfx::Vector2dF applied_delta(0.f, old_top_offset - ContentTopOffset());
|
|
+ // do not eat scroll offsets if the flag is on, since the content view
|
|
+ // top offsets are not changed. It is necessary to synchronize the scroll
|
|
+ // with the offset of the user's movement
|
|
+ if (base::FeatureList::IsEnabled(::features::kMoveTopToolbarToBottom))
|
|
+ return pending_delta;
|
|
return pending_delta - applied_delta;
|
|
}
|
|
|
|
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
|
|
--- a/cc/trees/layer_tree_host_impl.cc
|
|
+++ b/cc/trees/layer_tree_host_impl.cc
|
|
@@ -4496,6 +4496,9 @@ bool LayerTreeHostImpl::AnimateBrowserControls(base::TimeTicks time) {
|
|
if (scroll_delta.IsZero())
|
|
return false;
|
|
|
|
+ if (base::FeatureList::IsEnabled(::features::kMoveTopToolbarToBottom))
|
|
+ return false;
|
|
+
|
|
// This counter-scrolls the page to keep the appearance of the page content
|
|
// being fixed while the browser controls animate.
|
|
viewport().ScrollBy(scroll_delta,
|
|
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
|
|
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
|
|
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
|
|
@@ -98,6 +98,8 @@ import org.chromium.url.GURL;
|
|
|
|
import java.util.List;
|
|
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
+
|
|
/** The mediator implements the logic to interact with the surfaces and caller. */
|
|
class StartSurfaceMediator
|
|
implements StartSurface.OnTabSelectingListener,
|
|
@@ -860,6 +862,8 @@ class StartSurfaceMediator
|
|
}
|
|
|
|
private void setTopMargin(int topMargin) {
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled())
|
|
+ topMargin = 0;
|
|
mPropertyModel.set(TOP_MARGIN, topMargin);
|
|
}
|
|
|
|
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java
|
|
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java
|
|
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java
|
|
@@ -38,6 +38,7 @@ import org.chromium.components.feature_engagement.FeatureConstants;
|
|
import org.chromium.ui.modaldialog.ModalDialogManager;
|
|
import org.chromium.ui.modelutil.PropertyModel;
|
|
import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
|
|
+import org.chromium.chrome.browser.theme.TopUiThemeColorProvider;
|
|
|
|
import java.util.List;
|
|
|
|
@@ -156,7 +157,8 @@ public class TabGroupUiCoordinator
|
|
public void initializeWithNative(
|
|
Activity activity,
|
|
BottomControlsCoordinator.BottomControlsVisibilityController visibilityController,
|
|
- Callback<Object> onModelTokenChange) {
|
|
+ Callback<Object> onModelTokenChange,
|
|
+ TopUiThemeColorProvider topUiThemeColorProvider, ObservableSupplier<Tab> tabSupplier) {
|
|
var currentTabModelFilterSupplier =
|
|
mTabModelSelector.getTabModelFilterProvider().getCurrentTabModelFilterSupplier();
|
|
try (TraceEvent e = TraceEvent.scoped("TabGroupUiCoordinator.initializeWithNative")) {
|
|
@@ -214,7 +216,8 @@ public class TabGroupUiCoordinator
|
|
mLayoutStateProviderSupplier,
|
|
mIncognitoStateProvider,
|
|
mTabGridDialogControllerSupplier,
|
|
- mOmniboxFocusStateSupplier);
|
|
+ mOmniboxFocusStateSupplier,
|
|
+ topUiThemeColorProvider, tabSupplier);
|
|
|
|
TabGroupUtils.startObservingForCreationIPH();
|
|
}
|
|
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
|
|
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
|
|
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
|
|
@@ -52,6 +52,12 @@ import org.chromium.url.GURL;
|
|
|
|
import java.util.List;
|
|
|
|
+import org.chromium.chrome.browser.theme.TopUiThemeColorProvider;
|
|
+import org.chromium.chrome.browser.tab.CurrentTabObserver;
|
|
+import org.chromium.chrome.browser.tab.EmptyTabObserver;
|
|
+import org.chromium.chrome.browser.tab.Tab;
|
|
+import androidx.annotation.ColorInt;
|
|
+
|
|
/** A mediator for the TabGroupUi. Responsible for managing the internal state of the component. */
|
|
public class TabGroupUiMediator implements BackPressHandler {
|
|
/** An interface to control the TabGroupUi component. */
|
|
@@ -118,6 +124,11 @@ public class TabGroupUiMediator implements BackPressHandler {
|
|
private final @ColorInt int mPrimaryBackgroundColor;
|
|
private final @ColorInt int mIncognitoBackgroundColor;
|
|
|
|
+ private final TopUiThemeColorProvider mTopUiThemeColorProvider;
|
|
+
|
|
+ /** An observer that watches for changes in the active tab. */
|
|
+ private final CurrentTabObserver mTabObserver;
|
|
+
|
|
TabGroupUiMediator(
|
|
Context context,
|
|
BottomControlsVisibilityController visibilityController,
|
|
@@ -131,7 +142,8 @@ public class TabGroupUiMediator implements BackPressHandler {
|
|
@Nullable
|
|
LazyOneshotSupplier<TabGridDialogMediator.DialogController>
|
|
dialogControllerSupplier,
|
|
- ObservableSupplier<Boolean> omniboxFocusStateSupplier) {
|
|
+ ObservableSupplier<Boolean> omniboxFocusStateSupplier,
|
|
+ TopUiThemeColorProvider topUiThemeColorProvider, ObservableSupplier<Tab> tabSupplier) {
|
|
this(
|
|
context,
|
|
visibilityController,
|
|
@@ -145,7 +157,8 @@ public class TabGroupUiMediator implements BackPressHandler {
|
|
dialogControllerSupplier,
|
|
omniboxFocusStateSupplier,
|
|
SemanticColorUtils.getDialogBgColor(context),
|
|
- context.getColor(org.chromium.chrome.R.color.dialog_bg_color_dark_baseline));
|
|
+ context.getColor(org.chromium.chrome.R.color.dialog_bg_color_dark_baseline),
|
|
+ topUiThemeColorProvider, tabSupplier);
|
|
}
|
|
|
|
@VisibleForTesting
|
|
@@ -164,7 +177,9 @@ public class TabGroupUiMediator implements BackPressHandler {
|
|
dialogControllerSupplier,
|
|
ObservableSupplier<Boolean> omniboxFocusStateSupplier,
|
|
@ColorInt int primaryBackgroundColor,
|
|
- @ColorInt int incognitoBackgroundColor) {
|
|
+ @ColorInt int incognitoBackgroundColor,
|
|
+ TopUiThemeColorProvider topUiThemeColorProvider, ObservableSupplier<Tab> tabSupplier) {
|
|
+ mTopUiThemeColorProvider = topUiThemeColorProvider;
|
|
mContext = context;
|
|
mResetHandler = resetHandler;
|
|
mModel = model;
|
|
@@ -183,11 +198,30 @@ public class TabGroupUiMediator implements BackPressHandler {
|
|
mIsShowingOverViewMode = true;
|
|
}
|
|
|
|
+ // Keep an observer attached to the visible tab (and only the visible tab) to update
|
|
+ // properties including theme color.
|
|
+ Callback<Tab> activityTabCallback = (tab) -> {
|
|
+ if (tab == null) return;
|
|
+ updateThemeColor(tab);
|
|
+ };
|
|
+ mTabObserver = new CurrentTabObserver(tabSupplier, new EmptyTabObserver() {
|
|
+ @Override
|
|
+ public void onDidChangeThemeColor(Tab tab, int color) {
|
|
+ updateThemeColor(tab);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void onContentChanged(Tab tab) {
|
|
+ updateThemeColor(tab);
|
|
+ }
|
|
+ }, activityTabCallback);
|
|
+
|
|
// register for tab model
|
|
mTabModelObserver =
|
|
new TabModelObserver() {
|
|
@Override
|
|
public void didSelectTab(Tab tab, @TabSelectionType int type, int lastId) {
|
|
+ updateThemeColor(tab);
|
|
if (getTabsToShowForId(lastId).contains(tab)) {
|
|
return;
|
|
}
|
|
@@ -247,6 +281,7 @@ public class TabGroupUiMediator implements BackPressHandler {
|
|
return;
|
|
}
|
|
resetTabStripWithRelatedTabsForId(currentTab.getId());
|
|
+ updateThemeColor(currentTab);
|
|
}
|
|
|
|
@Override
|
|
@@ -372,6 +407,8 @@ public class TabGroupUiMediator implements BackPressHandler {
|
|
resetTabStripWithRelatedTabsForId(tab.getId());
|
|
}
|
|
|
|
+ mTabObserver.triggerWithCurrentTab();
|
|
+
|
|
mHandleBackPressChangedSupplier = handleBackPressChangedSupplier;
|
|
if (mTabGridDialogControllerSupplier != null) {
|
|
mTabGridDialogControllerSupplier.onAvailable(
|
|
@@ -399,6 +436,18 @@ public class TabGroupUiMediator implements BackPressHandler {
|
|
mModel.set(TabGroupUiProperties.LEFT_BUTTON_DRAWABLE_ID, drawableId);
|
|
}
|
|
|
|
+ /**
|
|
+ * Update the colors of the layer based on the specified tab.
|
|
+ * @param tab The tab to base the colors on.
|
|
+ */
|
|
+ private void updateThemeColor(Tab tab) {
|
|
+ if (tab != null) {
|
|
+ @ColorInt
|
|
+ int color = mTopUiThemeColorProvider.getSceneLayerBackground(tab);
|
|
+ mModel.set(TabGroupUiProperties.PRIMARY_COLOR, color);
|
|
+ }
|
|
+ }
|
|
+
|
|
void setupLeftButtonOnClickListener(View.OnClickListener listener) {
|
|
mModel.set(TabGroupUiProperties.LEFT_BUTTON_ON_CLICK_LISTENER, listener);
|
|
}
|
|
@@ -528,6 +577,7 @@ public class TabGroupUiMediator implements BackPressHandler {
|
|
}
|
|
|
|
public void destroy() {
|
|
+ mTabObserver.destroy();
|
|
if (mTabModelSelector != null) {
|
|
var filterProvider = mTabModelSelector.getTabModelFilterProvider();
|
|
|
|
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiProperties.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiProperties.java
|
|
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiProperties.java
|
|
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiProperties.java
|
|
@@ -8,6 +8,7 @@ import android.view.View.OnClickListener;
|
|
|
|
import org.chromium.ui.modelutil.PropertyKey;
|
|
import org.chromium.ui.modelutil.PropertyModel;
|
|
+import android.content.res.ColorStateList;
|
|
|
|
/** {@link PropertyKey} list for the TabGroupUi. */
|
|
class TabGroupUiProperties {
|
|
@@ -36,6 +37,9 @@ class TabGroupUiProperties {
|
|
public static final PropertyModel.WritableObjectPropertyKey<String>
|
|
RIGHT_BUTTON_CONTENT_DESCRIPTION = new PropertyModel.WritableObjectPropertyKey<>();
|
|
|
|
+ public static final PropertyModel.WritableIntPropertyKey PRIMARY_COLOR =
|
|
+ new PropertyModel.WritableIntPropertyKey();
|
|
+
|
|
public static final PropertyKey[] ALL_KEYS =
|
|
new PropertyKey[] {
|
|
LEFT_BUTTON_ON_CLICK_LISTENER,
|
|
@@ -46,6 +50,7 @@ class TabGroupUiProperties {
|
|
BACKGROUND_COLOR,
|
|
INITIAL_SCROLL_INDEX,
|
|
LEFT_BUTTON_CONTENT_DESCRIPTION,
|
|
- RIGHT_BUTTON_CONTENT_DESCRIPTION
|
|
+ RIGHT_BUTTON_CONTENT_DESCRIPTION,
|
|
+ PRIMARY_COLOR
|
|
};
|
|
}
|
|
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiToolbarView.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiToolbarView.java
|
|
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiToolbarView.java
|
|
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiToolbarView.java
|
|
@@ -21,6 +21,10 @@ import androidx.core.widget.ImageViewCompat;
|
|
import org.chromium.chrome.tab_ui.R;
|
|
import org.chromium.ui.widget.ChromeImageView;
|
|
|
|
+import org.chromium.ui.util.ColorUtils;
|
|
+import org.chromium.chrome.browser.theme.ThemeUtils;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
+
|
|
/** Toolbar for the bottom tab strip see {@link TabGroupUiCoordinator}. */
|
|
public class TabGroupUiToolbarView extends FrameLayout {
|
|
private ChromeImageView mRightButton;
|
|
@@ -86,6 +90,19 @@ public class TabGroupUiToolbarView extends FrameLayout {
|
|
mFadingEdgeEnd.setColorFilter(color, PorterDuff.Mode.SRC_IN);
|
|
}
|
|
|
|
+ void setPrimaryColorAndApplyTint(int color) {
|
|
+ if (!ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled())
|
|
+ return;
|
|
+
|
|
+ // change the background color of the bottom bar if the top toolbar is below
|
|
+ setContentBackgroundColor(color);
|
|
+
|
|
+ // and adjust the tint
|
|
+ boolean useLightTint = ColorUtils.shouldUseLightForegroundOnBackground(color);
|
|
+ ColorStateList tint = ThemeUtils.getThemedToolbarIconTint(getContext(), useLightTint);
|
|
+ setTint(tint);
|
|
+ }
|
|
+
|
|
void setTint(ColorStateList tint) {
|
|
ImageViewCompat.setImageTintList(mLeftButton, tint);
|
|
ImageViewCompat.setImageTintList(mRightButton, tint);
|
|
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinder.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinder.java
|
|
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinder.java
|
|
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinder.java
|
|
@@ -13,6 +13,7 @@ import static org.chromium.chrome.browser.tasks.tab_management.TabGroupUiPropert
|
|
import static org.chromium.chrome.browser.tasks.tab_management.TabGroupUiProperties.LEFT_BUTTON_ON_CLICK_LISTENER;
|
|
import static org.chromium.chrome.browser.tasks.tab_management.TabGroupUiProperties.RIGHT_BUTTON_CONTENT_DESCRIPTION;
|
|
import static org.chromium.chrome.browser.tasks.tab_management.TabGroupUiProperties.RIGHT_BUTTON_ON_CLICK_LISTENER;
|
|
+import static org.chromium.chrome.browser.tasks.tab_management.TabGroupUiProperties.PRIMARY_COLOR;
|
|
|
|
import android.view.View;
|
|
|
|
@@ -71,6 +72,8 @@ class TabGroupUiViewBinder {
|
|
} else if (RIGHT_BUTTON_CONTENT_DESCRIPTION == propertyKey) {
|
|
viewHolder.toolbarView.setRightButtonContentDescription(
|
|
model.get(RIGHT_BUTTON_CONTENT_DESCRIPTION));
|
|
+ } else if (PRIMARY_COLOR == propertyKey) {
|
|
+ viewHolder.toolbarView.setPrimaryColorAndApplyTint(model.get(PRIMARY_COLOR));
|
|
}
|
|
}
|
|
}
|
|
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
|
|
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
|
|
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
|
|
@@ -6,8 +6,12 @@ package org.chromium.chrome.browser.tasks.tab_management;
|
|
|
|
import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.CardProperties.CARD_TYPE;
|
|
|
|
+import android.os.Parcel;
|
|
+import android.os.Parcelable;
|
|
+
|
|
import android.app.Activity;
|
|
import android.content.Context;
|
|
+import android.content.res.Configuration;
|
|
import android.graphics.Rect;
|
|
import android.util.Size;
|
|
import android.view.LayoutInflater;
|
|
@@ -55,6 +59,8 @@ import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
|
|
import org.chromium.ui.modelutil.SimpleRecyclerViewAdapter;
|
|
import org.chromium.ui.widget.ViewLookupCachingFrameLayout;
|
|
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
+
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
import java.util.List;
|
|
@@ -112,6 +118,128 @@ public class TabListCoordinator
|
|
private int mAwaitingTabId = Tab.INVALID_TAB_ID;
|
|
private @TabActionState int mTabActionState;
|
|
|
|
+ public class GridLayoutManagerDockBottom extends GridLayoutManager {
|
|
+ public static class SavedState implements Parcelable {
|
|
+ private Parcelable superState;
|
|
+ private int mTopPadding;
|
|
+
|
|
+ public SavedState() {}
|
|
+
|
|
+ public SavedState(Parcel in) {
|
|
+ superState = in.readParcelable(GridLayoutManager.class.getClassLoader());
|
|
+ mTopPadding = in.readInt();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int describeContents() {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
|
|
+ dest.writeParcelable(superState, flags);
|
|
+ dest.writeInt(mTopPadding);
|
|
+ }
|
|
+
|
|
+ public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
|
|
+ @Override
|
|
+ public SavedState createFromParcel(Parcel in) {
|
|
+ return new SavedState(in);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public SavedState[] newArray(int size) {
|
|
+ return new SavedState[size];
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+
|
|
+ Context mContext;
|
|
+
|
|
+ TabListRecyclerView mRecyclerView;
|
|
+
|
|
+ final int MAX_TOP_PADDING = 99999;
|
|
+ int mTopPadding = MAX_TOP_PADDING;
|
|
+
|
|
+ int mLastPosition = -1;
|
|
+ boolean mIsFirstLayout = true;
|
|
+
|
|
+ public GridLayoutManagerDockBottom(Context context, int spanCount) {
|
|
+ super(context, spanCount);
|
|
+ mContext = context;
|
|
+ }
|
|
+
|
|
+ public void setTabListRecyclerView(TabListRecyclerView recyclerView) {
|
|
+ mRecyclerView = recyclerView;
|
|
+ }
|
|
+
|
|
+ public void ResetTopPosition() {
|
|
+ mIsFirstLayout = true;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int getPaddingTop() {
|
|
+ if (mContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
|
+ mTopPadding = MAX_TOP_PADDING;
|
|
+ return 0;
|
|
+ }
|
|
+ if (mTopPadding == MAX_TOP_PADDING) return super.getPaddingTop();
|
|
+ return mTopPadding;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int getPaddingBottom() {
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void scrollToPositionWithOffset(int position, int offset) {
|
|
+ mLastPosition = position;
|
|
+ super.scrollToPositionWithOffset(position, offset - getPaddingTop());
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void onLayoutCompleted(RecyclerView.State state) {
|
|
+ super.onLayoutCompleted(state);
|
|
+ checkAwaitingLayout();
|
|
+
|
|
+ if (state.isPreLayout() || state.isMeasuring()) return;
|
|
+ View lastView = findViewByPosition(findFirstVisibleItemPosition());
|
|
+ if (lastView != null) {
|
|
+ if (mTopPadding == 0) mTopPadding = MAX_TOP_PADDING;
|
|
+ mTopPadding = Math.min(mTopPadding, mRecyclerView.getHeight() - lastView.getHeight());
|
|
+ if (mIsFirstLayout) {
|
|
+ mIsFirstLayout = false;
|
|
+ scrollToPositionWithOffset(mLastPosition, getPaddingTop() + getPaddingBottom());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (mLastPosition >= state.getItemCount()) {
|
|
+ ResetTopPosition();
|
|
+ scrollToPositionWithOffset(state.getItemCount()-getSpanCount(),
|
|
+ getPaddingTop() + getPaddingBottom());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Parcelable onSaveInstanceState() {
|
|
+ SavedState ss = new SavedState();
|
|
+ ss.superState = super.onSaveInstanceState();
|
|
+ ss.mTopPadding = mTopPadding;
|
|
+ return ss;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void onRestoreInstanceState(Parcelable state) {
|
|
+ if (state instanceof SavedState) {
|
|
+ SavedState ss = (SavedState) state;
|
|
+ mTopPadding = ss.mTopPadding;
|
|
+ state = ss.superState;
|
|
+ }
|
|
+ super.onRestoreInstanceState(state);
|
|
+ }
|
|
+ }
|
|
+
|
|
/**
|
|
* Construct a coordinator for UI that shows a list of tabs.
|
|
*
|
|
@@ -354,6 +482,12 @@ public class TabListCoordinator
|
|
checkAwaitingLayout();
|
|
}
|
|
};
|
|
+ if (actionOnRelatedTabs && ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ gridLayoutManager =
|
|
+ new GridLayoutManagerDockBottom(context, GRID_LAYOUT_SPAN_COUNT_COMPACT);
|
|
+ ((GridLayoutManagerDockBottom)gridLayoutManager)
|
|
+ .setTabListRecyclerView(mRecyclerView);
|
|
+ }
|
|
mRecyclerView.setLayoutManager(gridLayoutManager);
|
|
mMediator.registerOrientationListener(gridLayoutManager);
|
|
mMediator.updateSpanCount(
|
|
@@ -365,8 +499,7 @@ public class TabListCoordinator
|
|
.getDecorView()
|
|
.getWindowVisibleDisplayFrame(frame);
|
|
updateGridCardLayout(frame.width());
|
|
- } else if (mMode == TabListMode.STRIP
|
|
- || mMode == TabListMode.LIST) {
|
|
+ } else if (mMode == TabListMode.STRIP) {
|
|
LinearLayoutManager layoutManager =
|
|
new LinearLayoutManager(
|
|
context,
|
|
@@ -381,6 +514,17 @@ public class TabListCoordinator
|
|
}
|
|
};
|
|
mRecyclerView.setLayoutManager(layoutManager);
|
|
+ } else if (mMode == TabListMode.LIST) {
|
|
+ LinearLayoutManager layout =
|
|
+ new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) {
|
|
+ @Override
|
|
+ public void onLayoutCompleted(RecyclerView.State state) {
|
|
+ super.onLayoutCompleted(state);
|
|
+ checkAwaitingLayout();
|
|
+ }
|
|
+ };
|
|
+ layout.setStackFromEnd(ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled());
|
|
+ mRecyclerView.setLayoutManager(layout);
|
|
}
|
|
mMediator.setRecyclerViewItemAnimationToggle(mRecyclerView::setDisableItemAnimations);
|
|
}
|
|
@@ -396,7 +540,7 @@ public class TabListCoordinator
|
|
|
|
mHasEmptyView = hasEmptyView;
|
|
if (mHasEmptyView) {
|
|
- mTabListEmptyCoordinator = new TabListEmptyCoordinator(parentView, mModel);
|
|
+ mTabListEmptyCoordinator = new TabListEmptyCoordinator(parentView, mModel, mBrowserControlsStateProvider);
|
|
mEmptyStateHeadingResId = emptyHeadingStringResId;
|
|
mEmptyStateSubheadingResId = emptySubheadingStringResId;
|
|
mEmptyStateImageResId = emptyImageResId;
|
|
@@ -685,6 +829,9 @@ public class TabListCoordinator
|
|
void prepareTabSwitcherPaneView() {
|
|
registerLayoutChangeListener();
|
|
mRecyclerView.setupCustomItemAnimator();
|
|
+ if (mRecyclerView.getLayoutManager() instanceof GridLayoutManagerDockBottom) {
|
|
+ ((GridLayoutManagerDockBottom)mRecyclerView.getLayoutManager()).ResetTopPosition();
|
|
+ }
|
|
mMediator.registerOnScrolledListener(mRecyclerView);
|
|
}
|
|
|
|
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListEmptyCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListEmptyCoordinator.java
|
|
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListEmptyCoordinator.java
|
|
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListEmptyCoordinator.java
|
|
@@ -9,10 +9,13 @@ import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.ImageView;
|
|
import android.widget.TextView;
|
|
+import android.widget.FrameLayout;
|
|
|
|
+import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
|
|
import org.chromium.chrome.tab_ui.R;
|
|
import org.chromium.ui.modelutil.ListObservable;
|
|
import org.chromium.ui.modelutil.ListObservable.ListObserver;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
|
|
/**
|
|
* Empty coordinator that is responsible for showing an empty state view in tab switcher when we are
|
|
@@ -30,13 +33,16 @@ class TabListEmptyCoordinator {
|
|
private ListObserver<Void> mListObserver;
|
|
private boolean mIsTabSwitcherShowing;
|
|
private boolean mIsListObserverAttached;
|
|
+ private BrowserControlsStateProvider mBrowserControlsStateProvider;
|
|
|
|
- public TabListEmptyCoordinator(ViewGroup rootView, TabListModel model) {
|
|
+ public TabListEmptyCoordinator(ViewGroup rootView, TabListModel model,
|
|
+ BrowserControlsStateProvider browserControlsStateProvider) {
|
|
mRootView = rootView;
|
|
mContext = rootView.getContext();
|
|
|
|
// Observe TabListModel to determine when to add / remove empty state view.
|
|
mModel = model;
|
|
+ mBrowserControlsStateProvider = browserControlsStateProvider;
|
|
mListObserver =
|
|
new ListObserver<Void>() {
|
|
@Override
|
|
@@ -121,6 +127,15 @@ class TabListEmptyCoordinator {
|
|
public void attachEmptyView() {
|
|
if (mEmptyView != null && mEmptyView.getParent() == null) {
|
|
mRootView.addView(mEmptyView);
|
|
+ FrameLayout.LayoutParams emptyViewParams =
|
|
+ (FrameLayout.LayoutParams) mEmptyView.getLayoutParams();
|
|
+ int toolbarHeightPx = mBrowserControlsStateProvider.getTopControlsHeight();
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ emptyViewParams.bottomMargin = toolbarHeightPx;
|
|
+ } else {
|
|
+ emptyViewParams.topMargin = toolbarHeightPx;
|
|
+ }
|
|
+ mEmptyView.setLayoutParams(emptyViewParams);
|
|
}
|
|
setEmptyViewVisibility(View.GONE);
|
|
}
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/accessibility/settings/AccessibilitySettings.java b/chrome/android/java/src/org/chromium/chrome/browser/accessibility/settings/AccessibilitySettings.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/accessibility/settings/AccessibilitySettings.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/accessibility/settings/AccessibilitySettings.java
|
|
@@ -51,6 +51,11 @@ public class AccessibilitySettings extends ChromeBaseSettingsFragment
|
|
private BooleanPreferenceDelegate mForceTabletUIDelegate;
|
|
static final String PREF_FORCE_TABLET_UI = "force_tablet_ui";
|
|
|
|
+ static final String PREF_MOVE_TOOLBAR_TO_BOTTOM = "move_toolbar_bottom";
|
|
+ static final String PREF_DISABLE_TOOLBAR_SWIPE_UP = "disable_toolbar_swipeup";
|
|
+ private BooleanPreferenceDelegate mMoveTopToolbarToBottomDelegate;
|
|
+ private BooleanPreferenceDelegate mDisableToolbarSwipeUpDelegate;
|
|
+
|
|
private TextScalePreference mTextScalePref;
|
|
private PageZoomPreference mPageZoomDefaultZoomPref;
|
|
private ChromeSwitchPreference mPageZoomIncludeOSAdjustment;
|
|
@@ -86,6 +91,10 @@ public class AccessibilitySettings extends ChromeBaseSettingsFragment
|
|
mFontSizePrefs = FontSizePrefs.getInstance(delegate.getBrowserContextHandle());
|
|
}
|
|
|
|
+ public AccessibilitySettingsDelegate getDelegate() {
|
|
+ return mDelegate;
|
|
+ }
|
|
+
|
|
@Override
|
|
public void onActivityCreated(Bundle savedInstanceState) {
|
|
super.onActivityCreated(savedInstanceState);
|
|
@@ -154,6 +163,18 @@ public class AccessibilitySettings extends ChromeBaseSettingsFragment
|
|
forceTabletUiPref.setChecked(mForceTabletUIDelegate.isEnabled());
|
|
forceTabletUiPref.setOnPreferenceChangeListener(this);
|
|
|
|
+ ChromeSwitchPreference mMoveToolbarToBottomPref =
|
|
+ (ChromeSwitchPreference) findPreference(PREF_MOVE_TOOLBAR_TO_BOTTOM);
|
|
+ mMoveTopToolbarToBottomDelegate = mDelegate.getMoveTopToolbarToBottomDelegate();
|
|
+ mMoveToolbarToBottomPref.setChecked(mMoveTopToolbarToBottomDelegate.isEnabled());
|
|
+ mMoveToolbarToBottomPref.setOnPreferenceChangeListener(this);
|
|
+
|
|
+ ChromeSwitchPreference mDisableToolbarSwipeUpPref =
|
|
+ (ChromeSwitchPreference) findPreference(PREF_DISABLE_TOOLBAR_SWIPE_UP);
|
|
+ mDisableToolbarSwipeUpDelegate = mDelegate.getDisableToolbarSwipeUpDelegate();
|
|
+ mDisableToolbarSwipeUpPref.setChecked(mDisableToolbarSwipeUpDelegate.isEnabled());
|
|
+ mDisableToolbarSwipeUpPref.setOnPreferenceChangeListener(this);
|
|
+
|
|
Preference captions = findPreference(PREF_CAPTIONS);
|
|
captions.setOnPreferenceClickListener(
|
|
preference -> {
|
|
@@ -237,6 +258,11 @@ public class AccessibilitySettings extends ChromeBaseSettingsFragment
|
|
mDelegate.getBrowserContextHandle(), (Integer) newValue);
|
|
} else if (PREF_PAGE_ZOOM_ALWAYS_SHOW.equals(preference.getKey())) {
|
|
PageZoomUtils.setShouldAlwaysShowZoomMenuItem((Boolean) newValue);
|
|
+ } else if (PREF_MOVE_TOOLBAR_TO_BOTTOM.equals(preference.getKey())) {
|
|
+ mMoveTopToolbarToBottomDelegate.setEnabled((Boolean) newValue);
|
|
+ mDelegate.requestRestart(getActivity());
|
|
+ } else if (PREF_DISABLE_TOOLBAR_SWIPE_UP.equals(preference.getKey())) {
|
|
+ mDisableToolbarSwipeUpDelegate.setEnabled((Boolean) newValue);
|
|
} else if (PREF_PAGE_ZOOM_INCLUDE_OS_ADJUSTMENT.equals(preference.getKey())) {
|
|
// TODO(mschillaci): Implement the override behavior for OS level.
|
|
}
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/accessibility/settings/ChromeAccessibilitySettingsDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/accessibility/settings/ChromeAccessibilitySettingsDelegate.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/accessibility/settings/ChromeAccessibilitySettingsDelegate.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/accessibility/settings/ChromeAccessibilitySettingsDelegate.java
|
|
@@ -15,6 +15,13 @@ import org.chromium.chrome.browser.flags.CromiteNativeUtils;
|
|
import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
|
|
import org.chromium.chrome.browser.preferences.ChromeSharedPreferences;
|
|
|
|
+import org.chromium.chrome.R;
|
|
+import android.app.Activity;
|
|
+import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
|
|
+import org.chromium.chrome.browser.ui.messages.snackbar.INeedSnackbarManager;
|
|
+import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
|
|
+import org.chromium.chrome.browser.ApplicationLifetime;
|
|
+
|
|
/** The Chrome implementation of AccessibilitySettingsDelegate. */
|
|
public class ChromeAccessibilitySettingsDelegate implements AccessibilitySettingsDelegate {
|
|
private static class TextSizeContrastAccessibilityDelegate
|
|
@@ -57,6 +64,12 @@ public class ChromeAccessibilitySettingsDelegate implements AccessibilitySetting
|
|
return new ForceTabletUIDelegate();
|
|
}
|
|
|
|
+ private SnackbarManager mSnackbarManager;
|
|
+
|
|
+ public void setSnackbarManager(SnackbarManager snackbarManager) {
|
|
+ mSnackbarManager = snackbarManager;
|
|
+ }
|
|
+
|
|
private final Profile mProfile;
|
|
|
|
/**
|
|
@@ -67,6 +80,62 @@ public class ChromeAccessibilitySettingsDelegate implements AccessibilitySetting
|
|
mProfile = profile;
|
|
}
|
|
|
|
+ private static class MoveTopToolbarToBottomDelegate implements BooleanPreferenceDelegate {
|
|
+ @Override
|
|
+ public boolean isEnabled() {
|
|
+ return ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setEnabled(boolean value) {
|
|
+ CromiteNativeUtils.setFlagEnabled(ChromeFeatureList.MOVE_TOP_TOOLBAR_TO_BOTTOM,
|
|
+ "move-top-toolbar-to-bottom", value);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private static class DisableToolbarSwipeUpDelegate implements BooleanPreferenceDelegate {
|
|
+ @Override
|
|
+ public boolean isEnabled() {
|
|
+ return ChromeFeatureList.sDisableToolbarSwipeUp.isEnabled();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setEnabled(boolean value) {
|
|
+ CromiteNativeUtils.setFlagEnabled(ChromeFeatureList.DISABLE_TOOLBAR_SWIPE_UP,
|
|
+ "disable-toolbar-swipe-up", value);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public BooleanPreferenceDelegate getMoveTopToolbarToBottomDelegate() {
|
|
+ return new MoveTopToolbarToBottomDelegate();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public BooleanPreferenceDelegate getDisableToolbarSwipeUpDelegate() {
|
|
+ return new DisableToolbarSwipeUpDelegate();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void requestRestart(Activity activity) {
|
|
+ Snackbar mSnackbar = Snackbar.make(activity.getString(R.string.ui_relaunch_notice),
|
|
+ new SnackbarManager.SnackbarController() {
|
|
+ @Override
|
|
+ public void onDismissNoAction(Object actionData) { }
|
|
+
|
|
+ @Override
|
|
+ public void onAction(Object actionData) {
|
|
+ ApplicationLifetime.terminate(true);
|
|
+ }
|
|
+ }, Snackbar.TYPE_NOTIFICATION, Snackbar.UMA_UNKNOWN)
|
|
+ .setSingleLine(false)
|
|
+ .setAction(activity.getString(R.string.relaunch),
|
|
+ /*actionData*/null)
|
|
+ .setDuration(/*durationMs*/70000);
|
|
+ if (!mSnackbarManager.isShowing())
|
|
+ mSnackbarManager.showSnackbar(mSnackbar);
|
|
+ }
|
|
+
|
|
@Override
|
|
public BrowserContextHandle getBrowserContextHandle() {
|
|
return mProfile;
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
|
|
@@ -252,6 +252,9 @@ import org.chromium.webapk.lib.client.WebApkNavigationClient;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
+import android.widget.ImageView;
|
|
+import android.view.ViewGroup.LayoutParams;
|
|
+
|
|
/**
|
|
* A {@link AsyncInitializationActivity} that builds and manages a {@link CompositorViewHolder} and
|
|
* associated classes.
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
|
|
@@ -251,6 +251,10 @@ public class CompositorViewHolder extends FrameLayout
|
|
@Override
|
|
public void setCurrentTouchEventOffsets(float top) {
|
|
EventForwarder forwarder = getEventForwarder();
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // no need to adjust the touch offsets, since the content view is never moved
|
|
+ top = 0;
|
|
+ }
|
|
if (forwarder != null) forwarder.setCurrentTouchEventOffsets(0, top);
|
|
}
|
|
|
|
@@ -881,6 +885,9 @@ public class CompositorViewHolder extends FrameLayout
|
|
mApplicationBottomInsetSupplier != null
|
|
? mApplicationBottomInsetSupplier.get().webContentsHeightInset
|
|
: 0;
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ keyboardInset = 0;
|
|
+ }
|
|
|
|
int viewportInsets = controlsInsets + keyboardInset;
|
|
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
|
|
@@ -38,6 +38,7 @@ import org.chromium.chrome.browser.util.ChromeAccessibilityUtil;
|
|
import org.chromium.components.browser_ui.widget.gesture.SwipeGestureListener.ScrollDirection;
|
|
import org.chromium.components.browser_ui.widget.gesture.SwipeGestureListener.SwipeHandler;
|
|
import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
|
|
import java.util.List;
|
|
|
|
@@ -152,7 +153,10 @@ public class LayoutManagerChrome extends LayoutManagerImpl
|
|
|
|
@Override
|
|
public SwipeHandler createToolbarSwipeHandler(boolean supportSwipeDown) {
|
|
- return new ToolbarSwipeHandler(supportSwipeDown);
|
|
+ boolean move_top_toolbar =
|
|
+ ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled();
|
|
+ return new ToolbarSwipeHandler(supportSwipeDown && !move_top_toolbar,
|
|
+ supportSwipeDown && move_top_toolbar);
|
|
}
|
|
|
|
@Override
|
|
@@ -340,9 +344,11 @@ public class LayoutManagerChrome extends LayoutManagerImpl
|
|
private static final float SWIPE_RANGE_DEG = 25;
|
|
|
|
private final boolean mSupportSwipeDown;
|
|
+ private final boolean mSupportSwipeUp;
|
|
|
|
- public ToolbarSwipeHandler(boolean supportSwipeDown) {
|
|
+ public ToolbarSwipeHandler(boolean supportSwipeDown, boolean supportSwipeUp) {
|
|
mSupportSwipeDown = supportSwipeDown;
|
|
+ mSupportSwipeUp = supportSwipeUp;
|
|
}
|
|
|
|
@Override
|
|
@@ -373,6 +379,10 @@ public class LayoutManagerChrome extends LayoutManagerImpl
|
|
if (mSupportSwipeDown && mScrollDirection == ScrollDirection.DOWN) {
|
|
RecordUserAction.record("MobileToolbarSwipeOpenStackView");
|
|
showLayout(LayoutType.TAB_SWITCHER, true);
|
|
+ } else if (mSupportSwipeUp
|
|
+ && mScrollDirection == ScrollDirection.UP
|
|
+ && !ChromeFeatureList.sDisableToolbarSwipeUp.isEnabled()) {
|
|
+ showLayout(LayoutType.TAB_SWITCHER, true);
|
|
} else if (mScrollDirection == ScrollDirection.LEFT
|
|
|| mScrollDirection == ScrollDirection.RIGHT) {
|
|
startShowing(mToolbarSwipeLayout, true);
|
|
@@ -424,6 +434,8 @@ public class LayoutManagerChrome extends LayoutManagerImpl
|
|
direction = ScrollDirection.RIGHT;
|
|
} else if (swipeAngle < 270 + SWIPE_RANGE_DEG && swipeAngle > 270 - SWIPE_RANGE_DEG) {
|
|
direction = ScrollDirection.DOWN;
|
|
+ } else if (swipeAngle < 90 + SWIPE_RANGE_DEG && swipeAngle > 90 - SWIPE_RANGE_DEG) {
|
|
+ direction = ScrollDirection.UP;
|
|
}
|
|
|
|
return direction;
|
|
@@ -440,7 +452,8 @@ public class LayoutManagerChrome extends LayoutManagerImpl
|
|
|
|
return direction == ScrollDirection.DOWN
|
|
|| direction == ScrollDirection.LEFT
|
|
- || direction == ScrollDirection.RIGHT;
|
|
+ || direction == ScrollDirection.RIGHT
|
|
+ || direction == ScrollDirection.UP;
|
|
}
|
|
}
|
|
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java
|
|
@@ -37,6 +37,7 @@ import org.chromium.chrome.browser.ui.desktop_windowing.DesktopWindowStateProvid
|
|
import org.chromium.ui.base.WindowAndroid;
|
|
import org.chromium.ui.dragdrop.DragAndDropDelegate;
|
|
import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
|
|
+import org.chromium.chrome.browser.fullscreen.BrowserControlsManager;
|
|
|
|
/**
|
|
* {@link LayoutManagerChromeTablet} is the specialization of {@link LayoutManagerChrome} for the
|
|
@@ -125,7 +126,8 @@ public class LayoutManagerChromeTablet extends LayoutManagerChrome {
|
|
windowAndroid,
|
|
toolbarManager,
|
|
desktopWindowStateProvider,
|
|
- actionConfirmationManager);
|
|
+ actionConfirmationManager,
|
|
+ /*browserControlsManagerSupplier*/ () -> getBrowserControlsManager());
|
|
addSceneOverlay(mTabStripLayoutHelperManager);
|
|
addObserver(mTabStripLayoutHelperManager.getTabSwitcherObserver());
|
|
mDesktopWindowStateProvider = desktopWindowStateProvider;
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/ToolbarSwipeLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/ToolbarSwipeLayout.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/ToolbarSwipeLayout.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/ToolbarSwipeLayout.java
|
|
@@ -36,6 +36,8 @@ import org.chromium.ui.base.LocalizationUtils;
|
|
import org.chromium.ui.interpolators.Interpolators;
|
|
import org.chromium.ui.resources.ResourceManager;
|
|
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
+
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
@@ -441,7 +443,11 @@ public class ToolbarSwipeLayout extends Layout {
|
|
mLeftToolbarOverlay.setXOffset(leftX * dpToPx);
|
|
}
|
|
mLeftTab.setX(leftX);
|
|
- mLeftTab.setY(mBrowserControlsStateProvider.getContentOffset() / dpToPx);
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ mLeftTab.setY(0);
|
|
+ } else {
|
|
+ mLeftTab.setY(mBrowserControlsStateProvider.getContentOffset() / dpToPx);
|
|
+ }
|
|
needUpdate = updateSnap(dt, mLeftTab) || needUpdate;
|
|
} else if (mLeftToolbarOverlay != null) {
|
|
mLeftToolbarOverlay.setManualVisibility(false);
|
|
@@ -454,7 +460,11 @@ public class ToolbarSwipeLayout extends Layout {
|
|
mRightToolbarOverlay.setXOffset(rightX * dpToPx);
|
|
}
|
|
mRightTab.setX(rightX);
|
|
- mRightTab.setY(mBrowserControlsStateProvider.getContentOffset() / dpToPx);
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ mRightTab.setY(0);
|
|
+ } else {
|
|
+ mRightTab.setY(mBrowserControlsStateProvider.getContentOffset() / dpToPx);
|
|
+ }
|
|
needUpdate = updateSnap(dt, mRightTab) || needUpdate;
|
|
} else if (mRightToolbarOverlay != null) {
|
|
mRightToolbarOverlay.setManualVisibility(false);
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
|
|
@@ -789,7 +789,7 @@ public class StripLayoutHelper implements StripLayoutTabDelegate, StripLayoutGro
|
|
boolean isRtl = LocalizationUtils.isLayoutRtl();
|
|
boolean useUnadjustedScrollOffset = isRtl != isLeft;
|
|
float offset =
|
|
- -(useUnadjustedScrollOffset ? mScrollOffset : (mMinScrollOffset - mScrollOffset));
|
|
+ -Math.abs(useUnadjustedScrollOffset ? mScrollOffset : (mMinScrollOffset - mScrollOffset));
|
|
|
|
if (offset <= 0.f) {
|
|
return 0.f;
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
|
|
@@ -34,6 +34,7 @@ import org.chromium.base.Callback;
|
|
import org.chromium.base.metrics.RecordUserAction;
|
|
import org.chromium.base.supplier.ObservableSupplier;
|
|
import org.chromium.base.supplier.ObservableSupplierImpl;
|
|
+import org.chromium.base.supplier.Supplier;
|
|
import org.chromium.chrome.R;
|
|
import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
|
|
import org.chromium.chrome.browser.compositor.LayerTitleCache;
|
|
@@ -97,6 +98,8 @@ import org.chromium.ui.interpolators.Interpolators;
|
|
import org.chromium.ui.resources.ResourceManager;
|
|
import org.chromium.ui.util.ColorUtils;
|
|
import org.chromium.url.GURL;
|
|
+import org.chromium.chrome.browser.fullscreen.BrowserControlsManager;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
@@ -265,12 +268,16 @@ public class StripLayoutHelperManager
|
|
// Drag-Drop
|
|
@Nullable private TabDragSource mTabDragSource;
|
|
|
|
+ private final Supplier<BrowserControlsManager> mBrowserControlsManagerSupplier;
|
|
+ private final float mDpToPx;
|
|
+
|
|
private class TabStripEventHandler implements MotionEventHandler {
|
|
@Override
|
|
public void onDown(float x, float y, boolean fromMouse, int buttons) {
|
|
if (DragDropGlobalState.hasValue()) {
|
|
return;
|
|
}
|
|
+ y -= mStripFilterArea.top;
|
|
if (mModelSelectorButton.onDown(x, y, fromMouse, buttons)) {
|
|
return;
|
|
}
|
|
@@ -293,6 +300,7 @@ public class StripLayoutHelperManager
|
|
if (DragDropGlobalState.hasValue()) {
|
|
return;
|
|
}
|
|
+ y -= mStripFilterArea.top;
|
|
mModelSelectorButton.drag(x, y);
|
|
getActiveStripLayoutHelper().drag(time(), x, y, dx);
|
|
}
|
|
@@ -302,6 +310,7 @@ public class StripLayoutHelperManager
|
|
if (DragDropGlobalState.hasValue()) {
|
|
return;
|
|
}
|
|
+ y -= mStripFilterArea.top;
|
|
long time = time();
|
|
if (mModelSelectorButton.click(x, y, fromMouse, buttons)) {
|
|
mModelSelectorButton.handleClick(time);
|
|
@@ -315,6 +324,7 @@ public class StripLayoutHelperManager
|
|
if (DragDropGlobalState.hasValue()) {
|
|
return;
|
|
}
|
|
+ y -= mStripFilterArea.top;
|
|
getActiveStripLayoutHelper().fling(time(), x, y, velocityX, velocityY);
|
|
}
|
|
|
|
@@ -323,6 +333,7 @@ public class StripLayoutHelperManager
|
|
if (DragDropGlobalState.hasValue()) {
|
|
return;
|
|
}
|
|
+ y -= mStripFilterArea.top;
|
|
getActiveStripLayoutHelper().onLongPress(time(), x, y);
|
|
}
|
|
|
|
@@ -429,7 +440,8 @@ public class StripLayoutHelperManager
|
|
// implement an interface to manage strip transition states.
|
|
@NonNull ToolbarManager toolbarManager,
|
|
@Nullable DesktopWindowStateProvider desktopWindowStateProvider,
|
|
- ActionConfirmationManager actionConfirmationManager) {
|
|
+ ActionConfirmationManager actionConfirmationManager,
|
|
+ Supplier<BrowserControlsManager> browserControlsManagerSupplier) {
|
|
Resources res = context.getResources();
|
|
mUpdateHost = updateHost;
|
|
mLayerTitleCacheSupplier = layerTitleCacheSupplier;
|
|
@@ -591,6 +603,8 @@ public class StripLayoutHelperManager
|
|
!mTabStripObscured
|
|
&& getStripVisibilityState()
|
|
== StripVisibilityState.VISIBLE);
|
|
+ mBrowserControlsManagerSupplier = browserControlsManagerSupplier;
|
|
+ mDpToPx = context.getResources().getDisplayMetrics().density;
|
|
|
|
tabHoverCardViewStub.setOnInflateListener(
|
|
(viewStub, view) -> {
|
|
@@ -753,6 +767,10 @@ public class StripLayoutHelperManager
|
|
// layer should be a negative value.
|
|
yOffset -= getHeight();
|
|
}
|
|
+ int topControlsHeight = 0;
|
|
+ if (mBrowserControlsManagerSupplier.get() != null) {
|
|
+ topControlsHeight = mBrowserControlsManagerSupplier.get().getTopControlsHeight();
|
|
+ }
|
|
mTabStripTreeProvider.pushAndUpdateStrip(
|
|
this,
|
|
mLayerTitleCacheSupplier.get(),
|
|
@@ -766,7 +784,9 @@ public class StripLayoutHelperManager
|
|
mStripTransitionScrimOpacity,
|
|
mLeftPadding,
|
|
mRightPadding,
|
|
- mTopPadding);
|
|
+ mTopPadding,
|
|
+ viewport.height(),
|
|
+ topControlsHeight);
|
|
return mTabStripTreeProvider;
|
|
}
|
|
|
|
@@ -822,11 +842,21 @@ public class StripLayoutHelperManager
|
|
mLeftPadding,
|
|
mRightPadding);
|
|
|
|
+ float top = mTopPadding;
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled() &&
|
|
+ mBrowserControlsManagerSupplier.get() != null) {
|
|
+ // move the rectangle to grab the touch events as the tab list (in tablet mode)
|
|
+ // is down and is following the toolbar offset as it moves.
|
|
+ // values are in pixels.
|
|
+ top = height - ((mBrowserControlsManagerSupplier.get().getTopControlsHeight()
|
|
+ - mBrowserControlsManagerSupplier.get().getTopControlOffset()) / mDpToPx);
|
|
+ visibleViewportOffsetY = mHeight;
|
|
+ }
|
|
mStripFilterArea.set(
|
|
mLeftPadding,
|
|
- mTopPadding,
|
|
+ top,
|
|
mWidth - mRightPadding,
|
|
- Math.min(getHeight(), visibleViewportOffsetY));
|
|
+ top + Math.min(getHeight(), visibleViewportOffsetY));
|
|
// Avoid handling motion events when invisible strip state persists after a size change.
|
|
if (getStripVisibilityState() == StripVisibilityState.VISIBLE) {
|
|
mEventFilter.setEventArea(mStripFilterArea);
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/StaticTabSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/StaticTabSceneLayer.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/StaticTabSceneLayer.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/StaticTabSceneLayer.java
|
|
@@ -17,6 +17,8 @@ import org.chromium.chrome.browser.tab_ui.TabContentManager;
|
|
import org.chromium.ui.modelutil.PropertyKey;
|
|
import org.chromium.ui.modelutil.PropertyModel;
|
|
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
+
|
|
/** A SceneLayer to render a static tab. */
|
|
@JNINamespace("android")
|
|
public class StaticTabSceneLayer extends SceneLayer {
|
|
@@ -49,7 +51,10 @@ public class StaticTabSceneLayer extends SceneLayer {
|
|
float y =
|
|
model.get(LayoutTab.CONTENT_OFFSET)
|
|
+ model.get(LayoutTab.RENDER_Y) * LayoutTab.sDpToPx;
|
|
-
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // the page content window never moves, it is fixed at the top
|
|
+ y = 0;
|
|
+ }
|
|
// Check isActiveLayout to prevent pushing a TAB_ID for a static layer that may already be
|
|
// invalidated by the next layout.
|
|
StaticTabSceneLayerJni.get()
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java
|
|
@@ -23,6 +23,8 @@ import org.chromium.components.browser_ui.styles.SemanticColorUtils;
|
|
import org.chromium.ui.resources.ResourceManager;
|
|
import org.chromium.ui.util.ColorUtils;
|
|
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
+
|
|
/**
|
|
* A SceneLayer to render a tab stack.
|
|
* TODO(changwan): change layouts to share one instance of this.
|
|
@@ -89,6 +91,12 @@ public class TabListSceneLayer extends SceneLayer {
|
|
|
|
TabListSceneLayerJni.get().beginBuildingFrame(mNativePtr, TabListSceneLayer.this);
|
|
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // the tabs list content window is fixed at the top, where the top toolbar used to be
|
|
+ viewport.top = 0;
|
|
+ backgroundTopOffset = 0;
|
|
+ }
|
|
+
|
|
// TODO(crbug.com/40126259): Use Supplier to get viewport and forward it to native, then
|
|
// updateLayer can become obsolete.
|
|
TabListSceneLayerJni.get()
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java
|
|
@@ -18,6 +18,9 @@ import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutTab;
|
|
import org.chromium.chrome.browser.layouts.scene_layer.SceneLayer;
|
|
import org.chromium.chrome.browser.layouts.scene_layer.SceneOverlayLayer;
|
|
import org.chromium.ui.resources.ResourceManager;
|
|
+import org.chromium.ui.base.DeviceFormFactor;
|
|
+import org.chromium.base.ContextUtils;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
|
|
/**
|
|
* The Java component of what is basically a CC Layer that manages drawing the Tab Strip (which is
|
|
@@ -88,9 +91,21 @@ public class TabStripSceneLayer extends SceneOverlayLayer {
|
|
float scrimOpacity,
|
|
float leftPaddingDp,
|
|
float rightPaddingDp,
|
|
- float topPaddingDp) {
|
|
+ float topPaddingDp,
|
|
+ float viewportHeight,
|
|
+ int topControlsHeight) {
|
|
if (mNativePtr == 0) return;
|
|
- final boolean visible = yOffset > -layoutHelper.getHeight();
|
|
+ boolean visible = yOffset > -layoutHelper.getHeight();
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ if (DeviceFormFactor.isNonMultiDisplayContextOnTablet(ContextUtils.getApplicationContext())) {
|
|
+ // the list of open tabs is moved down, above the top
|
|
+ // toolbar which is also below.
|
|
+ // values are in pixel.
|
|
+ yOffset = (((int)viewportHeight - topControlsHeight) / mDpToPx) - yOffset;
|
|
+ // and it disappears along with the moving toolbar with a higher range
|
|
+ visible = yOffset > (-layoutHelper.getHeight() - topControlsHeight);
|
|
+ }
|
|
+ }
|
|
// This will hide the tab strips if necessary.
|
|
TabStripSceneLayerJni.get()
|
|
.beginBuildingFrame(mNativePtr, TabStripSceneLayer.this, visible);
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindToolbarTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindToolbarTablet.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindToolbarTablet.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindToolbarTablet.java
|
|
@@ -14,6 +14,8 @@ import android.util.AttributeSet;
|
|
import android.view.View;
|
|
import android.widget.FrameLayout;
|
|
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
+
|
|
import org.chromium.chrome.R;
|
|
import org.chromium.components.browser_ui.widget.animation.CancelAwareAnimatorListener;
|
|
import org.chromium.ui.interpolators.Interpolators;
|
|
@@ -170,9 +172,11 @@ public class FindToolbarTablet extends FindToolbar {
|
|
|
|
if (show && getVisibility() != View.VISIBLE && mCurrentAnimation != mAnimationEnter) {
|
|
View anchorView = getRootView().findViewById(R.id.toolbar);
|
|
- FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
|
|
- lp.topMargin = anchorView.getBottom() - mYInsetPx;
|
|
- setLayoutParams(lp);
|
|
+ if (!ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
|
|
+ lp.topMargin = anchorView.getBottom() - mYInsetPx;
|
|
+ setLayoutParams(lp);
|
|
+ }
|
|
nextAnimator = mAnimationEnter;
|
|
} else if (!show && getVisibility() != View.GONE && mCurrentAnimation != mAnimationLeave) {
|
|
nextAnimator = mAnimationLeave;
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/BrowserControlsManager.java b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/BrowserControlsManager.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/BrowserControlsManager.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/BrowserControlsManager.java
|
|
@@ -48,6 +48,8 @@ import org.chromium.ui.util.TokenHolder;
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
+
|
|
/** A class that manages browser control visibility and positioning. */
|
|
public class BrowserControlsManager implements ActivityStateListener, BrowserControlsSizer {
|
|
// The amount of time to delay the control show request after returning to a once visible
|
|
@@ -464,6 +466,14 @@ public class BrowserControlsManager implements ActivityStateListener, BrowserCon
|
|
return mTopControlContainerHeight;
|
|
}
|
|
|
|
+ @Override
|
|
+ public int getTopControlsHeightRealOffset() {
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled())
|
|
+ return 0;
|
|
+ else
|
|
+ return mTopControlContainerHeight;
|
|
+ }
|
|
+
|
|
@Override
|
|
public int getTopControlsMinHeight() {
|
|
return mTopControlsMinHeight;
|
|
@@ -530,6 +540,8 @@ public class BrowserControlsManager implements ActivityStateListener, BrowserCon
|
|
|
|
@Override
|
|
public float getTopVisibleContentOffset() {
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled())
|
|
+ return 0;
|
|
return getTopControlsHeight() + getTopControlOffset();
|
|
}
|
|
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/messages/MessageContainerCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/messages/MessageContainerCoordinator.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/messages/MessageContainerCoordinator.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/messages/MessageContainerCoordinator.java
|
|
@@ -18,6 +18,9 @@ import org.chromium.chrome.browser.fullscreen.BrowserControlsManager;
|
|
import org.chromium.components.messages.MessageContainer;
|
|
import org.chromium.ui.base.ViewUtils;
|
|
|
|
+import android.view.Gravity;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
+
|
|
/**
|
|
* Coordinator of {@link MessageContainer}, which can adjust margins of the message container
|
|
* and control the visibility of browser control when message is being shown.
|
|
@@ -59,7 +62,12 @@ public class MessageContainerCoordinator implements BrowserControlsStateProvider
|
|
}
|
|
CoordinatorLayout.LayoutParams params =
|
|
(CoordinatorLayout.LayoutParams) mContainer.getLayoutParams();
|
|
- params.topMargin = getContainerTopOffset();
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ params.gravity = Gravity.START | Gravity.BOTTOM;
|
|
+ params.bottomMargin = getContainerTopOffset();
|
|
+ } else {
|
|
+ params.topMargin = getContainerTopOffset();
|
|
+ }
|
|
mContainer.setLayoutParams(params);
|
|
}
|
|
|
|
@@ -133,6 +141,12 @@ public class MessageContainerCoordinator implements BrowserControlsStateProvider
|
|
|
|
/** @return Offset of the message container from the top of the screen. */
|
|
private int getContainerTopOffset() {
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ return mControlsManager.getContentOffset()
|
|
+ + (mControlsManager.getBottomControlsHeight() - mControlsManager.getBottomControlOffset())
|
|
+ + mContainer.getMessageShadowTopMargin();
|
|
+ }
|
|
+
|
|
if (mControlsManager.getContentOffset() == 0) return 0;
|
|
final Resources res = mContainer.getResources();
|
|
return mControlsManager.getContentOffset()
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/ChromeTabModalPresenter.java b/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/ChromeTabModalPresenter.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/ChromeTabModalPresenter.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/ChromeTabModalPresenter.java
|
|
@@ -287,7 +287,7 @@ public class ChromeTabModalPresenter extends TabModalPresenter
|
|
Resources resources, BrowserControlsStateProvider provider) {
|
|
int scrimVerticalMargin =
|
|
resources.getDimensionPixelSize(R.dimen.tab_modal_scrim_vertical_margin);
|
|
- return provider.getTopControlsHeight() - scrimVerticalMargin;
|
|
+ return provider.getTopControlsHeightRealOffset() - scrimVerticalMargin;
|
|
}
|
|
|
|
/**
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
|
|
@@ -110,6 +110,7 @@ import org.chromium.ui.base.DeviceFormFactor;
|
|
import org.chromium.ui.base.WindowAndroid;
|
|
import org.chromium.ui.modaldialog.ModalDialogManager;
|
|
import org.chromium.url.GURL;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
|
|
import java.util.List;
|
|
|
|
@@ -669,11 +670,16 @@ public class NewTabPage
|
|
final int topControlsDistanceToRest =
|
|
mBrowserControlsStateProvider.getContentOffset()
|
|
- mBrowserControlsStateProvider.getTopControlsHeight();
|
|
- final int topMargin = getToolbarExtraYOffset() + topControlsDistanceToRest;
|
|
+ int topMargin = getToolbarExtraYOffset() + topControlsDistanceToRest;
|
|
|
|
- final int bottomMargin =
|
|
+ int bottomMargin =
|
|
mBrowserControlsStateProvider.getBottomControlsHeight()
|
|
- mBrowserControlsStateProvider.getBottomControlOffset();
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // move the margin of the new tab page up if the top toolbar is at the bottom
|
|
+ bottomMargin += mBrowserControlsStateProvider.getTopControlsHeight();
|
|
+ topMargin = -mBrowserControlsStateProvider.getTopControlsHeight();
|
|
+ }
|
|
|
|
if (topMargin != layoutParams.topMargin || bottomMargin != layoutParams.bottomMargin) {
|
|
layoutParams.topMargin = topMargin;
|
|
@@ -689,9 +695,7 @@ public class NewTabPage
|
|
* strip.
|
|
*/
|
|
private int getToolbarExtraYOffset() {
|
|
- return mBrowserControlsStateProvider.getTopControlsHeight()
|
|
- - mToolbarHeight
|
|
- - mTabStripHeightSupplier.get();
|
|
+ return 0;
|
|
}
|
|
|
|
/**
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
|
|
@@ -16,6 +16,9 @@ import android.util.AttributeSet;
|
|
import android.view.DragEvent;
|
|
import android.view.LayoutInflater;
|
|
import android.view.ViewStub;
|
|
+import android.view.ViewGroup.LayoutParams;
|
|
+import android.widget.FrameLayout;
|
|
+import android.view.Gravity;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.LinearLayout;
|
|
@@ -178,10 +181,17 @@ public class NewTabPageLayout extends LinearLayout {
|
|
mMiddleSpacer = findViewById(R.id.ntp_middle_spacer);
|
|
mFakeSearchBoxLayout = findViewById(R.id.search_box);
|
|
insertSiteSectionView();
|
|
-
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ FrameLayout.LayoutParams params =
|
|
+ new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
|
|
+ params.gravity = Gravity.BOTTOM;
|
|
+ setLayoutParams(params);
|
|
+ }
|
|
Log.i(TAG, "NewTabPageLayout.onFinishInflate after insertSiteSectionView");
|
|
}
|
|
|
|
+ /**
|
|
+
|
|
/**
|
|
* Initializes the NewTabPageLayout. This must be called immediately after inflation, before
|
|
* this object is used in any other way.
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsPage.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsPage.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsPage.java
|
|
@@ -25,6 +25,7 @@ import org.chromium.components.browser_ui.styles.SemanticColorUtils;
|
|
import org.chromium.components.embedder_support.util.UrlConstants;
|
|
import org.chromium.ui.base.DeviceFormFactor;
|
|
import org.chromium.ui.base.ViewUtils;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
|
|
/**
|
|
* The native recent tabs page. Lists recently closed tabs, open windows and tabs from the user's
|
|
@@ -98,7 +99,8 @@ public class RecentTabsPage
|
|
|
|
mView.addOnAttachStateChangeListener(this);
|
|
|
|
- if (!DeviceFormFactor.isNonMultiDisplayContextOnTablet(mActivity)) {
|
|
+ if (!DeviceFormFactor.isNonMultiDisplayContextOnTablet(mActivity) ||
|
|
+ ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
mBrowserControlsStateProvider = browserControlsStateProvider;
|
|
mBrowserControlsStateProvider.addObserver(this);
|
|
onBottomControlsHeightChanged(
|
|
@@ -110,14 +112,22 @@ public class RecentTabsPage
|
|
|
|
mTabStripHeightSupplier = tabStripHeightSupplier;
|
|
mView.setPadding(0, mTabStripHeightSupplier.get(), 0, 0);
|
|
- mTabStripHeightChangeCallback =
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ mView.setPadding(
|
|
+ mView.getPaddingLeft(),
|
|
+ 0,
|
|
+ mView.getPaddingRight(),
|
|
+ mView.getPaddingBottom());
|
|
+ } else {
|
|
+ mTabStripHeightChangeCallback =
|
|
newHeight ->
|
|
mView.setPadding(
|
|
mView.getPaddingLeft(),
|
|
newHeight,
|
|
mView.getPaddingRight(),
|
|
mView.getPaddingBottom());
|
|
- mTabStripHeightSupplier.addObserver(mTabStripHeightChangeCallback);
|
|
+ mTabStripHeightSupplier.addObserver(mTabStripHeightChangeCallback);
|
|
+ }
|
|
|
|
onUpdated();
|
|
}
|
|
@@ -298,7 +308,7 @@ public class RecentTabsPage
|
|
|
|
private void updateMargins() {
|
|
final View recentTabsRoot = mView.findViewById(R.id.recent_tabs_root);
|
|
- final int topControlsHeight = mBrowserControlsStateProvider.getTopControlsHeight();
|
|
+ final int topControlsHeight = mBrowserControlsStateProvider.getTopControlsHeightRealOffset();
|
|
final int contentOffset = mBrowserControlsStateProvider.getContentOffset();
|
|
ViewGroup.MarginLayoutParams layoutParams =
|
|
(ViewGroup.MarginLayoutParams) recentTabsRoot.getLayoutParams();
|
|
@@ -314,9 +324,17 @@ public class RecentTabsPage
|
|
|
|
// If the content offset is different from the margin, we use translationY to position the
|
|
// view in line with the content offset.
|
|
- recentTabsRoot.setTranslationY(contentOffset - topMargin);
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ topMargin = 0;
|
|
+ recentTabsRoot.setTranslationY(0);
|
|
+ } else {
|
|
+ recentTabsRoot.setTranslationY(contentOffset - topMargin);
|
|
+ }
|
|
|
|
- final int bottomMargin = mBrowserControlsStateProvider.getBottomControlsHeight();
|
|
+ int bottomMargin = mBrowserControlsStateProvider.getBottomControlsHeight();
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ bottomMargin += mBrowserControlsStateProvider.getTopControlsHeight();
|
|
+ }
|
|
if (topMargin != layoutParams.topMargin || bottomMargin != layoutParams.bottomMargin) {
|
|
layoutParams.topMargin = topMargin;
|
|
layoutParams.bottomMargin = bottomMargin;
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java
|
|
@@ -85,6 +85,11 @@ import org.chromium.url.GURL;
|
|
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
+
|
|
+import android.view.Gravity;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
|
+
|
|
import java.lang.ref.WeakReference;
|
|
|
|
/** Queries the user's default search engine and shows autocomplete suggestions. */
|
|
@@ -288,6 +293,12 @@ public class SearchActivity extends AsyncInitializationActivity
|
|
// Build the search box.
|
|
mSearchBox = contentView.findViewById(R.id.search_location_bar);
|
|
View anchorView = contentView.findViewById(R.id.toolbar);
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams)
|
|
+ anchorView.getLayoutParams();
|
|
+ layoutParams.gravity = Gravity.START | Gravity.BOTTOM;
|
|
+ anchorView.setLayoutParams(layoutParams);
|
|
+ }
|
|
|
|
// Update the status bar's color based on the toolbar color.
|
|
Drawable anchorViewBackground = anchorView.getBackground();
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
|
|
@@ -408,6 +408,11 @@ public class SettingsActivity extends ChromeBaseAppCompatActivity
|
|
if (fragment instanceof INeedSnackbarManager) {
|
|
((INeedSnackbarManager)fragment).setSnackbarManager(mSnackbarManager);
|
|
}
|
|
+ if (fragment instanceof AccessibilitySettings) {
|
|
+ ((ChromeAccessibilitySettingsDelegate)
|
|
+ ((AccessibilitySettings) fragment)
|
|
+ .getDelegate()).setSnackbarManager(mSnackbarManager);
|
|
+ }
|
|
if (fragment instanceof AccountManagementFragment) {
|
|
((AccountManagementFragment) fragment).setSnackbarManager(mSnackbarManager);
|
|
}
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorCoordinator.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorCoordinator.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorCoordinator.java
|
|
@@ -24,6 +24,10 @@ import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
|
|
import org.chromium.ui.resources.ResourceManager;
|
|
import org.chromium.ui.resources.dynamics.ViewResourceAdapter;
|
|
|
|
+import android.view.Gravity;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
|
+
|
|
/**
|
|
* The coordinator for a status indicator that is positioned below the status bar and is persistent.
|
|
* Typically used to relay status, e.g. indicate user is offline.
|
|
@@ -189,6 +193,11 @@ public class StatusIndicatorCoordinator {
|
|
private void initialize() {
|
|
final ViewStub stub = mActivity.findViewById(R.id.status_indicator_stub);
|
|
final ViewResourceFrameLayout root = (ViewResourceFrameLayout) stub.inflate();
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // status messages (such as the offline indicator) are docked at the bottom
|
|
+ CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams)root.getLayoutParams();
|
|
+ layoutParams.gravity = Gravity.START | Gravity.BOTTOM;
|
|
+ }
|
|
mResourceId = root.getId();
|
|
mSceneLayer.setResourceId(mResourceId);
|
|
mResourceAdapter = root.getResourceAdapter();
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorSceneLayer.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorSceneLayer.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorSceneLayer.java
|
|
@@ -16,6 +16,7 @@ import org.chromium.chrome.browser.layouts.components.VirtualView;
|
|
import org.chromium.chrome.browser.layouts.scene_layer.SceneLayer;
|
|
import org.chromium.chrome.browser.layouts.scene_layer.SceneOverlayLayer;
|
|
import org.chromium.ui.resources.ResourceManager;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
|
|
import java.util.List;
|
|
|
|
@@ -78,7 +79,10 @@ class StatusIndicatorSceneLayer extends SceneOverlayLayer implements SceneOverla
|
|
@Override
|
|
public SceneOverlayLayer getUpdatedSceneOverlayTree(
|
|
RectF viewport, RectF visibleViewport, ResourceManager resourceManager, float yOffset) {
|
|
- final int offset = mBrowserControlsStateProvider.getTopControlsMinHeightOffset();
|
|
+ int offset = mBrowserControlsStateProvider.getTopControlsMinHeightOffset();
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ offset = (int)viewport.bottom - offset;
|
|
+ }
|
|
StatusIndicatorSceneLayerJni.get()
|
|
.updateStatusIndicatorLayer(
|
|
mNativePtr,
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
|
|
@@ -190,6 +190,9 @@ import org.chromium.url.GURL;
|
|
|
|
import java.util.List;
|
|
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
+import android.view.Gravity;
|
|
+
|
|
/**
|
|
* Contains logic for managing the toolbar visual component. This class manages the interactions
|
|
* with the rest of the application to ensure the toolbar is always visually up to date.
|
|
@@ -629,6 +632,17 @@ public class ToolbarManager
|
|
}, AlwaysIncognitoLinkInterceptor.isAlwaysIncognito());
|
|
mControlContainer = controlContainer;
|
|
mToolbarHairline = mControlContainer.findViewById(R.id.toolbar_hairline);
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ ViewGroup.MarginLayoutParams layoutParamsCC =
|
|
+ ((ViewGroup.MarginLayoutParams) mControlContainer.getLayoutParams());
|
|
+ layoutParamsCC.bottomMargin = mToolbarHairline.getHeight();
|
|
+ mControlContainer.setLayoutParams(layoutParamsCC);
|
|
+
|
|
+ ViewGroup.MarginLayoutParams layoutParamsHR =
|
|
+ ((ViewGroup.MarginLayoutParams) mToolbarHairline.getLayoutParams());
|
|
+ layoutParamsHR.topMargin = 0;
|
|
+ mToolbarHairline.setLayoutParams(layoutParamsHR);
|
|
+ }
|
|
|
|
mBookmarkModelSupplier = bookmarkModelSupplier;
|
|
mBookmarkModelSupplier.addObserver(mBookmarkModelSupplierObserver);
|
|
@@ -1112,6 +1126,7 @@ public class ToolbarManager
|
|
// the height won't be measured by the background image.
|
|
if (mControlContainer.getBackground() == null) {
|
|
setControlContainerTopMargin(getToolbarExtraYOffset());
|
|
+ MoveBottomBarOverTopBar();
|
|
} else if (mLayoutChangeListener == null) {
|
|
mLayoutChangeListener =
|
|
(view,
|
|
@@ -1125,6 +1140,7 @@ public class ToolbarManager
|
|
oldBottom) -> {
|
|
if (mControlContainer.getBackground() == null) {
|
|
setControlContainerTopMargin(getToolbarExtraYOffset());
|
|
+ MoveBottomBarOverTopBar();
|
|
mControlContainer.removeOnLayoutChangeListener(
|
|
mLayoutChangeListener);
|
|
mLayoutChangeListener = null;
|
|
@@ -1513,16 +1529,28 @@ public class ToolbarManager
|
|
return ((LocationBarCoordinator) mLocationBar).getUrlBarTextWithoutAutocomplete();
|
|
}
|
|
|
|
+ View mBottomRoot;
|
|
+
|
|
+ private void MoveBottomBarOverTopBar() {
|
|
+ if (mBottomRoot != null &&
|
|
+ ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // move up the container view of the ui
|
|
+ // below there is the toolbar
|
|
+ mBottomRoot.setTranslationY(-mBrowserControlsVisibilityManager.getTopControlsHeight());
|
|
+ }
|
|
+ }
|
|
+
|
|
/** Enable the bottom controls. */
|
|
public void enableBottomControls() {
|
|
- View root = ((ViewStub) mActivity.findViewById(R.id.bottom_controls_stub)).inflate();
|
|
+ mBottomRoot = ((ViewStub) mActivity.findViewById(R.id.bottom_controls_stub)).inflate();
|
|
+ MoveBottomBarOverTopBar();
|
|
assert mTabGroupUiOneshotSupplier == null;
|
|
mTabGroupUiOneshotSupplier =
|
|
new TabGroupUiOneshotSupplier(
|
|
mActivityTabProvider,
|
|
mTabModelSelector,
|
|
mActivity,
|
|
- root.findViewById(R.id.bottom_container_slot),
|
|
+ mBottomRoot.findViewById(R.id.bottom_container_slot),
|
|
mBrowserControlsVisibilityManager,
|
|
mIncognitoStateProvider,
|
|
mScrimCoordinator,
|
|
@@ -1547,7 +1575,7 @@ public class ToolbarManager
|
|
mBottomControlsStacker,
|
|
mFullscreenManager,
|
|
mEdgeToEdgeControllerSupplier,
|
|
- (ScrollingBottomViewResourceFrameLayout) root,
|
|
+ (ScrollingBottomViewResourceFrameLayout) mBottomRoot,
|
|
bottomControlsContentDelegateSupplier,
|
|
mTabObscuringHandler,
|
|
mOverlayPanelVisibilitySupplier,
|
|
@@ -1555,7 +1583,8 @@ public class ToolbarManager
|
|
/* readAloudRestoringSupplier= */ () -> {
|
|
final var readAloud = mReadAloudControllerSupplier.get();
|
|
return readAloud != null && readAloud.isRestoringPlayer();
|
|
- });
|
|
+ },
|
|
+ mTopUiThemeColorProvider, mActivityTabProvider);
|
|
mBottomControlsCoordinatorSupplier.set(bottomControlsCoordinator);
|
|
if (mBackPressManager != null) {
|
|
mBackPressManager.addHandler(
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/BottomContainer.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/BottomContainer.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/ui/BottomContainer.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/BottomContainer.java
|
|
@@ -15,6 +15,7 @@ import org.chromium.base.lifetime.Destroyable;
|
|
import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
|
|
import org.chromium.ui.base.ApplicationViewportInsetSupplier;
|
|
import org.chromium.ui.base.ViewportInsets;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
|
|
/**
|
|
* The container that holds both infobars and snackbars. It will be translated up and down when the
|
|
@@ -63,10 +64,27 @@ public class BottomContainer extends FrameLayout
|
|
setTranslationY(mBaseYOffset);
|
|
}
|
|
|
|
+ @Override
|
|
+ public void onTopControlsHeightChanged(int topControlsHeight, int topControlsMinHeight) {
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled())
|
|
+ setTranslationY(mBaseYOffset);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void onAndroidControlsVisibilityChanged(int visibility) {
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled())
|
|
+ setTranslationY(mBaseYOffset);
|
|
+ }
|
|
+
|
|
@Override
|
|
public void setTranslationY(float y) {
|
|
mBaseYOffset = y;
|
|
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // the snackbar container is moved up because there is the top toolbar at the bottom
|
|
+ mBaseYOffset = -(mBrowserControlsStateProvider.getTopControlsHeight()
|
|
+ + mBrowserControlsStateProvider.getTopControlOffset());
|
|
+ }
|
|
float offsetFromControls =
|
|
mBrowserControlsStateProvider.getBottomControlOffset()
|
|
- mBrowserControlsStateProvider.getBottomControlsHeight();
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java
|
|
@@ -8,10 +8,13 @@ import android.content.Context;
|
|
import android.graphics.Color;
|
|
import android.view.View;
|
|
import android.view.Window;
|
|
+import android.os.Build;
|
|
|
|
import androidx.annotation.ColorInt;
|
|
import androidx.annotation.Nullable;
|
|
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
+
|
|
import org.chromium.base.CallbackController;
|
|
import org.chromium.base.supplier.ObservableSupplier;
|
|
import org.chromium.chrome.R;
|
|
@@ -482,6 +485,12 @@ public class StatusBarColorController
|
|
boolean needsDarkStatusBarIcons = !ColorUtils.shouldUseLightForegroundOnBackground(color);
|
|
UiUtils.setStatusBarIconColor(root, needsDarkStatusBarIcons);
|
|
UiUtils.setStatusBarColor(window, color);
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled() &&
|
|
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
+ UiUtils.setNavigationBarIconColor(window.getDecorView().getRootView(),
|
|
+ needsDarkStatusBarIcons);
|
|
+ window.setNavigationBarColor(color);
|
|
+ }
|
|
}
|
|
|
|
/**
|
|
diff --git a/chrome/browser/android/compositor/layer/toolbar_layer.cc b/chrome/browser/android/compositor/layer/toolbar_layer.cc
|
|
--- a/chrome/browser/android/compositor/layer/toolbar_layer.cc
|
|
+++ b/chrome/browser/android/compositor/layer/toolbar_layer.cc
|
|
@@ -5,6 +5,7 @@
|
|
#include "chrome/browser/android/compositor/layer/toolbar_layer.h"
|
|
|
|
#include "base/feature_list.h"
|
|
+#include "cc/base/features.h"
|
|
#include "cc/resources/scoped_ui_resource.h"
|
|
#include "cc/slim/layer.h"
|
|
#include "cc/slim/nine_patch_layer.h"
|
|
@@ -115,8 +116,13 @@ void ToolbarLayer::PushResource(int toolbar_resource_id,
|
|
debug_layer_->RemoveFromParent();
|
|
|
|
// Position the toolbar at the bottom of the space available for top controls.
|
|
- layer_->SetPosition(
|
|
- gfx::PointF(x_offset, content_offset - layer_->bounds().height()));
|
|
+ if (base::FeatureList::IsEnabled(::features::kMoveTopToolbarToBottom)) {
|
|
+ layer_->SetPosition(
|
|
+ gfx::PointF(x_offset, content_offset + layer_->bounds().height()));
|
|
+ } else {
|
|
+ layer_->SetPosition(
|
|
+ gfx::PointF(x_offset, content_offset - layer_->bounds().height()));
|
|
+ }
|
|
|
|
layer_->SetOffsetTag(offset_tag);
|
|
}
|
|
diff --git a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc
|
|
--- a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc
|
|
+++ b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc
|
|
@@ -20,6 +20,7 @@
|
|
#include "ui/gfx/geometry/point_f.h"
|
|
#include "ui/gfx/geometry/rounded_corners_f.h"
|
|
#include "ui/gfx/geometry/transform.h"
|
|
+#include "cc/base/features.h"
|
|
|
|
// Must come after all headers that specialize FromJniType() / ToJniType().
|
|
#include "chrome/android/chrome_jni_headers/TabStripSceneLayer_jni.h"
|
|
@@ -97,8 +98,10 @@ void TabStripSceneLayer::SetContentTree(
|
|
content_tree_ = content_tree;
|
|
if (content_tree) {
|
|
layer()->InsertChild(content_tree->layer(), 0);
|
|
- content_tree->layer()->SetPosition(
|
|
- gfx::PointF(0, -layer()->position().y()));
|
|
+ if (!base::FeatureList::IsEnabled(::features::kMoveTopToolbarToBottom)) {
|
|
+ content_tree->layer()->SetPosition(
|
|
+ gfx::PointF(0, -layer()->position().y()));
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
@@ -147,7 +150,12 @@ void TabStripSceneLayer::UpdateTabStripLayer(JNIEnv* env,
|
|
jfloat right_padding,
|
|
jfloat top_padding) {
|
|
gfx::RectF content(0, y_offset, width, height);
|
|
- layer()->SetPosition(gfx::PointF(0, y_offset));
|
|
+ if (base::FeatureList::IsEnabled(::features::kMoveTopToolbarToBottom)) {
|
|
+ // do not move the whole layer (which also contains the contents) but only the tab strip layer
|
|
+ tab_strip_layer_->SetPosition(gfx::PointF(0, y_offset));
|
|
+ } else {
|
|
+ layer()->SetPosition(gfx::PointF(0, y_offset));
|
|
+ }
|
|
tab_strip_layer_->SetBounds(gfx::Size(width, height));
|
|
tab_strip_layer_->SetBackgroundColor(SkColor4f::FromColor(background_color));
|
|
|
|
@@ -159,7 +167,7 @@ void TabStripSceneLayer::UpdateTabStripLayer(JNIEnv* env,
|
|
group_indicator_layer_->SetPosition(gfx::PointF(0, top_padding));
|
|
|
|
// Content tree should not be affected by tab strip scene layer visibility.
|
|
- if (content_tree_)
|
|
+ if (content_tree_ && !base::FeatureList::IsEnabled(::features::kMoveTopToolbarToBottom))
|
|
content_tree_->layer()->SetPosition(gfx::PointF(0, -y_offset));
|
|
|
|
// Update left and right padding layers as required.
|
|
diff --git a/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BottomControlsStacker.java b/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BottomControlsStacker.java
|
|
--- a/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BottomControlsStacker.java
|
|
+++ b/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BottomControlsStacker.java
|
|
@@ -122,7 +122,7 @@ public class BottomControlsStacker implements BrowserControlsStateProvider.Obser
|
|
/**
|
|
* @return {@link BrowserControlsStateProvider} instance in the current Activity.
|
|
*/
|
|
- public BrowserControlsStateProvider getBrowserControls() {
|
|
+ public BrowserControlsSizer getBrowserControls() {
|
|
return mBrowserControlsSizer;
|
|
}
|
|
|
|
diff --git a/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserControlsMarginSupplier.java b/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserControlsMarginSupplier.java
|
|
--- a/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserControlsMarginSupplier.java
|
|
+++ b/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserControlsMarginSupplier.java
|
|
@@ -8,6 +8,7 @@ import android.graphics.Rect;
|
|
|
|
import org.chromium.base.supplier.DestroyableObservableSupplier;
|
|
import org.chromium.base.supplier.ObservableSupplierImpl;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
|
|
/**
|
|
* An implementation of {@link DestroyableObservableSupplier} that monitors changes to browser
|
|
@@ -59,6 +60,10 @@ public class BrowserControlsMarginSupplier extends ObservableSupplierImpl<Rect>
|
|
int bottomMargin =
|
|
mBrowserControlsStateProvider.getBottomControlsHeight()
|
|
- mBrowserControlsStateProvider.getBottomControlOffset();
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ bottomMargin += topMargin;
|
|
+ topMargin = 0;
|
|
+ }
|
|
super.set(new Rect(0, topMargin, 0, bottomMargin));
|
|
}
|
|
}
|
|
diff --git a/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserControlsStateProvider.java b/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserControlsStateProvider.java
|
|
--- a/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserControlsStateProvider.java
|
|
+++ b/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserControlsStateProvider.java
|
|
@@ -85,6 +85,12 @@ public interface BrowserControlsStateProvider {
|
|
*/
|
|
int getTopControlsHeight();
|
|
|
|
+ /**
|
|
+ * @return The height of the top controls in pixels.
|
|
+ * returns 0 is the toolbar is at the bottom
|
|
+ */
|
|
+ int getTopControlsHeightRealOffset();
|
|
+
|
|
/**
|
|
* @return The minimum visible height top controls can have in pixels.
|
|
*/
|
|
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedListContentManager.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedListContentManager.java
|
|
--- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedListContentManager.java
|
|
+++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedListContentManager.java
|
|
@@ -14,6 +14,7 @@ import android.widget.FrameLayout;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.annotation.Px;
|
|
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
import org.chromium.chrome.browser.xsurface.ListContentManager;
|
|
import org.chromium.chrome.browser.xsurface.ListContentManagerObserver;
|
|
import org.chromium.chrome.browser.xsurface.LoggingParameters;
|
|
@@ -142,7 +143,10 @@ public class FeedListContentManager implements ListContentManager {
|
|
FrameLayout enclosingLayout = new FrameLayout(parent.getContext());
|
|
FrameLayout.LayoutParams layoutParams =
|
|
new FrameLayout.LayoutParams(
|
|
- new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
|
|
+ new LayoutParams(LayoutParams.MATCH_PARENT,
|
|
+ ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()
|
|
+ ? LayoutParams.MATCH_PARENT
|
|
+ : LayoutParams.WRAP_CONTENT));
|
|
enclosingLayout.setLayoutParams(layoutParams);
|
|
|
|
// Set the left and right paddings.
|
|
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
|
|
--- a/chrome/browser/flags/android/chrome_feature_list.cc
|
|
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
|
|
@@ -12,6 +12,7 @@
|
|
#include "base/feature_list.h"
|
|
#include "base/features.h"
|
|
#include "base/no_destructor.h"
|
|
+#include "cc/base/features.h"
|
|
#include "chrome/browser/android/webapk/webapk_features.h"
|
|
#include "chrome/browser/browser_features.h"
|
|
#include "chrome/browser/flags/android/chrome_session_state.h"
|
|
@@ -260,6 +261,8 @@ const base::Feature* const kFeaturesExposedToJava[] = {
|
|
&kNavBarColorMatchesTabBackground,
|
|
&kNewTabSearchEngineUrlAndroid,
|
|
&kNewTabPageAndroidTriggerForPrerender2,
|
|
+ &features::kMoveTopToolbarToBottom,
|
|
+ &features::kDisableToolbarSwipeUp,
|
|
&kNotificationPermissionVariant,
|
|
&kNotificationPermissionBottomSheet,
|
|
&kOfflineIndicatorV2,
|
|
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
|
|
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
|
|
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
|
|
@@ -374,6 +374,10 @@ public abstract class ChromeFeatureList {
|
|
public static final String NEW_TAB_PAGE_ANDROID_TRIGGER_FOR_PRERENDER2 =
|
|
"NewTabPageAndroidTriggerForPrerender2";
|
|
public static final String NOTIFICATION_ONE_TAP_UNSUBSCRIBE = "NotificationOneTapUnsubscribe";
|
|
+ public static final String DISABLE_TOOLBAR_SWIPE_UP =
|
|
+ "DisableToolbarSwipeUp";
|
|
+ public static final String MOVE_TOP_TOOLBAR_TO_BOTTOM =
|
|
+ "MoveTopToolbarToBottom";
|
|
public static final String NOTIFICATION_PERMISSION_VARIANT = "NotificationPermissionVariant";
|
|
public static final String NOTIFICATION_PERMISSION_BOTTOM_SHEET =
|
|
"NotificationPermissionBottomSheet";
|
|
@@ -670,6 +674,10 @@ public abstract class ChromeFeatureList {
|
|
public static final CachedFlag sPriceInsights = newCachedFlag(PRICE_INSIGHTS, false);
|
|
public static final CachedFlag sPrivacyGuideAndroid3 =
|
|
newCachedFlag(PRIVACY_GUIDE_ANDROID_3, false);
|
|
+ public static final CachedFlag sDisableToolbarSwipeUp =
|
|
+ newCachedFlag(DISABLE_TOOLBAR_SWIPE_UP, false);
|
|
+ public static final CachedFlag sMoveTopToolbarToBottom =
|
|
+ newCachedFlag(MOVE_TOP_TOOLBAR_TO_BOTTOM, false);
|
|
public static final CachedFlag sPrivacyGuidePreloadAndroid =
|
|
newCachedFlag(PRIVACY_GUIDE_PRELOAD_ANDROID, false);
|
|
public static final CachedFlag sOptimizationGuidePushNotifications =
|
|
@@ -800,6 +808,8 @@ public abstract class ChromeFeatureList {
|
|
sPrivacyGuideAndroid3,
|
|
sPrivacyGuidePreloadAndroid,
|
|
sOptimizationGuidePushNotifications,
|
|
+ sMoveTopToolbarToBottom,
|
|
+ sDisableToolbarSwipeUp,
|
|
sPaintPreviewDemo,
|
|
sPrefetchBrowserInitiatedTriggers,
|
|
sQueryTiles,
|
|
diff --git a/chrome/browser/hub/internal/BUILD.gn b/chrome/browser/hub/internal/BUILD.gn
|
|
--- a/chrome/browser/hub/internal/BUILD.gn
|
|
+++ b/chrome/browser/hub/internal/BUILD.gn
|
|
@@ -16,6 +16,7 @@ android_library("java") {
|
|
"//chrome/test/android:chrome_java_transit",
|
|
]
|
|
sources = [
|
|
+ "android/java/src/org/chromium/chrome/browser/hub/ReversedLinearLayout.java",
|
|
"android/java/src/org/chromium/chrome/browser/hub/ApplyButtonData.java",
|
|
"android/java/src/org/chromium/chrome/browser/hub/FadeHubLayoutAnimationFactory.java",
|
|
"android/java/src/org/chromium/chrome/browser/hub/FadeHubLayoutAnimationFactoryImpl.java",
|
|
@@ -68,6 +69,10 @@ android_library("java") {
|
|
"//third_party/androidx:androidx_interpolator_interpolator_java",
|
|
"//ui/android:ui_no_recycler_view_java",
|
|
]
|
|
+ deps += [
|
|
+ "//base:base_cached_flags_java",
|
|
+ "//chrome/browser/flags:java",
|
|
+ ]
|
|
}
|
|
|
|
android_resources("java_resources") {
|
|
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubCoordinator.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubCoordinator.java
|
|
--- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubCoordinator.java
|
|
+++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubCoordinator.java
|
|
@@ -8,6 +8,7 @@ import android.content.Context;
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.widget.FrameLayout;
|
|
+import android.widget.LinearLayout;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
@@ -18,6 +19,7 @@ import org.chromium.base.supplier.ObservableSupplierImpl;
|
|
import org.chromium.base.supplier.OneshotSupplier;
|
|
import org.chromium.base.supplier.TransitiveObservableSupplier;
|
|
import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
import org.chromium.chrome.browser.profiles.ProfileProvider;
|
|
import org.chromium.chrome.browser.tab.Tab;
|
|
import org.chromium.chrome.browser.toolbar.menu_button.MenuButtonCoordinator;
|
|
@@ -93,6 +95,12 @@ public class HubCoordinator implements PaneHubController, BackPressHandler {
|
|
HubPaneHostView hubPaneHostView = mContainerView.findViewById(R.id.hub_pane_host);
|
|
mHubPaneHostCoordinator =
|
|
new HubPaneHostCoordinator(hubPaneHostView, paneManager.getFocusedPaneSupplier());
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)
|
|
+ hubPaneHostView.getLayoutParams();
|
|
+ params.bottomMargin = hubToolbarView.getHeight();
|
|
+ hubPaneHostView.setLayoutParams(params);
|
|
+ }
|
|
|
|
mHubLayoutController = hubLayoutController;
|
|
mHandleBackPressSupplier = new ObservableSupplierImpl<>();
|
|
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubManagerImpl.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubManagerImpl.java
|
|
--- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubManagerImpl.java
|
|
+++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubManagerImpl.java
|
|
@@ -6,6 +6,7 @@ package org.chromium.chrome.browser.hub;
|
|
|
|
import android.content.Context;
|
|
import android.view.View;
|
|
+import android.view.ViewGroup;
|
|
import android.widget.FrameLayout.LayoutParams;
|
|
|
|
import androidx.annotation.ColorInt;
|
|
@@ -16,6 +17,7 @@ import org.chromium.base.ValueChangedCallback;
|
|
import org.chromium.base.supplier.ObservableSupplier;
|
|
import org.chromium.base.supplier.ObservableSupplierImpl;
|
|
import org.chromium.base.supplier.OneshotSupplier;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
import org.chromium.chrome.browser.back_press.BackPressManager;
|
|
import org.chromium.chrome.browser.profiles.ProfileProvider;
|
|
import org.chromium.chrome.browser.tab.Tab;
|
|
@@ -111,7 +113,10 @@ public class HubManagerImpl implements HubManager, HubController {
|
|
LayoutParams params = (LayoutParams) mHubContainerView.getLayoutParams();
|
|
assert params != null : "HubContainerView should always have layout params.";
|
|
mStatusIndicatorHeight = height;
|
|
- params.topMargin = mStatusIndicatorHeight + mAppHeaderHeight;
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled())
|
|
+ params.bottomMargin = mStatusIndicatorHeight + mAppHeaderHeight;
|
|
+ else
|
|
+ params.topMargin = mStatusIndicatorHeight + mAppHeaderHeight;
|
|
mHubContainerView.setLayoutParams(params);
|
|
}
|
|
|
|
@@ -121,7 +126,10 @@ public class HubManagerImpl implements HubManager, HubController {
|
|
LayoutParams params = (LayoutParams) mHubContainerView.getLayoutParams();
|
|
assert params != null : "HubContainerView should always have layout params.";
|
|
mAppHeaderHeight = height;
|
|
- params.topMargin = mStatusIndicatorHeight + mAppHeaderHeight;
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled())
|
|
+ params.bottomMargin = mStatusIndicatorHeight + mAppHeaderHeight;
|
|
+ else
|
|
+ params.topMargin = mStatusIndicatorHeight + mAppHeaderHeight;
|
|
mHubContainerView.setLayoutParams(params);
|
|
}
|
|
|
|
@@ -242,6 +250,9 @@ public class HubManagerImpl implements HubManager, HubController {
|
|
mMenuOrKeyboardActionController.registerMenuOrKeyboardActionHandler(
|
|
menuOrKeyboardActionHandler);
|
|
}
|
|
- mSnackbarManager.setParentView(mHubContainerView);
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled())
|
|
+ mSnackbarManager.setParentView((ViewGroup)getPaneHostView());
|
|
+ else
|
|
+ mSnackbarManager.setParentView(mHubContainerView);
|
|
}
|
|
}
|
|
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/ReversedLinearLayout.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/ReversedLinearLayout.java
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/ReversedLinearLayout.java
|
|
@@ -0,0 +1,42 @@
|
|
+package org.chromium.chrome.browser.hub;
|
|
+
|
|
+import android.content.Context;
|
|
+import android.util.AttributeSet;
|
|
+import android.widget.LinearLayout;
|
|
+import android.view.Gravity;
|
|
+import android.view.View;
|
|
+
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
+
|
|
+public class ReversedLinearLayout extends LinearLayout {
|
|
+ private boolean mReversedLayout;
|
|
+
|
|
+ public ReversedLinearLayout(Context context) {
|
|
+ super(context);
|
|
+ setReversedLayout();
|
|
+ }
|
|
+
|
|
+ public ReversedLinearLayout(Context context, AttributeSet attrs) {
|
|
+ super(context, attrs);
|
|
+ setReversedLayout();
|
|
+ }
|
|
+
|
|
+ public ReversedLinearLayout(Context context, AttributeSet attrs, int defStyle) {
|
|
+ super(context, attrs, defStyle);
|
|
+ setReversedLayout();
|
|
+ }
|
|
+
|
|
+ private void setReversedLayout() {
|
|
+ mReversedLayout = ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled();
|
|
+ if (mReversedLayout)
|
|
+ setGravity(Gravity.START | Gravity.BOTTOM);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public View getChildAt(int i) {
|
|
+ if (mReversedLayout)
|
|
+ return super.getChildAt(getChildCount() - 1 - i);
|
|
+ else
|
|
+ return super.getChildAt(i);
|
|
+ }
|
|
+}
|
|
diff --git a/chrome/browser/hub/internal/android/res/layout/hub_layout.xml b/chrome/browser/hub/internal/android/res/layout/hub_layout.xml
|
|
--- a/chrome/browser/hub/internal/android/res/layout/hub_layout.xml
|
|
+++ b/chrome/browser/hub/internal/android/res/layout/hub_layout.xml
|
|
@@ -4,7 +4,7 @@ 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.
|
|
-->
|
|
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
+<org.chromium.chrome.browser.hub.ReversedLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
android:layout_width="match_parent"
|
|
android:layout_height="match_parent"
|
|
android:orientation="vertical">
|
|
@@ -13,4 +13,4 @@ found in the LICENSE file.
|
|
|
|
<include layout="@layout/hub_pane_host_layout" />
|
|
|
|
-</LinearLayout>
|
|
\ No newline at end of file
|
|
+</org.chromium.chrome.browser.hub.ReversedLinearLayout>
|
|
diff --git a/chrome/browser/hub/internal/android/res/layout/hub_toolbar_layout.xml b/chrome/browser/hub/internal/android/res/layout/hub_toolbar_layout.xml
|
|
--- a/chrome/browser/hub/internal/android/res/layout/hub_toolbar_layout.xml
|
|
+++ b/chrome/browser/hub/internal/android/res/layout/hub_toolbar_layout.xml
|
|
@@ -9,7 +9,7 @@ found in the LICENSE file.
|
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
android:id="@+id/hub_toolbar"
|
|
android:layout_width="match_parent"
|
|
- android:layout_height="wrap_content"
|
|
+ android:layout_height="@dimen/toolbar_height_no_shadow"
|
|
android:orientation="vertical">
|
|
|
|
<FrameLayout
|
|
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
|
|
--- a/chrome/browser/prefs/browser_prefs.cc
|
|
+++ b/chrome/browser/prefs/browser_prefs.cc
|
|
@@ -2168,7 +2168,7 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
|
|
|
|
#if BUILDFLAG(IS_ANDROID)
|
|
registry->RegisterBooleanPref(prefs::kVirtualKeyboardResizesLayoutByDefault,
|
|
- false);
|
|
+ true);
|
|
#endif
|
|
|
|
#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
|
|
diff --git a/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenu.java b/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenu.java
|
|
--- a/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenu.java
|
|
+++ b/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenu.java
|
|
@@ -12,6 +12,7 @@ import android.graphics.Color;
|
|
import android.graphics.Rect;
|
|
import android.graphics.drawable.ColorDrawable;
|
|
import android.graphics.drawable.Drawable;
|
|
+import android.os.Build;
|
|
import android.os.SystemClock;
|
|
import android.text.TextUtils;
|
|
import android.view.Gravity;
|
|
@@ -41,6 +42,7 @@ import org.chromium.base.SysUtils;
|
|
import org.chromium.base.metrics.RecordHistogram;
|
|
import org.chromium.base.task.PostTask;
|
|
import org.chromium.base.task.TaskTraits;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
import org.chromium.chrome.browser.ui.appmenu.internal.R;
|
|
import org.chromium.components.browser_ui.styles.ChromeColors;
|
|
import org.chromium.components.browser_ui.widget.chips.ChipView;
|
|
@@ -265,6 +267,12 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuClickHandler
|
|
}
|
|
|
|
mListView = (ListView) contentView.findViewById(R.id.app_menu_list);
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // always scroll to the bottom to show new items
|
|
+ mListView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
|
|
+ // fill content starting from the bottom of the view
|
|
+ mListView.setStackFromBottom(true);
|
|
+ }
|
|
|
|
int footerHeight = inflateFooter(footerResourceId, contentView, menuWidth);
|
|
int headerHeight = inflateHeader(headerResourceId, contentView, menuWidth);
|
|
@@ -297,7 +305,7 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuClickHandler
|
|
Math.min(
|
|
Math.abs(mTempLocation[1] - visibleDisplayFrame.top),
|
|
Math.abs(mTempLocation[1] - visibleDisplayFrame.bottom));
|
|
- setMenuHeight(
|
|
+ int popupHeight = setMenuHeight(
|
|
menuItemIds,
|
|
heightList,
|
|
visibleDisplayFrame,
|
|
@@ -317,8 +325,14 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuClickHandler
|
|
sizingPadding,
|
|
anchorView,
|
|
popupWidth,
|
|
- anchorView.getRootView().getLayoutDirection());
|
|
+ anchorView.getRootView().getLayoutDirection(),
|
|
+ popupHeight);
|
|
mPopup.setContentView(contentView);
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // due to some unknown behaviour, the popup must be resized to
|
|
+ // allow selection without leaving touch
|
|
+ mPopup.setHeight(popupHeight - 1);
|
|
+ }
|
|
|
|
try {
|
|
mPopup.showAtLocation(
|
|
@@ -379,11 +393,20 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuClickHandler
|
|
Rect padding,
|
|
View anchorView,
|
|
int popupWidth,
|
|
- int viewLayoutDirection) {
|
|
+ int viewLayoutDirection,
|
|
+ int popupHeight) {
|
|
anchorView.getLocationInWindow(tempLocation);
|
|
int anchorViewX = tempLocation[0];
|
|
int anchorViewY = tempLocation[1];
|
|
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // moves the view offset up by the height of the popup
|
|
+ anchorViewY -= popupHeight;
|
|
+ // fix it if it goes offscreen
|
|
+ if (anchorViewY <= negativeSoftwareVerticalOffset)
|
|
+ anchorViewY = negativeSoftwareVerticalOffset;
|
|
+ }
|
|
+
|
|
int[] offsets = new int[2];
|
|
// If we have a hardware menu button, locate the app menu closer to the estimated
|
|
// hardware menu button location.
|
|
@@ -557,7 +580,7 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuClickHandler
|
|
if (mAdapter != null) mAdapter.notifyDataSetChanged();
|
|
}
|
|
|
|
- private void setMenuHeight(
|
|
+ private int setMenuHeight(
|
|
List<Integer> menuItemIds,
|
|
List<Integer> heightList,
|
|
Rect appDimensions,
|
|
@@ -576,7 +599,13 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuClickHandler
|
|
- footerHeight
|
|
- headerHeight
|
|
- anchorViewImpactHeight;
|
|
-
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N) {
|
|
+ // due to an Android Nougat bug the popup does not appear above the anchorview.
|
|
+ // the display is not pleasant, so we reduce the space
|
|
+ availableScreenSpace -= anchorView.getHeight();
|
|
+ }
|
|
+ }
|
|
if (mIsByPermanentButton) availableScreenSpace -= padding.top;
|
|
if (availableScreenSpace <= 0 && sExceptionReporter != null) {
|
|
String logMessage =
|
|
@@ -606,6 +635,7 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuClickHandler
|
|
menuItemIds, heightList, groupDividerResourceId, availableScreenSpace);
|
|
menuHeight += footerHeight + headerHeight + padding.top + padding.bottom;
|
|
mPopup.setHeight(menuHeight);
|
|
+ return menuHeight;
|
|
}
|
|
|
|
@VisibleForTesting
|
|
diff --git a/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuHandlerImpl.java b/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuHandlerImpl.java
|
|
--- a/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuHandlerImpl.java
|
|
+++ b/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuHandlerImpl.java
|
|
@@ -19,6 +19,7 @@ import androidx.annotation.VisibleForTesting;
|
|
|
|
import org.chromium.base.Callback;
|
|
import org.chromium.base.metrics.RecordUserAction;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
import org.chromium.base.supplier.Supplier;
|
|
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
|
|
import org.chromium.chrome.browser.lifecycle.ConfigurationChangedObserver;
|
|
@@ -219,7 +220,16 @@ class AppMenuHandlerImpl
|
|
id, customViewBinders, customViewTypeOffsetMap);
|
|
}),
|
|
this);
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // reverses the order of items in the menu
|
|
+ ModelList modelListReversed = new ModelList();
|
|
+ for (int i = 0; i < mModelList.size(); i++) {
|
|
+ modelListReversed.add(0, mModelList.get(i));
|
|
+ }
|
|
+ mModelList = modelListReversed;
|
|
+ }
|
|
mModelList.addObserver(mListObserver);
|
|
+
|
|
ContextThemeWrapper wrapper =
|
|
new ContextThemeWrapper(mContext, R.style.OverflowMenuThemeOverlay);
|
|
|
|
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxSuggestionsDropdownEmbedderImpl.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxSuggestionsDropdownEmbedderImpl.java
|
|
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxSuggestionsDropdownEmbedderImpl.java
|
|
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxSuggestionsDropdownEmbedderImpl.java
|
|
@@ -15,6 +15,7 @@ import android.view.WindowInsets;
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.core.graphics.Insets;
|
|
+import androidx.core.view.ViewCompat;
|
|
import androidx.core.view.WindowInsetsCompat;
|
|
|
|
import org.chromium.base.BuildInfo;
|
|
@@ -23,6 +24,7 @@ import org.chromium.base.supplier.ObservableSupplierImpl;
|
|
import org.chromium.base.supplier.Supplier;
|
|
import org.chromium.chrome.browser.omnibox.styles.OmniboxResourceProvider;
|
|
import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionsDropdownEmbedder;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
import org.chromium.ui.base.DeviceFormFactor;
|
|
import org.chromium.ui.base.ViewUtils;
|
|
import org.chromium.ui.base.WindowAndroid;
|
|
@@ -97,6 +99,11 @@ class OmniboxSuggestionsDropdownEmbedderImpl
|
|
mOmniboxAlignmentSupplier.removeObserver(obs);
|
|
}
|
|
|
|
+ @Override
|
|
+ public View getAnchorView() {
|
|
+ return mAnchorView;
|
|
+ }
|
|
+
|
|
@Nullable
|
|
@Override
|
|
public OmniboxAlignment getCurrentAlignment() {
|
|
@@ -121,6 +128,9 @@ class OmniboxSuggestionsDropdownEmbedderImpl
|
|
|
|
@Override
|
|
public void onDetachedFromWindow() {
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ recalculateOmniboxAlignment();
|
|
+ }
|
|
mAnchorView.removeOnLayoutChangeListener(this);
|
|
mAlignmentView.removeOnLayoutChangeListener(this);
|
|
mAnchorView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
|
@@ -211,6 +221,8 @@ class OmniboxSuggestionsDropdownEmbedderImpl
|
|
ViewUtils.getRelativeLayoutPosition(baseRelativeLayout, mAnchorView, mPositionArray);
|
|
|
|
int top = mPositionArray[1] + mAnchorView.getMeasuredHeight() - contentViewTopPadding;
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled())
|
|
+ top -= mPositionArray[1];
|
|
int left;
|
|
int width;
|
|
int paddingLeft;
|
|
@@ -277,6 +289,12 @@ class OmniboxSuggestionsDropdownEmbedderImpl
|
|
: contentView.getMeasuredHeight() - keyboardHeight;
|
|
int height = Math.min(windowSpace, contentSpace) - top;
|
|
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ ViewCompat.setPaddingRelative(
|
|
+ contentView, 0, 0, 0, keyboardHeight);
|
|
+ top = 0;
|
|
+ }
|
|
+
|
|
// TODO(pnoland@, https://crbug.com/1416985): avoid pushing changes that are identical to
|
|
// the previous alignment value.
|
|
OmniboxAlignment omniboxAlignment =
|
|
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
|
|
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
|
|
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
|
|
@@ -48,6 +48,7 @@ import org.chromium.ui.modelutil.LazyConstructionPropertyMcp;
|
|
import org.chromium.ui.modelutil.MVCListAdapter;
|
|
import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
|
|
import org.chromium.ui.modelutil.PropertyModel;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
@@ -66,6 +67,7 @@ public class AutocompleteCoordinator
|
|
private @Nullable OmniboxSuggestionsDropdown mDropdown;
|
|
private @NonNull ObserverList<OmniboxSuggestionsDropdownScrollListener> mScrollListenerList =
|
|
new ObserverList<>();
|
|
+ private final @NonNull OmniboxSuggestionsDropdownEmbedder mDropdownEmbedder;
|
|
|
|
/** An observer watching for changes to the visual state of the omnibox suggestions. */
|
|
public interface OmniboxSuggestionsVisualStateObserver {
|
|
@@ -102,6 +104,7 @@ public class AutocompleteCoordinator
|
|
Context context = parent.getContext();
|
|
|
|
ModelList listItems = new ModelList();
|
|
+ mDropdownEmbedder = dropdownEmbedder;
|
|
PropertyModel listModel =
|
|
new PropertyModel.Builder(SuggestionListProperties.ALL_KEYS)
|
|
.with(SuggestionListProperties.EMBEDDER, dropdownEmbedder)
|
|
@@ -219,6 +222,16 @@ public class AutocompleteCoordinator
|
|
|
|
dropdown.forcePhoneStyleOmnibox(forcePhoneStyleOmnibox);
|
|
dropdown.setAdapter(mAdapter);
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // make margins works
|
|
+ dropdown.getViewGroup().setClipToPadding(true);
|
|
+ container.bringToFront();
|
|
+
|
|
+ // do not cover the bar
|
|
+ ViewGroup.LayoutParams params = container.getLayoutParams();
|
|
+ ((ViewGroup.MarginLayoutParams) params).bottomMargin =
|
|
+ mDropdownEmbedder.getAnchorView().getMeasuredHeight();
|
|
+ }
|
|
mRecycledViewPool.ifPresent(p -> dropdown.setRecycledViewPool(p));
|
|
mHolder = new SuggestionListViewHolder(container, dropdown);
|
|
for (int i = 0; i < mCallbacks.size(); i++) {
|
|
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
|
|
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
|
|
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
|
|
@@ -68,6 +68,8 @@ import org.chromium.ui.modelutil.PropertyModel;
|
|
import org.chromium.ui.mojom.WindowOpenDisposition;
|
|
import org.chromium.url.GURL;
|
|
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
+
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
import java.util.List;
|
|
@@ -1162,7 +1164,9 @@ class AutocompleteMediator
|
|
@Override
|
|
public void onSuggestionDropdownScroll() {
|
|
mSuggestionsListScrolled = true;
|
|
- mDelegate.setKeyboardVisibility(false, false);
|
|
+ if (!ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ mDelegate.setKeyboardVisibility(false, false);
|
|
+ }
|
|
}
|
|
|
|
/**
|
|
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManager.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManager.java
|
|
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManager.java
|
|
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManager.java
|
|
@@ -9,6 +9,7 @@ import android.view.View;
|
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
import org.chromium.chrome.browser.ui.theme.BrandedColorScheme;
|
|
import org.chromium.ui.base.DeviceFormFactor;
|
|
import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
|
|
@@ -102,7 +103,11 @@ class DropdownItemViewInfoListManager {
|
|
|
|
// round the bottom corners of the last suggestion.
|
|
if (previousItem != null) {
|
|
- previousItem.model.set(DropdownCommonProperties.BG_BOTTOM_CORNER_ROUNDED, true);
|
|
+ boolean toolbarToBottom =
|
|
+ ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled();
|
|
+ previousItem.model.set(toolbarToBottom
|
|
+ ? DropdownCommonProperties.BG_TOP_CORNER_ROUNDED
|
|
+ : DropdownCommonProperties.BG_BOTTOM_CORNER_ROUNDED, true);
|
|
}
|
|
|
|
mManagedModel.set(suggestionsList);
|
|
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdown.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdown.java
|
|
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdown.java
|
|
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdown.java
|
|
@@ -43,6 +43,9 @@ import org.chromium.ui.base.ViewUtils;
|
|
|
|
import java.util.Optional;
|
|
|
|
+import android.graphics.Rect;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
+
|
|
/** A widget for showing a list of omnibox suggestions. */
|
|
public class OmniboxSuggestionsDropdown extends RecyclerView {
|
|
/**
|
|
@@ -242,7 +245,6 @@ public class OmniboxSuggestionsDropdown extends RecyclerView {
|
|
addItemDecoration(new SuggestionHorizontalDivider(context));
|
|
|
|
mLayoutScrollListener = new SuggestionLayoutScrollListener(context);
|
|
- setLayoutManager(mLayoutScrollListener);
|
|
mSelectionController = new RecyclerViewSelectionController(mLayoutScrollListener);
|
|
addOnChildAttachStateChangeListener(mSelectionController);
|
|
|
|
@@ -251,6 +253,13 @@ public class OmniboxSuggestionsDropdown extends RecyclerView {
|
|
resources.getDimensionPixelOffset(R.dimen.omnibox_suggestion_list_padding_bottom);
|
|
int paddingTop =
|
|
resources.getDimensionPixelOffset(R.dimen.omnibox_suggestion_list_padding_top);
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // reverse the layout so that the items are at the bottom (in reverse order)
|
|
+ // and anchored to the bottom edge
|
|
+ mLayoutScrollListener.setReverseLayout(true);
|
|
+ paddingTop = 0;
|
|
+ }
|
|
+ setLayoutManager(mLayoutScrollListener);
|
|
this.setPaddingRelative(0, paddingTop, 0, paddingBottom);
|
|
|
|
if (OmniboxFeatures.sAsyncViewInflation.isEnabled()) {
|
|
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdownEmbedder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdownEmbedder.java
|
|
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdownEmbedder.java
|
|
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdownEmbedder.java
|
|
@@ -5,6 +5,7 @@
|
|
package org.chromium.chrome.browser.omnibox.suggestions;
|
|
|
|
import android.annotation.SuppressLint;
|
|
+import android.view.View;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
@@ -109,6 +110,9 @@ public interface OmniboxSuggestionsDropdownEmbedder {
|
|
@NonNull
|
|
OmniboxAlignment getCurrentAlignment();
|
|
|
|
+ @NonNull
|
|
+ View getAnchorView();
|
|
+
|
|
/** Return whether the suggestions are being rendered in the tablet UI. */
|
|
boolean isTablet();
|
|
|
|
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
|
|
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
|
|
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
|
|
@@ -1699,6 +1699,12 @@ Your Google account may have other forms of browsing history like searches and a
|
|
<message name="IDS_FORCE_TABLET_UI_TITLE" desc="Title of the preference that allows the user to update force tablet UI settings.">
|
|
Force Tablet Mode
|
|
</message>
|
|
+ <message name="IDS_MOVE_TOOLBAR_BOTTOM_TITLE" desc="Title of the preference that allows the user to move toolbar on bottom.">
|
|
+ Move toolbar to bottom
|
|
+ </message>
|
|
+ <message name="IDS_DISABLE_TOOLBAR_SWIPE_UP" desc="Summary of the preference that allows the user to disable toolbar swipeup.">
|
|
+ Disable toolbar swipe up
|
|
+ </message>
|
|
|
|
<!-- Safety check -->
|
|
<message name="IDS_PREFS_SAFETY_CHECK" desc="Title of the Safety check element in settings, allowing the user to check multiple areas of browser safety. [CHAR_LIMIT=32]">
|
|
diff --git a/chrome/browser/ui/android/toolbar/BUILD.gn b/chrome/browser/ui/android/toolbar/BUILD.gn
|
|
--- a/chrome/browser/ui/android/toolbar/BUILD.gn
|
|
+++ b/chrome/browser/ui/android/toolbar/BUILD.gn
|
|
@@ -167,6 +167,7 @@ android_library("java") {
|
|
"//content/public/android:content_java",
|
|
"//third_party/android_deps:material_design_java",
|
|
"//third_party/androidx:androidx_annotation_annotation_experimental_java",
|
|
+ "//third_party/androidx:androidx_coordinatorlayout_coordinatorlayout_java",
|
|
"//third_party/androidx:androidx_annotation_annotation_java",
|
|
"//third_party/androidx:androidx_appcompat_appcompat_java",
|
|
"//third_party/androidx:androidx_appcompat_appcompat_resources_java",
|
|
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandler.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandler.java
|
|
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandler.java
|
|
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandler.java
|
|
@@ -16,6 +16,7 @@ import org.chromium.components.browser_ui.widget.scrim.ScrimProperties;
|
|
import org.chromium.ui.base.DeviceFormFactor;
|
|
import org.chromium.ui.modelutil.PropertyModel;
|
|
import org.chromium.ui.util.ColorUtils;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
|
|
/** Handles showing and hiding a scrim when url bar focus changes. */
|
|
public class LocationBarFocusScrimHandler implements UrlFocusChangeListener {
|
|
@@ -60,6 +61,10 @@ public class LocationBarFocusScrimHandler implements UrlFocusChangeListener {
|
|
mContext = context;
|
|
|
|
int topMargin = tabStripHeightSupplier.get() == null ? 0 : tabStripHeightSupplier.get();
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // since the top bar is at the bottom, we need to cover the whole page
|
|
+ topMargin = 0;
|
|
+ }
|
|
mLightScrimColor = context.getColor(R.color.omnibox_focused_fading_background_color_light);
|
|
mScrimModel =
|
|
new PropertyModel.Builder(ScrimProperties.ALL_KEYS)
|
|
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsContentDelegate.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsContentDelegate.java
|
|
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsContentDelegate.java
|
|
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsContentDelegate.java
|
|
@@ -5,6 +5,10 @@
|
|
package org.chromium.chrome.browser.toolbar.bottom;
|
|
|
|
import android.app.Activity;
|
|
+import org.chromium.base.supplier.ObservableSupplier;
|
|
+import org.chromium.chrome.browser.theme.TopUiThemeColorProvider;
|
|
+import org.chromium.chrome.browser.tab.CurrentTabObserver;
|
|
+import org.chromium.chrome.browser.tab.Tab;
|
|
|
|
import org.chromium.base.Callback;
|
|
import org.chromium.components.browser_ui.widget.gesture.BackPressHandler;
|
|
@@ -26,11 +30,14 @@ public interface BottomControlsContentDelegate extends BackPressHandler {
|
|
* @param activity Activity for the delegate.
|
|
* @param visibilityController Bottom controls visibility controller.
|
|
* @param onModelTokenChange Callback to notify when a new capture is needed.
|
|
+ * @param topUiThemeColorProvider {@link ThemeColorProvider} for top UI.
|
|
+ * @param tabSupplier Activity tab supplier.
|
|
*/
|
|
void initializeWithNative(
|
|
Activity activity,
|
|
BottomControlsCoordinator.BottomControlsVisibilityController visibilityController,
|
|
- Callback<Object> onModelTokenChange);
|
|
+ Callback<Object> onModelTokenChange,
|
|
+ TopUiThemeColorProvider topUiThemeColorProvider, ObservableSupplier<Tab> tabSupplier);
|
|
|
|
/** Destroy the delegate. */
|
|
void destroy();
|
|
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java
|
|
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java
|
|
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java
|
|
@@ -31,6 +31,8 @@ import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
|
|
import org.chromium.ui.resources.ResourceManager;
|
|
import org.chromium.ui.resources.dynamics.ViewResourceAdapter;
|
|
import org.chromium.ui.widget.Toast;
|
|
+import org.chromium.chrome.browser.theme.TopUiThemeColorProvider;
|
|
+import org.chromium.chrome.browser.tab.Tab;
|
|
|
|
/**
|
|
* The root coordinator for the bottom controls component. This component is intended for use with
|
|
@@ -80,6 +82,8 @@ public class BottomControlsCoordinator implements BackPressHandler {
|
|
* @param constraintsSupplier Used to access current constraints of the browser controls.
|
|
* @param readAloudRestoringSupplier Supplier that returns true if Read Aloud is currently
|
|
* restoring its player, e.g. after theme change.
|
|
+ * @param topUiThemeColorProvider {@link ThemeColorProvider} for top UI.
|
|
+ * @param tabSupplier Activity tab supplier.
|
|
*/
|
|
@SuppressLint("CutPasteId") // Not actually cut and paste since it's View vs ViewGroup.
|
|
public BottomControlsCoordinator(
|
|
@@ -95,7 +99,9 @@ public class BottomControlsCoordinator implements BackPressHandler {
|
|
TabObscuringHandler tabObscuringHandler,
|
|
ObservableSupplier<Boolean> overlayPanelVisibilitySupplier,
|
|
ObservableSupplier<Integer> constraintsSupplier,
|
|
- Supplier<Boolean> readAloudRestoringSupplier) {
|
|
+ Supplier<Boolean> readAloudRestoringSupplier,
|
|
+ TopUiThemeColorProvider topUiThemeColorProvider,
|
|
+ ObservableSupplier<Tab> tabSupplier) {
|
|
mRootFrameLayout = root;
|
|
root.setConstraintsSupplier(constraintsSupplier);
|
|
PropertyModel model = new PropertyModel(BottomControlsProperties.ALL_KEYS);
|
|
@@ -155,7 +161,8 @@ public class BottomControlsCoordinator implements BackPressHandler {
|
|
mMediator.setBottomControlsColor(color);
|
|
}
|
|
},
|
|
- root::onModelTokenChange);
|
|
+ root::onModelTokenChange,
|
|
+ topUiThemeColorProvider, tabSupplier);
|
|
mContentDelegateWrapper.set(contentDelegate);
|
|
});
|
|
}
|
|
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsMediator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsMediator.java
|
|
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsMediator.java
|
|
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsMediator.java
|
|
@@ -25,6 +25,7 @@ import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeSupplier.ChangeObse
|
|
import org.chromium.ui.KeyboardVisibilityDelegate;
|
|
import org.chromium.ui.base.WindowAndroid;
|
|
import org.chromium.ui.modelutil.PropertyModel;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
|
|
/**
|
|
* This class is responsible for reacting to events from the outside world, interacting with other
|
|
@@ -148,6 +149,12 @@ class BottomControlsMediator
|
|
}
|
|
|
|
void setBottomControlsVisible(boolean visible) {
|
|
+ if (visible == true
|
|
+ && mIsBottomControlsVisible == false
|
|
+ && ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // always show the toolbar if the bottom controls are visible, so as not to leave the hole below.
|
|
+ mBottomControlsStacker.getBrowserControls().getBrowserVisibilityDelegate().showControlsTransient();
|
|
+ }
|
|
mIsBottomControlsVisible = visible;
|
|
updateCompositedViewVisibility();
|
|
updateAndroidViewVisibility();
|
|
@@ -182,6 +189,7 @@ class BottomControlsMediator
|
|
int bottomControlsMinHeightOffset,
|
|
boolean needsAnimate,
|
|
boolean isVisibilityForced) {
|
|
+ mModel.set(BottomControlsProperties.TOPCONTROLSMINHEIGHT_OFFSET, topControlsMinHeightOffset);
|
|
// Method call routed to onBrowserControlsOffsetUpdate.
|
|
if (BottomControlsStacker.isDispatchingYOffset()) return;
|
|
|
|
@@ -303,10 +311,12 @@ class BottomControlsMediator
|
|
&& !mIsInSwipeLayout
|
|
&& getBrowserControls().getBottomControlOffset() == 0;
|
|
if (visible) {
|
|
- // Translate view so that its bottom is aligned with browser controls min height.
|
|
- mModel.set(
|
|
- BottomControlsProperties.ANDROID_VIEW_TRANSLATE_Y,
|
|
- -getBrowserControls().getBottomControlsMinHeight());
|
|
+ if (!ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // Translate view so that its bottom is aligned with browser controls min height.
|
|
+ mModel.set(
|
|
+ BottomControlsProperties.ANDROID_VIEW_TRANSLATE_Y,
|
|
+ -getBrowserControls().getBottomControlsMinHeight());
|
|
+ }
|
|
}
|
|
mModel.set(BottomControlsProperties.ANDROID_VIEW_VISIBLE, visible);
|
|
}
|
|
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsProperties.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsProperties.java
|
|
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsProperties.java
|
|
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsProperties.java
|
|
@@ -22,6 +22,9 @@ class BottomControlsProperties {
|
|
*/
|
|
static final WritableIntPropertyKey ANDROID_VIEW_TRANSLATE_Y = new WritableIntPropertyKey();
|
|
|
|
+ /** The min height of browser controls in px. */
|
|
+ static final WritableIntPropertyKey TOPCONTROLSMINHEIGHT_OFFSET = new WritableIntPropertyKey();
|
|
+
|
|
/** Whether the Android view version of the bottom controls component is visible. */
|
|
static final WritableBooleanPropertyKey ANDROID_VIEW_VISIBLE = new WritableBooleanPropertyKey();
|
|
|
|
@@ -40,6 +43,7 @@ class BottomControlsProperties {
|
|
ANDROID_VIEW_TRANSLATE_Y,
|
|
ANDROID_VIEW_VISIBLE,
|
|
COMPOSITED_VIEW_VISIBLE,
|
|
- IS_OBSCURED
|
|
+ IS_OBSCURED,
|
|
+ TOPCONTROLSMINHEIGHT_OFFSET
|
|
};
|
|
}
|
|
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsViewBinder.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsViewBinder.java
|
|
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsViewBinder.java
|
|
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsViewBinder.java
|
|
@@ -53,6 +53,8 @@ class BottomControlsViewBinder {
|
|
view.sceneLayer.setYOffset(model.get(BottomControlsProperties.Y_OFFSET));
|
|
} else if (BottomControlsProperties.ANDROID_VIEW_TRANSLATE_Y == propertyKey) {
|
|
view.root.setTranslationY(model.get(BottomControlsProperties.ANDROID_VIEW_TRANSLATE_Y));
|
|
+ } else if (BottomControlsProperties.TOPCONTROLSMINHEIGHT_OFFSET == propertyKey) {
|
|
+ view.sceneLayer.setTopControlsMinHeightOffset(model.get(BottomControlsProperties.TOPCONTROLSMINHEIGHT_OFFSET));
|
|
} else if (BottomControlsProperties.ANDROID_VIEW_VISIBLE == propertyKey
|
|
|| BottomControlsProperties.COMPOSITED_VIEW_VISIBLE == propertyKey) {
|
|
final boolean showAndroidView =
|
|
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewSceneLayer.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewSceneLayer.java
|
|
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewSceneLayer.java
|
|
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewSceneLayer.java
|
|
@@ -20,6 +20,8 @@ import org.chromium.ui.resources.ResourceManager;
|
|
|
|
import java.util.List;
|
|
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
+
|
|
/**
|
|
* A composited view that sits at the bottom of the screen and listens to changes in the browser
|
|
* controls. When visible, the view will mimic the behavior of the top browser controls when
|
|
@@ -39,6 +41,9 @@ public class ScrollingBottomViewSceneLayer extends SceneOverlayLayer implements
|
|
/** The current Y offset of the bottom view in px. */
|
|
private int mCurrentYOffsetPx;
|
|
|
|
+ /** The min height of browser controls in px. */
|
|
+ private int mTopControlsMinHeightOffset;
|
|
+
|
|
/** The current X offset of the bottom view in px. */
|
|
private int mCurrentXOffsetPx;
|
|
|
|
@@ -86,6 +91,13 @@ public class ScrollingBottomViewSceneLayer extends SceneOverlayLayer implements
|
|
mCurrentXOffsetPx = offsetPx;
|
|
}
|
|
|
|
+ /**
|
|
+ * @param offsetPx The min height of browser controls in px.
|
|
+ */
|
|
+ public void setTopControlsMinHeightOffset(int offsetPx) {
|
|
+ mTopControlsMinHeightOffset = offsetPx;
|
|
+ }
|
|
+
|
|
/**
|
|
* @param visible Whether this {@link SceneLayer} is visible.
|
|
*/
|
|
@@ -114,6 +126,11 @@ public class ScrollingBottomViewSceneLayer extends SceneOverlayLayer implements
|
|
// The composited shadow should be visible if the Android toolbar's isn't.
|
|
boolean isShadowVisible = mBottomView.getVisibility() != View.VISIBLE;
|
|
|
|
+ float offsetPy = viewport.height() + mCurrentYOffsetPx;
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // fix the offset of the fake bottom controls, used only for animations
|
|
+ offsetPy -= (mBottomView.getHeight() - mCurrentYOffsetPx + mTopControlsMinHeightOffset);
|
|
+ }
|
|
ScrollingBottomViewSceneLayerJni.get()
|
|
.updateScrollingBottomViewLayer(
|
|
mNativePtr,
|
|
@@ -122,7 +139,7 @@ public class ScrollingBottomViewSceneLayer extends SceneOverlayLayer implements
|
|
mResourceId,
|
|
mTopShadowHeightPx,
|
|
mCurrentXOffsetPx,
|
|
- viewport.height() + mCurrentYOffsetPx,
|
|
+ offsetPy,
|
|
isShadowVisible);
|
|
|
|
return this;
|
|
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java
|
|
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java
|
|
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java
|
|
@@ -62,6 +62,10 @@ import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
import java.util.function.BooleanSupplier;
|
|
|
|
+import android.view.Gravity;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
|
+
|
|
/** Layout for the browser controls (omnibox, menu, tab strip, etc..). */
|
|
public class ToolbarControlContainer extends OptimizedFrameLayout
|
|
implements ControlContainer, DesktopWindowStateProvider.AppHeaderObserver {
|
|
@@ -143,6 +147,11 @@ public class ToolbarControlContainer extends OptimizedFrameLayout
|
|
if (view != null)
|
|
((MarginLayoutParams)view.getLayoutParams()).topMargin = tab_strip_height;
|
|
}
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // the top toolbar is docked at the bottom
|
|
+ CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams)getLayoutParams();
|
|
+ layoutParams.gravity = Gravity.START | Gravity.BOTTOM;
|
|
+ }
|
|
mToolbarContainer =
|
|
(ToolbarViewResourceFrameLayout) findViewById(R.id.toolbar_container);
|
|
ViewStub toolbarStub = findViewById(R.id.toolbar_stub);
|
|
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayCoordinator.java
|
|
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayCoordinator.java
|
|
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayCoordinator.java
|
|
@@ -21,11 +21,14 @@ import org.chromium.chrome.browser.tab.Tab;
|
|
import org.chromium.chrome.browser.theme.TopUiThemeColorProvider;
|
|
import org.chromium.chrome.browser.toolbar.R;
|
|
import org.chromium.components.browser_ui.widget.ClipDrawableProgressBar;
|
|
+import org.chromium.ui.base.DeviceFormFactor;
|
|
import org.chromium.ui.modelutil.PropertyModel;
|
|
import org.chromium.ui.resources.ResourceManager;
|
|
|
|
import java.util.List;
|
|
|
|
+import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
|
|
+
|
|
/** The public interface for the top toolbar texture component. */
|
|
public class TopToolbarOverlayCoordinator implements SceneOverlay {
|
|
/** The view state for this overlay. */
|
|
@@ -62,6 +65,12 @@ public class TopToolbarOverlayCoordinator implements SceneOverlay {
|
|
TopToolbarOverlayProperties.CONTENT_OFFSET,
|
|
browserControlsStateProvider.getContentOffset())
|
|
.with(TopToolbarOverlayProperties.ANONYMIZE, false)
|
|
+ .with(TopToolbarOverlayProperties.VIEWPORT_HEIGHT, 0)
|
|
+ .with(TopToolbarOverlayProperties.TOOLBAR_HEIGHT,
|
|
+ browserControlsStateProvider.getTopControlsHeight()
|
|
+ + (DeviceFormFactor.isNonMultiDisplayContextOnTablet(context)
|
|
+ ? context.getResources().getDimensionPixelSize(R.dimen.toolbar_hairline_height)
|
|
+ : -context.getResources().getDimensionPixelSize(R.dimen.toolbar_hairline_height)))
|
|
.build();
|
|
mSceneLayer = new TopToolbarSceneLayer(resourceManagerSupplier);
|
|
mChangeProcessor =
|
|
@@ -113,6 +122,7 @@ public class TopToolbarOverlayCoordinator implements SceneOverlay {
|
|
@Override
|
|
public SceneOverlayLayer getUpdatedSceneOverlayTree(
|
|
RectF viewport, RectF visibleViewport, ResourceManager resourceManager, float yOffset) {
|
|
+ mModel.set(TopToolbarOverlayProperties.VIEWPORT_HEIGHT, viewport.height());
|
|
return mSceneLayer;
|
|
}
|
|
|
|
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayProperties.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayProperties.java
|
|
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayProperties.java
|
|
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayProperties.java
|
|
@@ -51,6 +51,12 @@ public class TopToolbarOverlayProperties {
|
|
public static final WritableObjectPropertyKey<OffsetTag> TOOLBAR_OFFSET_TAG =
|
|
new WritableObjectPropertyKey<>();
|
|
|
|
+ /** The current height of the main visible view. */
|
|
+ public static final WritableFloatPropertyKey VIEWPORT_HEIGHT = new WritableFloatPropertyKey();
|
|
+
|
|
+ /** The current height of the top toolbar. */
|
|
+ public static final WritableFloatPropertyKey TOOLBAR_HEIGHT = new WritableFloatPropertyKey();
|
|
+
|
|
public static final PropertyKey[] ALL_KEYS =
|
|
new PropertyKey[] {
|
|
ANONYMIZE,
|
|
@@ -64,5 +70,5 @@ public class TopToolbarOverlayProperties {
|
|
X_OFFSET,
|
|
CONTENT_OFFSET,
|
|
TOOLBAR_OFFSET_TAG
|
|
- };
|
|
+ , VIEWPORT_HEIGHT, TOOLBAR_HEIGHT};
|
|
}
|
|
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarSceneLayer.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarSceneLayer.java
|
|
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarSceneLayer.java
|
|
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarSceneLayer.java
|
|
@@ -15,6 +15,7 @@ import org.chromium.components.browser_ui.widget.ClipDrawableProgressBar.Drawing
|
|
import org.chromium.ui.modelutil.PropertyKey;
|
|
import org.chromium.ui.modelutil.PropertyModel;
|
|
import org.chromium.ui.resources.ResourceManager;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
|
|
/** A SceneLayer to render the top toolbar. This is the "view" piece of the top toolbar overlay. */
|
|
@JNINamespace("android")
|
|
@@ -40,6 +41,13 @@ class TopToolbarSceneLayer extends SceneOverlayLayer {
|
|
/** Push all information about the texture to native at once. */
|
|
private void pushProperties(PropertyModel model) {
|
|
if (mResourceManagerSupplier.get() == null) return;
|
|
+ float offsetY = model.get(TopToolbarOverlayProperties.CONTENT_OFFSET);
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // fix the offset of the fake top controls, used only for animations
|
|
+ offsetY = model.get(TopToolbarOverlayProperties.VIEWPORT_HEIGHT) -
|
|
+ model.get(TopToolbarOverlayProperties.TOOLBAR_HEIGHT) -
|
|
+ offsetY;
|
|
+ }
|
|
TopToolbarSceneLayerJni.get()
|
|
.updateToolbarLayer(
|
|
mNativePtr,
|
|
@@ -50,7 +58,7 @@ class TopToolbarSceneLayer extends SceneOverlayLayer {
|
|
model.get(TopToolbarOverlayProperties.URL_BAR_RESOURCE_ID),
|
|
model.get(TopToolbarOverlayProperties.URL_BAR_COLOR),
|
|
model.get(TopToolbarOverlayProperties.X_OFFSET),
|
|
- model.get(TopToolbarOverlayProperties.CONTENT_OFFSET),
|
|
+ offsetY,
|
|
model.get(TopToolbarOverlayProperties.SHOW_SHADOW),
|
|
model.get(TopToolbarOverlayProperties.VISIBLE),
|
|
model.get(TopToolbarOverlayProperties.ANONYMIZE),
|
|
diff --git a/components/browser_ui/accessibility/android/java/res/xml/accessibility_preferences.xml b/components/browser_ui/accessibility/android/java/res/xml/accessibility_preferences.xml
|
|
--- a/components/browser_ui/accessibility/android/java/res/xml/accessibility_preferences.xml
|
|
+++ b/components/browser_ui/accessibility/android/java/res/xml/accessibility_preferences.xml
|
|
@@ -60,4 +60,12 @@ found in the LICENSE file.
|
|
android:key="image_descriptions"
|
|
android:title="@string/image_descriptions_settings_title" />
|
|
|
|
+ <org.chromium.components.browser_ui.settings.ChromeSwitchPreference
|
|
+ android:key="move_toolbar_bottom"
|
|
+ android:title="@string/move_toolbar_bottom_title" />
|
|
+
|
|
+ <org.chromium.components.browser_ui.settings.ChromeSwitchPreference
|
|
+ android:key="disable_toolbar_swipeup"
|
|
+ android:title="@string/disable_toolbar_swipe_up" />
|
|
+
|
|
</PreferenceScreen>
|
|
diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettingsDelegate.java b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettingsDelegate.java
|
|
--- a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettingsDelegate.java
|
|
+++ b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettingsDelegate.java
|
|
@@ -4,6 +4,8 @@
|
|
|
|
package org.chromium.components.browser_ui.accessibility;
|
|
|
|
+import android.app.Activity;
|
|
+
|
|
import org.chromium.content_public.browser.BrowserContextHandle;
|
|
|
|
/**
|
|
@@ -32,6 +34,11 @@ public interface AccessibilitySettingsDelegate {
|
|
void setValue(int value);
|
|
}
|
|
|
|
+ void requestRestart(Activity activity);
|
|
+
|
|
+ BooleanPreferenceDelegate getMoveTopToolbarToBottomDelegate();
|
|
+ BooleanPreferenceDelegate getDisableToolbarSwipeUpDelegate();
|
|
+
|
|
/** @return The BrowserContextHandle that should be used to read and update settings. */
|
|
BrowserContextHandle getBrowserContextHandle();
|
|
|
|
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
|
|
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
|
|
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
|
|
@@ -26,6 +26,7 @@
|
|
#include "base/task/single_thread_task_runner.h"
|
|
#include "base/task/thread_pool.h"
|
|
#include "base/threading/scoped_blocking_call.h"
|
|
+#include "cc/base/features.h"
|
|
#include "cc/base/math_util.h"
|
|
#include "cc/input/browser_controls_offset_tags_info.h"
|
|
#include "cc/slim/layer.h"
|
|
@@ -857,6 +858,8 @@ void RenderWidgetHostViewAndroid::OnRenderFrameMetadataChangedBeforeActivation(
|
|
// factor. Thus, |top_content_offset| in CSS pixels is also in DIPs.
|
|
float top_content_offset =
|
|
metadata.top_controls_height * metadata.top_controls_shown_ratio;
|
|
+ if (base::FeatureList::IsEnabled(::features::kMoveTopToolbarToBottom))
|
|
+ top_content_offset = 0;
|
|
float top_shown_pix = top_content_offset;
|
|
|
|
if (ime_adapter_android_) {
|
|
diff --git a/cromite_flags/chrome/browser/about_flags_cc/Move-navigation-bar-to-bottom.inc b/cromite_flags/chrome/browser/about_flags_cc/Move-navigation-bar-to-bottom.inc
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/cromite_flags/chrome/browser/about_flags_cc/Move-navigation-bar-to-bottom.inc
|
|
@@ -0,0 +1,17 @@
|
|
+#if BUILDFLAG(IS_ANDROID)
|
|
+
|
|
+#ifdef FLAG_SECTION
|
|
+
|
|
+ {"move-top-toolbar-to-bottom",
|
|
+ "Move top toolbar to bottom",
|
|
+ "Move the top toolbar to the bottom.", kOsAndroid,
|
|
+ FEATURE_VALUE_TYPE(features::kMoveTopToolbarToBottom)},
|
|
+
|
|
+ {"disable-toolbar-swipe-up",
|
|
+ "Disable toolbar swipe up",
|
|
+ "Disable toolbar swipe up.", kOsAndroid,
|
|
+ FEATURE_VALUE_TYPE(features::kDisableToolbarSwipeUp)},
|
|
+
|
|
+#endif
|
|
+
|
|
+#endif
|
|
--
|