2890 lines
154 KiB
Diff
2890 lines
154 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 | 4 +
|
|
cc/base/features.h | 1 +
|
|
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 | 50 +++++++++-
|
|
.../tab_management/TabGroupUiProperties.java | 7 +-
|
|
.../tab_management/TabGroupUiToolbarView.java | 17 ++++
|
|
.../tab_management/TabGroupUiViewBinder.java | 3 +
|
|
.../TabListContainerViewBinder.java | 15 ++-
|
|
.../tab_management/TabListCoordinator.java | 95 ++++++++++++++++++-
|
|
.../tab_management/TabListRecyclerView.java | 19 +++-
|
|
.../tab_management/TabSwitcherMediator.java | 27 +++++-
|
|
.../ChromeAccessibilitySettingsDelegate.java | 50 ++++++++++
|
|
.../chrome/browser/app/ChromeActivity.java | 13 +++
|
|
.../compositor/CompositorViewHolder.java | 8 ++
|
|
.../layouts/LayoutManagerChrome.java | 17 +++-
|
|
.../layouts/LayoutManagerChromeTablet.java | 4 +-
|
|
.../layouts/ToolbarSwipeLayout.java | 14 ++-
|
|
.../overlays/strip/StripLayoutHelper.java | 2 +-
|
|
.../strip/StripLayoutHelperManager.java | 35 ++++++-
|
|
.../scene_layer/StaticTabSceneLayer.java | 7 +-
|
|
.../scene_layer/TabListSceneLayer.java | 8 ++
|
|
.../scene_layer/TabStripSceneLayer.java | 22 ++++-
|
|
.../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 | 8 ++
|
|
.../chrome/browser/ntp/RecentTabsPage.java | 21 +++-
|
|
.../browser/searchwidget/SearchActivity.java | 12 ++-
|
|
.../browser/settings/SettingsActivity.java | 5 +
|
|
.../StatusIndicatorCoordinator.java | 9 ++
|
|
.../StatusIndicatorSceneLayer.java | 6 +-
|
|
.../browser/toolbar/ToolbarManager.java | 46 ++++++++-
|
|
.../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 +++-
|
|
.../BrowserControlsMarginSupplier.java | 5 +
|
|
.../BrowserControlsStateProvider.java | 6 ++
|
|
.../browser/feed/FeedListContentManager.java | 6 +-
|
|
.../flags/android/chrome_feature_list.cc | 2 +
|
|
.../browser/flags/ChromeFeatureList.java | 5 +
|
|
chrome/browser/prefs/browser_prefs.cc | 2 +-
|
|
.../chrome/browser/ui/appmenu/AppMenu.java | 40 +++++++-
|
|
.../ui/appmenu/AppMenuHandlerImpl.java | 10 ++
|
|
.../omnibox/LocationBarCoordinator.java | 7 +-
|
|
...mniboxSuggestionsDropdownEmbedderImpl.java | 24 ++++-
|
|
.../suggestions/AutocompleteCoordinator.java | 16 +++-
|
|
.../suggestions/AutocompleteMediator.java | 6 +-
|
|
.../DropdownItemViewInfoListManager.java | 13 ++-
|
|
.../OmniboxSuggestionsDropdown.java | 39 +++++++-
|
|
.../OmniboxSuggestionsDropdownEmbedder.java | 8 ++
|
|
.../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 | 8 ++
|
|
.../bottom/BottomControlsProperties.java | 6 +-
|
|
.../bottom/BottomControlsViewBinder.java | 2 +
|
|
.../bottom/ScrollingBottomViewSceneLayer.java | 19 +++-
|
|
.../toolbar/top/ToolbarControlContainer.java | 10 ++
|
|
.../top/TopToolbarOverlayCoordinator.java | 6 ++
|
|
.../top/TopToolbarOverlayProperties.java | 8 +-
|
|
.../toolbar/top/TopToolbarSceneLayer.java | 10 +-
|
|
.../res/xml/accessibility_preferences.xml | 4 +
|
|
.../accessibility/AccessibilitySettings.java | 15 +++
|
|
.../AccessibilitySettingsDelegate.java | 6 ++
|
|
.../render_widget_host_view_android.cc | 3 +
|
|
.../Move-navigation-bar-to-bottom.inc | 12 +++
|
|
74 files changed, 899 insertions(+), 83 deletions(-)
|
|
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
|
|
@@ -36,6 +36,10 @@ BASE_FEATURE(kSynchronizedScrolling,
|
|
base::FEATURE_ENABLED_BY_DEFAULT);
|
|
#endif
|
|
|
|
+BASE_FEATURE(kMoveTopToolbarToBottom,
|
|
+ "MoveTopToolbarToBottom",
|
|
+ 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
|
|
@@ -15,6 +15,7 @@ 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);
|
|
|
|
// 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
|
|
@@ -17,6 +17,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 {
|
|
@@ -484,6 +485,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
|
|
@@ -4287,6 +4287,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
|
|
@@ -113,6 +113,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 TabSwitcher.TabSwitcherViewObserver,
|
|
@@ -1467,6 +1469,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
|
|
@@ -41,6 +41,7 @@ import org.chromium.components.feature_engagement.FeatureConstants;
|
|
import org.chromium.ui.modelutil.PropertyModel;
|
|
import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
|
|
import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
|
|
+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")) {
|
|
@@ -216,7 +218,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
|
|
@@ -48,6 +48,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. */
|
|
@@ -113,6 +119,11 @@ public class TabGroupUiMediator implements BackPressHandler {
|
|
private boolean mIsTabGroupUiVisible;
|
|
private boolean mIsShowingOverViewMode;
|
|
|
|
+ private final TopUiThemeColorProvider mTopUiThemeColorProvider;
|
|
+
|
|
+ /** An observer that watches for changes in the active tab. */
|
|
+ private final CurrentTabObserver mTabObserver;
|
|
+
|
|
TabGroupUiMediator(
|
|
Context context,
|
|
BottomControlsVisibilityController visibilityController,
|
|
@@ -125,7 +136,9 @@ public class TabGroupUiMediator implements BackPressHandler {
|
|
@Nullable
|
|
LazyOneshotSupplier<TabGridDialogMediator.DialogController>
|
|
dialogControllerSupplier,
|
|
- ObservableSupplier<Boolean> omniboxFocusStateSupplier) {
|
|
+ ObservableSupplier<Boolean> omniboxFocusStateSupplier,
|
|
+ TopUiThemeColorProvider topUiThemeColorProvider, ObservableSupplier<Tab> tabSupplier) {
|
|
+ mTopUiThemeColorProvider = topUiThemeColorProvider;
|
|
mContext = context;
|
|
mResetHandler = resetHandler;
|
|
mModel = model;
|
|
@@ -147,11 +160,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;
|
|
}
|
|
@@ -213,6 +245,7 @@ public class TabGroupUiMediator implements BackPressHandler {
|
|
return;
|
|
}
|
|
resetTabStripWithRelatedTabsForId(currentTab.getId());
|
|
+ updateThemeColor(currentTab);
|
|
}
|
|
|
|
@Override
|
|
@@ -338,6 +371,8 @@ public class TabGroupUiMediator implements BackPressHandler {
|
|
resetTabStripWithRelatedTabsForId(tab.getId());
|
|
}
|
|
|
|
+ mTabObserver.triggerWithCurrentTab();
|
|
+
|
|
mBackPressStateSupplier = new ObservableSupplierImpl<>();
|
|
if (mTabGridDialogControllerSupplier != null) {
|
|
mTabGridDialogControllerSupplier.onAvailable(
|
|
@@ -353,6 +388,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);
|
|
}
|
|
@@ -478,6 +525,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 {
|
|
@@ -34,6 +35,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,
|
|
@@ -43,6 +47,7 @@ class TabGroupUiProperties {
|
|
LEFT_BUTTON_DRAWABLE_ID,
|
|
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
|
|
@@ -28,6 +28,10 @@ import org.chromium.components.browser_ui.styles.SemanticColorUtils;
|
|
import org.chromium.ui.KeyboardVisibilityDelegate;
|
|
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;
|
|
+
|
|
/**
|
|
* Represents a generic toolbar used in the bottom strip/grid component.
|
|
* {@link TabGridPanelToolbarCoordinator}
|
|
@@ -173,6 +177,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
|
|
+ setPrimaryColor(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
|
|
@@ -12,6 +12,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;
|
|
|
|
@@ -68,6 +69,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/TabListContainerViewBinder.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinder.java
|
|
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinder.java
|
|
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinder.java
|
|
@@ -34,6 +34,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
|
|
|
import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
|
|
import org.chromium.chrome.browser.hub.HubFieldTrial;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
import org.chromium.chrome.browser.tab.TabUtils;
|
|
import org.chromium.chrome.browser.theme.ThemeUtils;
|
|
import org.chromium.components.browser_ui.styles.ChromeColors;
|
|
@@ -103,13 +104,21 @@ class TabListContainerViewBinder {
|
|
final int oldTopMargin = params.topMargin;
|
|
final int oldBottomMargin = params.bottomMargin;
|
|
if (model.get(IS_VISIBLE)) {
|
|
- params.topMargin = model.get(TOP_MARGIN);
|
|
- params.bottomMargin = model.get(BOTTOM_CONTROLS_HEIGHT);
|
|
+ if (!ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ params.topMargin = model.get(TOP_MARGIN);
|
|
+ params.bottomMargin = model.get(BOTTOM_CONTROLS_HEIGHT);
|
|
+ } else {
|
|
+ params.topMargin = 0;
|
|
+ params.bottomMargin = model.get(TOP_MARGIN) +
|
|
+ model.get(BOTTOM_CONTROLS_HEIGHT);
|
|
+ }
|
|
} else {
|
|
// Treat the bottom margin as 0 to avoid layout shift in tab shrink animations.
|
|
// IS_VISIBLE will be set to true after the tab shrink animation see
|
|
// {@link TabSwitcherMediator#showTabSwitcherView(boolean)}.
|
|
- params.bottomMargin = 0;
|
|
+ if (!ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ params.bottomMargin = 0;
|
|
+ }
|
|
|
|
// Leave the top margin unchanged to avoid relayouts during scrolls and for top
|
|
// toolbar indicators while the view is not visible. Once visible the offset will
|
|
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
|
|
@@ -8,6 +8,7 @@ import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.Card
|
|
|
|
import android.app.Activity;
|
|
import android.content.Context;
|
|
+import android.content.res.Configuration;
|
|
import android.content.res.Resources;
|
|
import android.graphics.Bitmap;
|
|
import android.graphics.BitmapFactory;
|
|
@@ -56,6 +57,8 @@ import org.chromium.ui.modelutil.SimpleRecyclerViewAdapter;
|
|
import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
|
|
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;
|
|
@@ -113,6 +116,75 @@ public class TabListCoordinator
|
|
private @Nullable Runnable mAwaitingLayoutRunnable;
|
|
private int mAwaitingTabId = Tab.INVALID_TAB_ID;
|
|
|
|
+ public class GridLayoutManagerDockBottom extends GridLayoutManager {
|
|
+ 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());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
/**
|
|
* Construct a coordinator for UI that shows a list of tabs.
|
|
*
|
|
@@ -393,6 +465,12 @@ public class TabListCoordinator
|
|
checkAwaitingLayout();
|
|
}
|
|
};
|
|
+ if (titleProvider != null && ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ gridLayoutManager =
|
|
+ new GridLayoutManagerDockBottom(context, GRID_LAYOUT_SPAN_COUNT_COMPACT);
|
|
+ ((GridLayoutManagerDockBottom)gridLayoutManager)
|
|
+ .setTabListRecyclerView(mRecyclerView);
|
|
+ }
|
|
mRecyclerView.setLayoutManager(gridLayoutManager);
|
|
mMediator.registerOrientationListener(gridLayoutManager);
|
|
mMediator.updateSpanCount(
|
|
@@ -404,8 +482,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,
|
|
@@ -420,6 +497,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);
|
|
}
|
|
@@ -726,6 +814,9 @@ public class TabListCoordinator
|
|
void prepareTabSwitcherView() {
|
|
registerLayoutChangeListener();
|
|
mRecyclerView.prepareTabSwitcherView();
|
|
+ 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/TabListRecyclerView.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java
|
|
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java
|
|
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java
|
|
@@ -41,6 +41,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
|
|
|
import org.chromium.base.Log;
|
|
import org.chromium.chrome.browser.hub.HubFieldTrial;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
import org.chromium.chrome.browser.tabmodel.TabModel;
|
|
import org.chromium.chrome.tab_ui.R;
|
|
import org.chromium.ui.base.ViewUtils;
|
|
@@ -68,6 +69,8 @@ class TabListRecyclerView extends RecyclerView
|
|
public static final long BASE_ANIMATION_DURATION_MS = 218;
|
|
public static final long FINAL_FADE_IN_DURATION_MS = 50;
|
|
|
|
+ private boolean mIsVisible = false;
|
|
+
|
|
/** An interface to listen to visibility related changes on this {@link RecyclerView}. */
|
|
interface VisibilityListener {
|
|
/**
|
|
@@ -285,6 +288,7 @@ class TabListRecyclerView extends RecyclerView
|
|
? FINAL_FADE_IN_DURATION_MS
|
|
: BASE_ANIMATION_DURATION_MS;
|
|
|
|
+ mIsVisible = true;
|
|
setAlpha(0);
|
|
setVisibility(View.VISIBLE);
|
|
mFadeInAnimator = ObjectAnimator.ofFloat(this, View.ALPHA, 1);
|
|
@@ -337,6 +341,11 @@ class TabListRecyclerView extends RecyclerView
|
|
}
|
|
|
|
void setShadowVisibility(boolean shouldShowShadow) {
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()
|
|
+ && mIsVisible) {
|
|
+ // always show shadow
|
|
+ shouldShowShadow = true;
|
|
+ }
|
|
if (mShadowImageView == null) {
|
|
Context context = getContext();
|
|
mShadowImageView = new ImageView(context);
|
|
@@ -350,7 +359,10 @@ class TabListRecyclerView extends RecyclerView
|
|
// Add shadow for grid tab switcher.
|
|
FrameLayout.LayoutParams params =
|
|
new FrameLayout.LayoutParams(
|
|
- LayoutParams.MATCH_PARENT, shadowHeight, Gravity.TOP);
|
|
+ LayoutParams.MATCH_PARENT, shadowHeight,
|
|
+ (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled() ?
|
|
+ Gravity.BOTTOM :
|
|
+ Gravity.TOP));
|
|
mShadowImageView.setLayoutParams(params);
|
|
mShadowImageView.setTranslationY(mShadowTopOffset);
|
|
FrameLayout parent = (FrameLayout) getParent();
|
|
@@ -379,6 +391,10 @@ class TabListRecyclerView extends RecyclerView
|
|
|
|
void setShadowTopOffset(int shadowTopOffset) {
|
|
mShadowTopOffset = shadowTopOffset;
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // invert the offset since Gravity is set to BOTTOM
|
|
+ mShadowTopOffset = -mShadowTopOffset;
|
|
+ }
|
|
|
|
if (mShadowImageView != null && getParent() instanceof FrameLayout) {
|
|
// Since the shadow has no functionality, other than just existing visually, we can use
|
|
@@ -572,6 +588,7 @@ class TabListRecyclerView extends RecyclerView
|
|
mListener.finishedHiding();
|
|
}
|
|
});
|
|
+ mIsVisible = false;
|
|
setShadowVisibility(false);
|
|
mFadeOutAnimator.start();
|
|
if (!animate) mFadeOutAnimator.end();
|
|
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
|
|
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
|
|
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
|
|
@@ -407,7 +407,10 @@ class TabSwitcherMediator
|
|
@Override
|
|
public void onBottomControlsHeightChanged(
|
|
int bottomControlsHeight, int bottomControlsMinHeight) {
|
|
- mContainerViewModel.set(BOTTOM_CONTROLS_HEIGHT, bottomControlsHeight);
|
|
+ mContainerViewModel.set(BOTTOM_CONTROLS_HEIGHT, bottomControlsHeight +
|
|
+ (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled() && mMode == TabListCoordinator.TabListMode.LIST
|
|
+ ? mBrowserControlsStateProvider.getContentOffset()
|
|
+ : 0));
|
|
}
|
|
};
|
|
|
|
@@ -450,11 +453,21 @@ class TabSwitcherMediator
|
|
updateTopControlsProperties();
|
|
mContainerViewModel.set(
|
|
BOTTOM_CONTROLS_HEIGHT, browserControlsStateProvider.getBottomControlsHeight());
|
|
-
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ mContainerViewModel.set(
|
|
+ BOTTOM_CONTROLS_HEIGHT, mContainerViewModel.get(BOTTOM_CONTROLS_HEIGHT) +
|
|
+ mBrowserControlsStateProvider.getContentOffset());
|
|
+ }
|
|
if (mMode == TabListMode.GRID) {
|
|
mContainerViewModel.set(
|
|
BOTTOM_PADDING,
|
|
(int) context.getResources().getDimension(R.dimen.tab_grid_bottom_padding));
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // adjust the bottom margin so as not to cover the top toolbar at the bottom
|
|
+ mContainerViewModel.set(
|
|
+ BOTTOM_PADDING, mContainerViewModel.get(BOTTOM_PADDING) +
|
|
+ mBrowserControlsStateProvider.getContentOffset());
|
|
+ }
|
|
if (backPressManager != null && BackPressManager.isEnabled()) {
|
|
assert !mIsStartSurfaceEnabled || mIsStartSurfaceRefactorEnabled;
|
|
backPressManager.addHandler(this, BackPressHandler.Type.TAB_SWITCHER);
|
|
@@ -522,8 +535,10 @@ class TabSwitcherMediator
|
|
|
|
// The grid tab switcher for tablets translates up over top of the browser controls.
|
|
if (mIsTablet) {
|
|
- final int toolbarHeight = getToolbarHeight();
|
|
-
|
|
+ int toolbarHeight = getToolbarHeight();
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ toolbarHeight = 0;
|
|
+ }
|
|
mContainerViewModel.set(TOP_MARGIN, toolbarHeight);
|
|
mContainerViewModel.set(SHADOW_TOP_OFFSET, toolbarHeight);
|
|
return;
|
|
@@ -532,6 +547,10 @@ class TabSwitcherMediator
|
|
final int contentOffset = mBrowserControlsStateProvider.getContentOffset();
|
|
|
|
mContainerViewModel.set(TOP_MARGIN, contentOffset);
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // move the view up since the toolbar is at the bottom
|
|
+ mContainerViewModel.set(TOP_MARGIN, 0);
|
|
+ }
|
|
mContainerViewModel.set(SHADOW_TOP_OFFSET, contentOffset);
|
|
}
|
|
|
|
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
|
|
@@ -28,6 +28,12 @@ import org.chromium.chrome.browser.flags.CromiteNativeUtils;
|
|
import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
|
|
import org.chromium.chrome.browser.preferences.ChromeSharedPreferences;
|
|
|
|
+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 ReaderForAccessibilityDelegate implements BooleanPreferenceDelegate {
|
|
@@ -69,6 +75,12 @@ public class ChromeAccessibilitySettingsDelegate implements AccessibilitySetting
|
|
}
|
|
}
|
|
|
|
+ private SnackbarManager mSnackbarManager;
|
|
+
|
|
+ public void setSnackbarManager(SnackbarManager snackbarManager) {
|
|
+ mSnackbarManager = snackbarManager;
|
|
+ }
|
|
+
|
|
private final Profile mProfile;
|
|
|
|
/**
|
|
@@ -113,6 +125,44 @@ public class ChromeAccessibilitySettingsDelegate implements AccessibilitySetting
|
|
return new ForceTabletUIDelegate();
|
|
}
|
|
|
|
+ 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);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public BooleanPreferenceDelegate getMoveTopToolbarToBottomDelegate() {
|
|
+ return new MoveTopToolbarToBottomDelegate();
|
|
+ }
|
|
+
|
|
+ @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 void addExtraPreferences(PreferenceFragmentCompat fragment) {
|
|
if (ImageDescriptionsController.getInstance().shouldShowImageDescriptionsMenuItem()) {
|
|
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.
|
|
@@ -855,6 +858,16 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
|
|
int toolbarLayoutId = getToolbarLayoutId();
|
|
if (toolbarLayoutId != ActivityUtils.NO_RESOURCE_ID && controlContainer != null) {
|
|
controlContainer.initWithToolbar(toolbarLayoutId);
|
|
+ ImageView shadowImage = findViewById(R.id.toolbar_hairline);
|
|
+ if (shadowImage != null) {
|
|
+ // Invert the shadown if the top toolbar is at the bottom
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ ViewGroup.MarginLayoutParams marginParams = (ViewGroup.MarginLayoutParams)shadowImage.getLayoutParams();
|
|
+ marginParams.setMargins(marginParams.leftMargin, 0,
|
|
+ marginParams.rightMargin, marginParams.bottomMargin);
|
|
+ shadowImage.setLayoutParams(marginParams);
|
|
+ }
|
|
+ }
|
|
}
|
|
}
|
|
onInitialLayoutInflationComplete();
|
|
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
|
|
@@ -95,6 +95,7 @@ import org.chromium.ui.base.WindowAndroid;
|
|
import org.chromium.ui.mojom.VirtualKeyboardMode;
|
|
import org.chromium.ui.resources.ResourceManager;
|
|
import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashSet;
|
|
@@ -253,6 +254,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);
|
|
}
|
|
|
|
@@ -951,6 +956,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
|
|
@@ -47,6 +47,7 @@ import org.chromium.components.browser_ui.widget.gesture.SwipeGestureListener.Sw
|
|
import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator;
|
|
import org.chromium.ui.base.DeviceFormFactor;
|
|
import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
|
|
import java.util.List;
|
|
import java.util.concurrent.Callable;
|
|
@@ -419,7 +420,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
|
|
@@ -711,9 +715,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
|
|
@@ -746,6 +752,9 @@ public class LayoutManagerChrome extends LayoutManagerImpl
|
|
&& mScrollDirection == ScrollDirection.DOWN) {
|
|
RecordUserAction.record("MobileToolbarSwipeOpenStackView");
|
|
showLayout(LayoutType.TAB_SWITCHER, true);
|
|
+ } else if (mSupportSwipeUp && isTabSwitcherReady()
|
|
+ && mScrollDirection == ScrollDirection.UP) {
|
|
+ showLayout(LayoutType.TAB_SWITCHER, true);
|
|
} else if (mScrollDirection == ScrollDirection.LEFT
|
|
|| mScrollDirection == ScrollDirection.RIGHT) {
|
|
startShowing(mToolbarSwipeLayout, true);
|
|
@@ -796,6 +805,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;
|
|
@@ -810,7 +821,7 @@ public class LayoutManagerChrome extends LayoutManagerImpl
|
|
return false;
|
|
}
|
|
|
|
- if (direction == ScrollDirection.DOWN) {
|
|
+ if (direction == ScrollDirection.DOWN || direction == ScrollDirection.UP) {
|
|
return isTabSwitcherReady();
|
|
}
|
|
|
|
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
|
|
@@ -34,6 +34,7 @@ import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator;
|
|
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;
|
|
|
|
import java.util.concurrent.Callable;
|
|
|
|
@@ -129,7 +130,8 @@ public class LayoutManagerChromeTablet extends LayoutManagerChrome {
|
|
tabContentManagerSupplier,
|
|
browserControlsStateProvider,
|
|
windowAndroid,
|
|
- toolbarManager);
|
|
+ toolbarManager,
|
|
+ /*browserControlsManagerSupplier*/ () -> getBrowserControlsManager());
|
|
addSceneOverlay(mTabStripLayoutHelperManager);
|
|
addObserver(mTabStripLayoutHelperManager.getTabSwitcherObserver());
|
|
|
|
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;
|
|
|
|
@@ -442,7 +444,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);
|
|
@@ -455,7 +461,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
|
|
@@ -559,7 +559,7 @@ public class StripLayoutHelper implements StripLayoutTab.StripLayoutTabDelegate
|
|
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
|
|
@@ -81,6 +81,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.util.List;
|
|
|
|
@@ -193,12 +195,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)) {
|
|
return;
|
|
}
|
|
@@ -221,6 +227,7 @@ public class StripLayoutHelperManager
|
|
if (DragDropGlobalState.hasValue()) {
|
|
return;
|
|
}
|
|
+ y -= mStripFilterArea.top;
|
|
mModelSelectorButton.drag(x, y);
|
|
getActiveStripLayoutHelper().drag(time(), x, y, dx);
|
|
}
|
|
@@ -230,6 +237,7 @@ public class StripLayoutHelperManager
|
|
if (DragDropGlobalState.hasValue()) {
|
|
return;
|
|
}
|
|
+ y -= mStripFilterArea.top;
|
|
long time = time();
|
|
if (mModelSelectorButton.click(x, y)) {
|
|
mModelSelectorButton.handleClick(time);
|
|
@@ -243,6 +251,7 @@ public class StripLayoutHelperManager
|
|
if (DragDropGlobalState.hasValue()) {
|
|
return;
|
|
}
|
|
+ y -= mStripFilterArea.top;
|
|
getActiveStripLayoutHelper().fling(time(), x, y, velocityX, velocityY);
|
|
}
|
|
|
|
@@ -251,6 +260,7 @@ public class StripLayoutHelperManager
|
|
if (DragDropGlobalState.hasValue()) {
|
|
return;
|
|
}
|
|
+ y -= mStripFilterArea.top;
|
|
getActiveStripLayoutHelper().onLongPress(time(), x, y);
|
|
}
|
|
|
|
@@ -352,7 +362,8 @@ public class StripLayoutHelperManager
|
|
@NonNull WindowAndroid windowAndroid,
|
|
// TODO(crbug.com/1498252): Avoid passing the ToolbarManager instance. Potentially
|
|
// implement an interface to manage strip transition states.
|
|
- @NonNull ToolbarManager toolbarManager) {
|
|
+ @NonNull ToolbarManager toolbarManager,
|
|
+ Supplier<BrowserControlsManager> browserControlsManagerSupplier) {
|
|
mUpdateHost = updateHost;
|
|
mLayerTitleCacheSupplier = layerTitleCacheSupplier;
|
|
mTabStripTreeProvider = new TabStripSceneLayer(context);
|
|
@@ -480,6 +491,8 @@ public class StripLayoutHelperManager
|
|
mTabDragSource,
|
|
toolbarContainerView,
|
|
windowAndroid);
|
|
+ mBrowserControlsManagerSupplier = browserControlsManagerSupplier;
|
|
+ mDpToPx = context.getResources().getDisplayMetrics().density;
|
|
|
|
tabHoverCardViewStub.setOnInflateListener(
|
|
(viewStub, view) -> {
|
|
@@ -621,6 +634,10 @@ public class StripLayoutHelperManager
|
|
// value.
|
|
yOffset -= getHeight();
|
|
}
|
|
+ int topControlsHeight = 0;
|
|
+ if (mBrowserControlsManagerSupplier.get() != null) {
|
|
+ topControlsHeight = mBrowserControlsManagerSupplier.get().getTopControlsHeight();
|
|
+ }
|
|
mTabStripTreeProvider.pushAndUpdateStrip(
|
|
this,
|
|
mLayerTitleCacheSupplier.get(),
|
|
@@ -630,7 +647,9 @@ public class StripLayoutHelperManager
|
|
selectedTabId,
|
|
hoveredTabId,
|
|
getStripTransitionScrimColor(),
|
|
- scrimOpacity);
|
|
+ scrimOpacity,
|
|
+ viewport.height(),
|
|
+ topControlsHeight);
|
|
return mTabStripTreeProvider;
|
|
}
|
|
|
|
@@ -674,7 +693,17 @@ public class StripLayoutHelperManager
|
|
mIncognitoHelper.onSizeChanged(
|
|
mWidth, getHeight(), orientationChanged, LayoutManagerImpl.time());
|
|
|
|
- mStripFilterArea.set(0, 0, mWidth, Math.min(getHeight(), visibleViewportOffsetY));
|
|
+ float top = 0;
|
|
+ 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(0, top, mWidth, top + Math.min(getHeight(), visibleViewportOffsetY));
|
|
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
|
|
@@ -16,6 +16,8 @@ import org.chromium.chrome.browser.tab.Tab;
|
|
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 {
|
|
@@ -48,7 +50,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/1070281): 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
|
|
@@ -20,6 +20,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
|
|
@@ -83,9 +86,24 @@ public class TabStripSceneLayer extends SceneOverlayLayer {
|
|
int selectedTabId,
|
|
int hoveredTabId,
|
|
int scrimColor,
|
|
- float scrimOpacity) {
|
|
+ float scrimOpacity,
|
|
+ float viewportHeight,
|
|
+ int topControlsHeight) {
|
|
if (mNativePtr == 0) return;
|
|
- final boolean visible = yOffset > -layoutHelper.getHeight();
|
|
+ boolean visible = yOffset > -layoutHelper.getHeight();
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // check if force tablet mode is active
|
|
+ // is active if(isTablet != isNonMultiDisplayContextOnTablet)
|
|
+ if (DeviceFormFactor.isTablet() ==
|
|
+ DeviceFormFactor.isNonMultiDisplayContextOnTablet(ContextUtils.getApplicationContext())) {
|
|
+ // the list of open tabs (in tablet mode not forced) 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
|
|
@@ -415,6 +417,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;
|
|
@@ -481,6 +491,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);
|
|
}
|
|
|
|
@@ -132,6 +140,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
|
|
@@ -291,7 +291,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
|
|
@@ -117,6 +117,7 @@ import org.chromium.content_public.browser.NavigationController;
|
|
import org.chromium.ui.base.DeviceFormFactor;
|
|
import org.chromium.ui.base.WindowAndroid;
|
|
import org.chromium.url.GURL;
|
|
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
|
|
|
import java.util.List;
|
|
|
|
@@ -685,11 +686,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;
|
|
@@ -709,9 +715,7 @@ public class NewTabPage
|
|
* strip.
|
|
*/
|
|
private int getToolbarExtraYOffset() {
|
|
- return mBrowserControlsStateProvider.getTopControlsHeight()
|
|
- - mToolbarHeight
|
|
- - mTabStripHeightSupplier.get();
|
|
+ return 0;
|
|
}
|
|
|
|
/** @return The view container for the new tab layout. */
|
|
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
|
|
@@ -19,6 +19,8 @@ import android.view.DragEvent;
|
|
import android.view.Gravity;
|
|
import android.view.LayoutInflater;
|
|
import android.view.ViewStub;
|
|
+import android.view.ViewGroup.LayoutParams;
|
|
+import android.widget.FrameLayout;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.LinearLayout;
|
|
@@ -198,6 +200,12 @@ public class NewTabPageLayout extends LinearLayout {
|
|
super.onFinishInflate();
|
|
mMiddleSpacer = findViewById(R.id.ntp_middle_spacer);
|
|
insertSiteSectionView();
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ FrameLayout.LayoutParams params =
|
|
+ new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
|
+ params.gravity = Gravity.BOTTOM;
|
|
+ setLayoutParams(params);
|
|
+ }
|
|
}
|
|
|
|
/**
|
|
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
|
|
@@ -26,6 +26,7 @@ import org.chromium.chrome.browser.ui.native_page.NativePageHost;
|
|
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
|
|
@@ -56,6 +57,7 @@ public class RecentTabsPage
|
|
private int mSnapshotListTop;
|
|
private int mSnapshotWidth;
|
|
private int mSnapshotHeight;
|
|
+ private final int mTabStripAndToolbarHeight;
|
|
|
|
/** Whether {@link #mView} is attached to the application window. */
|
|
private boolean mIsAttachedToWindow;
|
|
@@ -82,6 +84,8 @@ public class RecentTabsPage
|
|
mActivity = activity;
|
|
mRecentTabsManager = recentTabsManager;
|
|
mPageHost = pageHost;
|
|
+ mTabStripAndToolbarHeight =
|
|
+ activity.getResources().getDimensionPixelSize(R.dimen.tab_strip_and_toolbar_height);
|
|
Resources resources = activity.getResources();
|
|
|
|
mTitle = resources.getString(R.string.recent_tabs);
|
|
@@ -99,7 +103,8 @@ public class RecentTabsPage
|
|
|
|
mView.addOnAttachStateChangeListener(this);
|
|
|
|
- if (!DeviceFormFactor.isNonMultiDisplayContextOnTablet(mActivity)) {
|
|
+ if (!DeviceFormFactor.isNonMultiDisplayContextOnTablet(mActivity) ||
|
|
+ ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
mBrowserControlsStateProvider = browserControlsStateProvider;
|
|
mBrowserControlsStateProvider.addObserver(this);
|
|
onBottomControlsHeightChanged(
|
|
@@ -300,7 +305,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();
|
|
@@ -316,9 +321,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
|
|
@@ -91,6 +91,10 @@ import org.chromium.ui.base.WindowDelegate;
|
|
import org.chromium.ui.modaldialog.ModalDialogManager;
|
|
import org.chromium.url.GURL;
|
|
|
|
+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. */
|
|
@@ -232,6 +236,12 @@ public class SearchActivity extends AsyncInitializationActivity
|
|
(SearchActivityLocationBarLayout)
|
|
mContentView.findViewById(R.id.search_location_bar);
|
|
mAnchorView = mContentView.findViewById(R.id.toolbar);
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams)
|
|
+ mAnchorView.getLayoutParams();
|
|
+ layoutParams.gravity = Gravity.START | Gravity.BOTTOM;
|
|
+ mAnchorView.setLayoutParams(layoutParams);
|
|
+ }
|
|
updateAnchorViewLayout();
|
|
|
|
// Create status bar color controller and assign to search activity.
|
|
@@ -259,7 +269,7 @@ public class SearchActivity extends AsyncInitializationActivity
|
|
getOnBackPressedDispatcher().addCallback(this, backPressManager.getCallback());
|
|
mLocationBarCoordinator =
|
|
new LocationBarCoordinator(
|
|
- mSearchBox,
|
|
+ mSearchBox, mAnchorView,
|
|
mAnchorView,
|
|
mProfileSupplier,
|
|
PrivacyPreferencesManagerImpl.getInstance(),
|
|
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
|
|
@@ -362,6 +362,11 @@ public class SettingsActivity extends ChromeBaseAppCompatActivity
|
|
if (fragment instanceof INeedSnackbarManager) {
|
|
((INeedSnackbarManager)fragment).setSnackbarManager(mSnackbarManager);
|
|
}
|
|
+ if (fragment instanceof AccessibilitySettings) {
|
|
+ ((ChromeAccessibilitySettingsDelegate)
|
|
+ ((AccessibilitySettings) fragment)
|
|
+ .getDelegate()).setSnackbarManager(mSnackbarManager);
|
|
+ }
|
|
initBackPressHandler();
|
|
}
|
|
|
|
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
|
|
@@ -193,6 +193,9 @@ import org.chromium.url.GURL;
|
|
import java.util.List;
|
|
import java.util.function.BooleanSupplier;
|
|
|
|
+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.
|
|
@@ -824,7 +827,7 @@ public class ToolbarManager
|
|
LocationBarCoordinator locationBarCoordinator =
|
|
new LocationBarCoordinator(
|
|
mActivity.findViewById(R.id.location_bar),
|
|
- toolbarLayout,
|
|
+ toolbarLayout, controlContainer,
|
|
profileSupplier,
|
|
PrivacyPreferencesManagerImpl.getInstance(),
|
|
mLocationBarModel,
|
|
@@ -1132,6 +1135,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,
|
|
@@ -1145,6 +1149,7 @@ public class ToolbarManager
|
|
oldBottom) -> {
|
|
if (mControlContainer.getBackground() == null) {
|
|
setControlContainerTopMargin(getToolbarExtraYOffset());
|
|
+ MoveBottomBarOverTopBar();
|
|
mControlContainer.removeOnLayoutChangeListener(
|
|
mLayoutChangeListener);
|
|
mLayoutChangeListener = null;
|
|
@@ -1334,6 +1339,13 @@ public class ToolbarManager
|
|
public void setTabSwitcherFullScreenView(ViewGroup containerView) {
|
|
ViewStub toolbarStub =
|
|
containerView.findViewById(R.id.fullscreen_tab_switcher_toolbar_stub);
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // the top tab switcher toolbar is docked at the bottom
|
|
+ FrameLayout.LayoutParams params =
|
|
+ (FrameLayout.LayoutParams)toolbarStub.getLayoutParams();
|
|
+ params.gravity = Gravity.START | Gravity.BOTTOM;
|
|
+ toolbarStub.setLayoutParams(params);
|
|
+ }
|
|
mToolbar.setFullScreenToolbarStub(toolbarStub);
|
|
}
|
|
|
|
@@ -1631,14 +1643,26 @@ 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(-mBrowserControlsSizer.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();
|
|
mTabGroupUi =
|
|
TabManagementDelegateProvider.getDelegate()
|
|
.createTabGroupUi(
|
|
mActivity,
|
|
- root.findViewById(R.id.bottom_container_slot),
|
|
+ mBottomRoot.findViewById(R.id.bottom_container_slot),
|
|
mBrowserControlsSizer,
|
|
mIncognitoStateProvider,
|
|
mScrimCoordinator,
|
|
@@ -1661,11 +1685,12 @@ public class ToolbarManager
|
|
mCompositorViewHolder.getResourceManager(),
|
|
mBrowserControlsSizer,
|
|
mFullscreenManager,
|
|
- (ScrollingBottomViewResourceFrameLayout) root,
|
|
+ (ScrollingBottomViewResourceFrameLayout) mBottomRoot,
|
|
mTabGroupUi,
|
|
mTabObscuringHandler,
|
|
mOverlayPanelVisibilitySupplier,
|
|
- mConstraintsProxy);
|
|
+ mConstraintsProxy,
|
|
+ mTopUiThemeColorProvider, mActivityTabProvider);
|
|
mBottomControlsCoordinatorSupplier.set(bottomControlsCoordinator);
|
|
if (mBackPressManager != null) {
|
|
mBackPressManager.addHandler(
|
|
@@ -2195,6 +2220,8 @@ public class ToolbarManager
|
|
*/
|
|
private int getToolbarExtraYOffset() {
|
|
int toolbarHairlineHeight = mToolbarHairline.getHeight();
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled())
|
|
+ toolbarHairlineHeight = 0;
|
|
int extraYOffset =
|
|
mBrowserControlsSizer.getTopControlsHeight()
|
|
- (mControlContainer.getHeight() - toolbarHairlineHeight);
|
|
@@ -2589,6 +2616,15 @@ public class ToolbarManager
|
|
private void setControlContainerTopMargin(int margin) {
|
|
final ViewGroup.MarginLayoutParams layoutParams =
|
|
((ViewGroup.MarginLayoutParams) mControlContainer.getLayoutParams());
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ if (layoutParams.bottomMargin == margin) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ layoutParams.bottomMargin = margin;
|
|
+ mControlContainer.setLayoutParams(layoutParams);
|
|
+ return;
|
|
+ }
|
|
if (layoutParams.topMargin == margin) {
|
|
return;
|
|
}
|
|
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
|
|
@@ -62,10 +63,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.base.supplier.OneshotSupplier;
|
|
@@ -593,6 +596,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"
|
|
@@ -113,8 +114,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()));
|
|
+ }
|
|
}
|
|
|
|
int ToolbarLayer::GetIndexOfLayer(scoped_refptr<cc::slim::Layer> layer) {
|
|
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
|
|
@@ -17,6 +17,7 @@
|
|
#include "ui/android/resources/nine_patch_resource.h"
|
|
#include "ui/android/resources/resource_manager_impl.h"
|
|
#include "ui/gfx/geometry/transform.h"
|
|
+#include "cc/base/features.h"
|
|
|
|
using base::android::JavaParamRef;
|
|
using base::android::JavaRef;
|
|
@@ -82,8 +83,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()));
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
@@ -117,13 +120,18 @@ void TabStripSceneLayer::UpdateTabStripLayer(JNIEnv* env,
|
|
jint scrim_color,
|
|
jfloat scrim_opacity) {
|
|
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));
|
|
scrollable_strip_layer_->SetBounds(gfx::Size(width, height));
|
|
tab_strip_layer_->SetBackgroundColor(SkColor4f::FromColor(background_color));
|
|
|
|
// 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));
|
|
|
|
// Hide scrim layer if it's not visible.
|
|
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
|
|
@@ -58,6 +59,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
|
|
@@ -58,6 +58,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;
|
|
@@ -133,7 +134,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/browser_features.h"
|
|
#include "chrome/browser/feature_guide/notifications/feature_notification_guide_service.h"
|
|
#include "chrome/browser/flags/android/chrome_session_state.h"
|
|
@@ -231,6 +232,7 @@ const base::Feature* const kFeaturesExposedToJava[] = {
|
|
&kMagicStackAndroid,
|
|
&kMultiInstanceApplicationStatusCleanup,
|
|
&kNewTabSearchEngineUrlAndroid,
|
|
+ &features::kMoveTopToolbarToBottom,
|
|
&kNotificationPermissionVariant,
|
|
&kNotificationPermissionBottomSheet,
|
|
&kOpenDownloadDialog,
|
|
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
|
|
@@ -339,6 +339,8 @@ public abstract class ChromeFeatureList {
|
|
"MultiInstanceApplicationStatusCleanup";
|
|
public static final String NEW_TAB_SEARCH_ENGINE_URL_ANDROID = "NewTabSearchEngineUrlAndroid";
|
|
public static final String NOTIFICATION_ONE_TAP_UNSUBSCRIBE = "NotificationOneTapUnsubscribe";
|
|
+ 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";
|
|
@@ -614,6 +616,8 @@ public abstract class ChromeFeatureList {
|
|
newCachedFlag(QUERY_TILES_IN_ZPS_ON_NTP, false);
|
|
public static final CachedFlag sOmniboxMatchToolbarAndStatusBarColor =
|
|
newCachedFlag(OMNIBOX_MATCH_TOOLBAR_AND_STATUS_BAR_COLOR, false);
|
|
+ public static final CachedFlag sMoveTopToolbarToBottom =
|
|
+ newCachedFlag(MOVE_TOP_TOOLBAR_TO_BOTTOM, false);
|
|
public static final CachedFlag sOmniboxModernizeVisualUpdate =
|
|
newCachedFlag(OMNIBOX_MODERNIZE_VISUAL_UPDATE, true);
|
|
public static final CachedFlag sOptimizationGuidePushNotifications =
|
|
@@ -735,6 +739,7 @@ public abstract class ChromeFeatureList {
|
|
sOmniboxMatchToolbarAndStatusBarColor,
|
|
sOmniboxModernizeVisualUpdate,
|
|
sOptimizationGuidePushNotifications,
|
|
+ sMoveTopToolbarToBottom,
|
|
sPaintPreviewDemo,
|
|
sQueryTiles,
|
|
sRedirectExplicitCTAIntentsToExistingActivity,
|
|
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
|
|
@@ -2100,7 +2100,7 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
|
|
|
|
#if BUILDFLAG(IS_ANDROID)
|
|
registry->RegisterBooleanPref(prefs::kVirtualKeyboardResizesLayoutByDefault,
|
|
- false);
|
|
+ true);
|
|
#endif
|
|
|
|
registry->RegisterTimePref(prefs::kDIPSTimerLastUpdate, base::Time());
|
|
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;
|
|
@@ -188,6 +189,15 @@ class AppMenuHandlerImpl
|
|
}),
|
|
this);
|
|
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ // reverses the order of items in the menu
|
|
+ ModelList modelListReversed = new ModelList();
|
|
+ for (int i = 0; i < modelList.size(); i++) {
|
|
+ modelListReversed.add(0, modelList.get(i));
|
|
+ }
|
|
+ modelList = modelListReversed;
|
|
+ }
|
|
+
|
|
ContextThemeWrapper wrapper =
|
|
new ContextThemeWrapper(mContext, R.style.OverflowMenuThemeOverlay);
|
|
|
|
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java
|
|
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java
|
|
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java
|
|
@@ -91,6 +91,7 @@ public class LocationBarCoordinator
|
|
private StatusCoordinator mStatusCoordinator;
|
|
private WindowDelegate mWindowDelegate;
|
|
private WindowAndroid mWindowAndroid;
|
|
+ private View mContainerView;
|
|
private LocationBarMediator mLocationBarMediator;
|
|
private View mUrlBar;
|
|
private View mDeleteButton;
|
|
@@ -150,7 +151,7 @@ public class LocationBarCoordinator
|
|
*/
|
|
public LocationBarCoordinator(
|
|
View locationBarLayout,
|
|
- View autocompleteAnchorView,
|
|
+ View autocompleteAnchorView, View containerView,
|
|
ObservableSupplier<Profile> profileObservableSupplier,
|
|
PrivacyPreferencesManager privacyPreferencesManager,
|
|
LocationBarDataProvider locationBarDataProvider,
|
|
@@ -190,6 +191,7 @@ public class LocationBarCoordinator
|
|
mWindowAndroid = windowAndroid;
|
|
mActivityLifecycleDispatcher = activityLifecycleDispatcher;
|
|
mActivityLifecycleDispatcher.register(this);
|
|
+ mContainerView = containerView;
|
|
Context context = mLocationBarLayout.getContext();
|
|
OneshotSupplierImpl<TemplateUrlService> templateUrlServiceSupplier =
|
|
new OneshotSupplierImpl<>();
|
|
@@ -200,7 +202,8 @@ public class LocationBarCoordinator
|
|
autocompleteAnchorView,
|
|
mLocationBarLayout,
|
|
forcePhoneStyleOmnibox,
|
|
- baseChromeLayout);
|
|
+ baseChromeLayout,
|
|
+ mContainerView);
|
|
|
|
mUrlBar = mLocationBarLayout.findViewById(R.id.url_bar);
|
|
// TODO(crbug.com/1151513): Inject LocaleManager instance to LocationBarCoordinator instead
|
|
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
|
|
@@ -22,6 +22,7 @@ import org.chromium.base.Callback;
|
|
import org.chromium.base.supplier.ObservableSupplierImpl;
|
|
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;
|
|
@@ -42,6 +43,7 @@ class OmniboxSuggestionsDropdownEmbedderImpl
|
|
private final @NonNull WindowAndroid mWindowAndroid;
|
|
private final @NonNull WindowDelegate mWindowDelegate;
|
|
private final @NonNull View mAnchorView;
|
|
+ private final @NonNull View mContainerView;
|
|
private final @NonNull View mHorizontalAlignmentView;
|
|
private final boolean mForcePhoneStyleOmnibox;
|
|
private final @NonNull Context mContext;
|
|
@@ -73,10 +75,12 @@ class OmniboxSuggestionsDropdownEmbedderImpl
|
|
@NonNull View anchorView,
|
|
@NonNull View horizontalAlignmentView,
|
|
boolean forcePhoneStyleOmnibox,
|
|
- @Nullable View baseChromeLayout) {
|
|
+ @Nullable View baseChromeLayout,
|
|
+ @NonNull View containerView) {
|
|
mWindowAndroid = windowAndroid;
|
|
mWindowDelegate = windowDelegate;
|
|
mAnchorView = anchorView;
|
|
+ mContainerView = containerView;
|
|
mHorizontalAlignmentView = horizontalAlignmentView;
|
|
mForcePhoneStyleOmnibox = forcePhoneStyleOmnibox;
|
|
mContext = mAnchorView.getContext();
|
|
@@ -98,6 +102,16 @@ class OmniboxSuggestionsDropdownEmbedderImpl
|
|
mOmniboxAlignmentSupplier.removeObserver(obs);
|
|
}
|
|
|
|
+ @Override
|
|
+ public View getAnchorView() {
|
|
+ return mAnchorView;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public View getAnchorContainerView() {
|
|
+ return mContainerView;
|
|
+ }
|
|
+
|
|
@Nullable
|
|
@Override
|
|
public OmniboxAlignment getCurrentAlignment() {
|
|
@@ -116,9 +130,11 @@ class OmniboxSuggestionsDropdownEmbedderImpl
|
|
mAnchorView.addOnLayoutChangeListener(this);
|
|
mHorizontalAlignmentView.addOnLayoutChangeListener(this);
|
|
mAnchorView.getViewTreeObserver().addOnGlobalLayoutListener(this);
|
|
- mDeferredIMEWindowInsetApplicationCallback =
|
|
- new DeferredIMEWindowInsetApplicationCallback(this::recalculateOmniboxAlignment);
|
|
- mDeferredIMEWindowInsetApplicationCallback.attach(mWindowAndroid);
|
|
+ if (!ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ mDeferredIMEWindowInsetApplicationCallback =
|
|
+ new DeferredIMEWindowInsetApplicationCallback(this::recalculateOmniboxAlignment);
|
|
+ mDeferredIMEWindowInsetApplicationCallback.attach(mWindowAndroid);
|
|
+ }
|
|
onConfigurationChanged(mContext.getResources().getConfiguration());
|
|
recalculateOmniboxAlignment();
|
|
}
|
|
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
|
|
@@ -60,6 +60,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;
|
|
@@ -81,6 +82,7 @@ public class AutocompleteCoordinator implements UrlFocusChangeListener, UrlTextC
|
|
new OneshotSupplierImpl<>();
|
|
private PreWarmingRecycledViewPool mRecycledViewPool;
|
|
private final boolean mForcePhoneStyleOmnibox;
|
|
+ private final @NonNull OmniboxSuggestionsDropdownEmbedder mDropdownEmbedder;
|
|
|
|
public AutocompleteCoordinator(
|
|
@NonNull ViewGroup parent,
|
|
@@ -109,6 +111,7 @@ public class AutocompleteCoordinator implements UrlFocusChangeListener, UrlTextC
|
|
PropertyModel listModel = new PropertyModel(SuggestionListProperties.ALL_KEYS);
|
|
ModelList listItems = new ModelList();
|
|
|
|
+ mDropdownEmbedder = dropdownEmbedder;
|
|
listModel.set(SuggestionListProperties.EMBEDDER, dropdownEmbedder);
|
|
listModel.set(SuggestionListProperties.VISIBLE, false);
|
|
listModel.set(SuggestionListProperties.DRAW_OVER_ANCHOR, false);
|
|
@@ -190,7 +193,8 @@ public class AutocompleteCoordinator implements UrlFocusChangeListener, UrlTextC
|
|
try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
|
|
dropdown =
|
|
new OmniboxSuggestionsDropdown(
|
|
- context, mRecycledViewPool, mForcePhoneStyleOmnibox);
|
|
+ context, mRecycledViewPool, mForcePhoneStyleOmnibox,
|
|
+ mDropdownEmbedder);
|
|
}
|
|
|
|
dropdown.getViewGroup().setClipToPadding(false);
|
|
@@ -204,6 +208,16 @@ public class AutocompleteCoordinator implements UrlFocusChangeListener, UrlTextC
|
|
R.id
|
|
.omnibox_results_container_stub))
|
|
.inflate();
|
|
+ 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();
|
|
+ }
|
|
|
|
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
|
|
@@ -67,6 +67,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;
|
|
@@ -1081,7 +1083,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.omnibox.OmniboxFeatures;
|
|
import org.chromium.chrome.browser.omnibox.R;
|
|
import org.chromium.chrome.browser.omnibox.styles.OmniboxResourceProvider;
|
|
@@ -118,6 +119,7 @@ class DropdownItemViewInfoListManager {
|
|
boolean shouldShowModernizeVisualUpdate =
|
|
OmniboxFeatures.shouldShowModernizeVisualUpdate(mContext);
|
|
|
|
+ boolean toolbarToBottom = ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled();
|
|
for (int i = 0; i < mSourceViewInfoList.size(); i++) {
|
|
final DropdownItemViewInfo item = mSourceViewInfoList.get(i);
|
|
final PropertyModel model = item.model;
|
|
@@ -129,11 +131,14 @@ class DropdownItemViewInfoListManager {
|
|
currentSection = item.groupConfig.getSection();
|
|
var applyRounding = currentSection != previousSection;
|
|
|
|
- model.set(DropdownCommonProperties.BG_TOP_CORNER_ROUNDED, applyRounding);
|
|
+ model.set(toolbarToBottom ? DropdownCommonProperties.BG_BOTTOM_CORNER_ROUNDED
|
|
+ : DropdownCommonProperties.BG_TOP_CORNER_ROUNDED, applyRounding);
|
|
|
|
if (previousItem != null) {
|
|
previousItem.model.set(
|
|
- DropdownCommonProperties.BG_BOTTOM_CORNER_ROUNDED, applyRounding);
|
|
+ toolbarToBottom ?
|
|
+ DropdownCommonProperties.BG_TOP_CORNER_ROUNDED :
|
|
+ DropdownCommonProperties.BG_BOTTOM_CORNER_ROUNDED, applyRounding);
|
|
previousItem.model.set(DropdownCommonProperties.SHOW_DIVIDER, !applyRounding);
|
|
}
|
|
|
|
@@ -146,7 +151,9 @@ class DropdownItemViewInfoListManager {
|
|
|
|
// round the bottom corners of the last suggestion.
|
|
if (previousItem != null) {
|
|
- previousItem.model.set(DropdownCommonProperties.BG_BOTTOM_CORNER_ROUNDED, true);
|
|
+ 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
|
|
@@ -41,6 +41,9 @@ import org.chromium.ui.KeyboardVisibilityDelegate;
|
|
import org.chromium.ui.base.DeviceFormFactor;
|
|
import org.chromium.ui.base.ViewUtils;
|
|
|
|
+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 {
|
|
/**
|
|
@@ -219,7 +222,8 @@ public class OmniboxSuggestionsDropdown extends RecyclerView {
|
|
public OmniboxSuggestionsDropdown(
|
|
@NonNull Context context,
|
|
RecycledViewPool recycledViewPool,
|
|
- boolean forcePhoneStyleOmnibox) {
|
|
+ boolean forcePhoneStyleOmnibox,
|
|
+ @NonNull OmniboxSuggestionsDropdownEmbedder embedder) {
|
|
super(context, null, android.R.attr.dropDownListViewStyle);
|
|
setFocusable(true);
|
|
setFocusableInTouchMode(true);
|
|
@@ -231,7 +235,6 @@ public class OmniboxSuggestionsDropdown extends RecyclerView {
|
|
setItemAnimator(null);
|
|
|
|
mLayoutScrollListener = new SuggestionLayoutScrollListener(context);
|
|
- setLayoutManager(mLayoutScrollListener);
|
|
mSelectionController = new RecyclerViewSelectionController(mLayoutScrollListener);
|
|
addOnChildAttachStateChangeListener(mSelectionController);
|
|
|
|
@@ -242,6 +245,20 @@ 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);
|
|
+
|
|
+ if (!embedder.isTablet()) {
|
|
+ ViewGroup.MarginLayoutParams embedderParams = (ViewGroup.MarginLayoutParams)
|
|
+ embedder.getAnchorContainerView().getLayoutParams();
|
|
+ paddingBottom = resources.getDimensionPixelOffset(R.dimen.toolbar_height_no_shadow) +
|
|
+ embedderParams.bottomMargin;
|
|
+ }
|
|
+ paddingTop = 0;
|
|
+ }
|
|
+ setLayoutManager(mLayoutScrollListener);
|
|
ViewCompat.setPaddingRelative(this, 0, paddingTop, 0, paddingBottom);
|
|
|
|
mStandardBgColor =
|
|
@@ -399,8 +416,16 @@ public class OmniboxSuggestionsDropdown extends RecyclerView {
|
|
TimingMetric metric = OmniboxMetrics.recordSuggestionListMeasureTime();
|
|
TimingMetric metric2 = OmniboxMetrics.recordSuggestionListMeasureWallTime()) {
|
|
OmniboxAlignment omniboxAlignment = mEmbedder.getCurrentAlignment();
|
|
- maybeUpdateLayoutParams(omniboxAlignment.top);
|
|
- int availableViewportHeight = omniboxAlignment.height;
|
|
+ int top = omniboxAlignment.top;
|
|
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
|
|
+ top = 0;
|
|
+ }
|
|
+ maybeUpdateLayoutParams(top);
|
|
+ boolean useAlignmentSpecifiedHeight =
|
|
+ !ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled();
|
|
+ int availableViewportHeight = useAlignmentSpecifiedHeight
|
|
+ ? omniboxAlignment.height
|
|
+ : calculateAvailableViewportHeight() - top;
|
|
int desiredWidth = omniboxAlignment.width;
|
|
adjustHorizontalPosition();
|
|
notifyObserversIfViewportHeightChanged(availableViewportHeight);
|
|
@@ -420,6 +445,12 @@ public class OmniboxSuggestionsDropdown extends RecyclerView {
|
|
}
|
|
}
|
|
|
|
+ private int calculateAvailableViewportHeight() {
|
|
+ Rect mTempRect = new Rect();
|
|
+ mEmbedder.getWindowDelegate().getWindowVisibleDisplayFrame(mTempRect);
|
|
+ return mTempRect.height();
|
|
+ }
|
|
+
|
|
private void maybeUpdateLayoutParams(int topMargin) {
|
|
// Update the layout params to ensure the parent correctly positions the suggestions
|
|
// under the anchor view.
|
|
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;
|
|
@@ -108,6 +109,13 @@ public interface OmniboxSuggestionsDropdownEmbedder {
|
|
@NonNull
|
|
OmniboxAlignment getCurrentAlignment();
|
|
|
|
+ @NonNull
|
|
+ View getAnchorView();
|
|
+
|
|
+ /** Return the container view the suggestion list should be drawn in. */
|
|
+ @NonNull
|
|
+ View getAnchorContainerView();
|
|
+
|
|
/** Return the delegate used to interact with the Window. */
|
|
@NonNull
|
|
WindowDelegate getWindowDelegate();
|
|
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
|
|
@@ -1605,6 +1605,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_MOVE_TOOLBAR_BOTTOM_SUMMARY" desc="Summary of the preference that allows the user to move toolbar on bottom.">
|
|
+ Move toolbar to bottom
|
|
+ </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
|
|
@@ -174,6 +174,7 @@ android_library("java") {
|
|
"//components/user_prefs/android:java",
|
|
"//content/public/android:content_java",
|
|
"//third_party/android_deps:material_design_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
|
|
@@ -17,6 +17,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 {
|
|
@@ -61,6 +62,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
|
|
@@ -26,6 +26,8 @@ import org.chromium.ui.modelutil.PropertyModel;
|
|
import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
|
|
import org.chromium.ui.resources.ResourceManager;
|
|
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
|
|
@@ -60,6 +62,8 @@ public class BottomControlsCoordinator implements BackPressHandler {
|
|
* @param tabObscuringHandler Delegate object handling obscuring views.
|
|
* @param overlayPanelVisibilitySupplier Notifies overlay panel visibility event.
|
|
* @param constraintsSupplier Used to access current constraints of the browser controls.
|
|
+ * @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(
|
|
@@ -73,7 +77,9 @@ public class BottomControlsCoordinator implements BackPressHandler {
|
|
BottomControlsContentDelegate contentDelegate,
|
|
TabObscuringHandler tabObscuringHandler,
|
|
ObservableSupplier<Boolean> overlayPanelVisibilitySupplier,
|
|
- ObservableSupplier<Integer> constraintsSupplier) {
|
|
+ ObservableSupplier<Integer> constraintsSupplier,
|
|
+ TopUiThemeColorProvider topUiThemeColorProvider,
|
|
+ ObservableSupplier<Tab> tabSupplier) {
|
|
root.setConstraintsSupplier(constraintsSupplier);
|
|
PropertyModel model = new PropertyModel(BottomControlsProperties.ALL_KEYS);
|
|
|
|
@@ -115,7 +121,8 @@ public class BottomControlsCoordinator implements BackPressHandler {
|
|
|
|
if (mContentDelegate != null) {
|
|
mContentDelegate.initializeWithNative(
|
|
- activity, mMediator::setBottomControlsVisible, root::onModelTokenChange);
|
|
+ activity, mMediator::setBottomControlsVisible, root::onModelTokenChange,
|
|
+ topUiThemeColorProvider, tabSupplier);
|
|
}
|
|
}
|
|
|
|
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
|
|
@@ -16,6 +16,7 @@ import org.chromium.chrome.browser.tab.TabObscuringHandler;
|
|
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
|
|
@@ -108,6 +109,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.
|
|
+ mBrowserControlsSizer.getBrowserVisibilityDelegate().showControlsTransient();
|
|
+ }
|
|
mIsBottomControlsVisible = visible;
|
|
updateCompositedViewVisibility();
|
|
updateAndroidViewVisibility();
|
|
@@ -132,6 +139,7 @@ class BottomControlsMediator
|
|
int bottomOffset,
|
|
int bottomControlsMinHeightOffset,
|
|
boolean needsAnimate) {
|
|
+ mModel.set(BottomControlsProperties.TOPCONTROLSMINHEIGHT_OFFSET, topControlsMinHeightOffset);
|
|
int minHeight = mBrowserControlsSizer.getBottomControlsMinHeight();
|
|
mModel.set(BottomControlsProperties.Y_OFFSET, bottomOffset - minHeight);
|
|
|
|
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
|
|
@@ -23,6 +23,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();
|
|
|
|
@@ -41,6 +44,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
|
|
@@ -42,6 +42,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
|
|
@@ -60,6 +60,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 {
|
|
private boolean mIncognito;
|
|
@@ -114,6 +118,12 @@ public class ToolbarControlContainer extends OptimizedFrameLayout implements Con
|
|
@Override
|
|
public void initWithToolbar(int toolbarLayoutId) {
|
|
try (TraceEvent te = TraceEvent.scoped("ToolbarControlContainer.initWithToolbar")) {
|
|
+ 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
|
|
@@ -26,6 +26,8 @@ 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 +64,9 @@ 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())
|
|
.build();
|
|
mSceneLayer = new TopToolbarSceneLayer(resourceManagerSupplier);
|
|
mChangeProcessor =
|
|
@@ -113,6 +118,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
|
|
@@ -46,6 +46,12 @@ public class TopToolbarOverlayProperties {
|
|
/** The current y offset of the top toolbar. */
|
|
public static final WritableFloatPropertyKey CONTENT_OFFSET = new WritableFloatPropertyKey();
|
|
|
|
+ /** 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,
|
|
@@ -58,5 +64,5 @@ public class TopToolbarOverlayProperties {
|
|
VISIBLE,
|
|
X_OFFSET,
|
|
CONTENT_OFFSET
|
|
- };
|
|
+ , 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
|
|
@@ -14,6 +14,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")
|
|
@@ -39,6 +40,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,
|
|
@@ -49,7 +57,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
|
|
@@ -54,4 +54,8 @@ found in the LICENSE file.
|
|
android:key="captions"
|
|
android:title="@string/accessibility_captions_title"/>
|
|
|
|
+ <org.chromium.components.browser_ui.settings.ChromeSwitchPreference
|
|
+ android:key="move_toolbar_bottom"
|
|
+ android:summary="@string/move_toolbar_bottom_summary"
|
|
+ android:title="@string/move_toolbar_bottom_title" />
|
|
</PreferenceScreen>
|
|
diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java
|
|
--- a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java
|
|
+++ b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java
|
|
@@ -34,6 +34,7 @@ public class AccessibilitySettings extends PreferenceFragmentCompat
|
|
|
|
private BooleanPreferenceDelegate mForceTabletUIDelegate;
|
|
static final String PREF_FORCE_TABLET_UI = "force_tablet_ui";
|
|
+ static final String PREF_MOVE_TOOLBAR_TO_BOTTOM = "move_toolbar_bottom";
|
|
private TextScalePreference mTextScalePref;
|
|
private PageZoomPreference mPageZoomDefaultZoomPref;
|
|
private ChromeSwitchPreference mPageZoomIncludeOSAdjustment;
|
|
@@ -43,6 +44,7 @@ public class AccessibilitySettings extends PreferenceFragmentCompat
|
|
private AccessibilitySettingsDelegate mDelegate;
|
|
private BooleanPreferenceDelegate mReaderForAccessibilityDelegate;
|
|
private double mPageZoomLatestDefaultZoomPrefValue;
|
|
+ private BooleanPreferenceDelegate mMoveTopToolbarToBottomDelegate;
|
|
|
|
private FontSizePrefs mFontSizePrefs;
|
|
private FontSizePrefsObserver mFontSizePrefsObserver =
|
|
@@ -65,6 +67,10 @@ public class AccessibilitySettings extends PreferenceFragmentCompat
|
|
mFontSizePrefs = FontSizePrefs.getInstance(delegate.getBrowserContextHandle());
|
|
}
|
|
|
|
+ public AccessibilitySettingsDelegate getDelegate() {
|
|
+ return mDelegate;
|
|
+ }
|
|
+
|
|
@Override
|
|
public void onActivityCreated(Bundle savedInstanceState) {
|
|
super.onActivityCreated(savedInstanceState);
|
|
@@ -137,6 +143,12 @@ public class AccessibilitySettings extends PreferenceFragmentCompat
|
|
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);
|
|
+
|
|
Preference captions = findPreference(PREF_CAPTIONS);
|
|
captions.setOnPreferenceClickListener(
|
|
preference -> {
|
|
@@ -211,6 +223,9 @@ public class AccessibilitySettings extends PreferenceFragmentCompat
|
|
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_PAGE_ZOOM_INCLUDE_OS_ADJUSTMENT.equals(preference.getKey())) {
|
|
// TODO(mschillaci): Implement the override behavior for OS level.
|
|
}
|
|
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
|
|
@@ -6,6 +6,8 @@ package org.chromium.components.browser_ui.accessibility;
|
|
|
|
import android.content.Context;
|
|
|
|
+import android.app.Activity;
|
|
+
|
|
import androidx.annotation.NonNull;
|
|
import androidx.preference.PreferenceFragmentCompat;
|
|
|
|
@@ -37,6 +39,10 @@ public interface AccessibilitySettingsDelegate {
|
|
void setValue(int value);
|
|
}
|
|
|
|
+ void requestRestart(Activity activity);
|
|
+
|
|
+ BooleanPreferenceDelegate getMoveTopToolbarToBottomDelegate();
|
|
+
|
|
/** @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/slim/layer.h"
|
|
#include "components/viz/common/features.h"
|
|
@@ -866,6 +867,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,12 @@
|
|
+#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)},
|
|
+
|
|
+#endif
|
|
+
|
|
+#endif
|
|
--
|