Commit ed20c69b authored by Jinsuk Kim's avatar Jinsuk Kim Committed by Commit Bot

Android: Refactor gesture navigation objects to be activity-level

HistoryNavigationLayout is a top level layout class of gesture
navigation feature, and is a child view of Tab's
ContentView. This CL moves it one level up in the view hierarchy
so that it becomes a child of CompositorViewHolder instead. This
has a few benefits:

1) Many native pages included HistoryNavigationLayout in its
layout definition. This caused undesirable dependencies on
gesture navigation, blocking component-wise modularization
efforts. Once it is removed from native page layout, it becomes
much easier to build each component as its own target.

2) Gesture navigation-related UI doesn't have to be instantiated
for each tab. A single set of instances can be used for all, each
tab only needing to provide with navigation delegate objects that
have dependency on tab when it goes foreground.

3) When the layout is added to Tab's content view, the
UI (especially arrow's fade-away animation when navigation
starts) is visible as long as its parent view is alive, but
navigation between rendered and native page swaps out the content
view. This keeps the navigation and animation from starting
simultaneously. The refactoring gets rid of this limitation.

Major changes are:

- CompositorViewHolder dispatches touch event to
HistoryNavigationLayout. If the right gesture is detected, lets
it consume the following events.

- HistoryNavigationLayout in native pages are either removed or all
replaced with FrameLayout. This is basically reverting relevant
parts of the past CLs:

https://crrev.com/c/1249530 Implement gesture navigation on Android
https://crrev.com/c/1423477 Android: More native pages become navigable
https://crrev.com/c/1547547 Android: Trigger history navigation with edge swipe
https://crrev.com/c/1554200 Android: Enable overscroll navigation in explore site page

- Rendered pages also make use of
HistoryNavigationLayout (previously SwipeRefreshHandler had its
own NavigationHandler) and reference the NavigationHandler that
the layout provides. This helps consolidate most of the
navigation event handling logic in the layout.

Bug: 1003914
Change-Id: I62ed28bd8f6aab39ca7a47f2e3fdce7a131fbfb6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1961351
Commit-Queue: Jinsuk Kim <jinsukkim@chromium.org>
Reviewed-by: default avatarTed Choc <tedchoc@chromium.org>
Cr-Commit-Position: refs/heads/master@{#732653}
parent e81f9c34
...@@ -757,12 +757,11 @@ chrome_java_sources = [ ...@@ -757,12 +757,11 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/gesturenav/AndroidUiNavigationGlow.java", "java/src/org/chromium/chrome/browser/gesturenav/AndroidUiNavigationGlow.java",
"java/src/org/chromium/chrome/browser/gesturenav/CompositorNavigationGlow.java", "java/src/org/chromium/chrome/browser/gesturenav/CompositorNavigationGlow.java",
"java/src/org/chromium/chrome/browser/gesturenav/GestureNavMetrics.java", "java/src/org/chromium/chrome/browser/gesturenav/GestureNavMetrics.java",
"java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationCoordinator.java",
"java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationDelegate.java", "java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationDelegate.java",
"java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationDelegateFactory.java",
"java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationLayout.java", "java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationLayout.java",
"java/src/org/chromium/chrome/browser/gesturenav/NavigationBubble.java", "java/src/org/chromium/chrome/browser/gesturenav/NavigationBubble.java",
"java/src/org/chromium/chrome/browser/gesturenav/NavigationGlow.java", "java/src/org/chromium/chrome/browser/gesturenav/NavigationGlow.java",
"java/src/org/chromium/chrome/browser/gesturenav/NavigationGlowFactory.java",
"java/src/org/chromium/chrome/browser/gesturenav/NavigationHandler.java", "java/src/org/chromium/chrome/browser/gesturenav/NavigationHandler.java",
"java/src/org/chromium/chrome/browser/gesturenav/NavigationSheet.java", "java/src/org/chromium/chrome/browser/gesturenav/NavigationSheet.java",
"java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetCoordinator.java", "java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetCoordinator.java",
......
...@@ -96,7 +96,7 @@ class ExploreSurfaceCoordinator implements FeedSurfaceCoordinator.FeedSurfaceDel ...@@ -96,7 +96,7 @@ class ExploreSurfaceCoordinator implements FeedSurfaceCoordinator.FeedSurfaceDel
(SectionHeaderView) inflater.inflate(R.layout.ss_feed_header, null, false); (SectionHeaderView) inflater.inflate(R.layout.ss_feed_header, null, false);
} }
FeedSurfaceCoordinator feedSurfaceCoordinator = new FeedSurfaceCoordinator(mActivity, null, FeedSurfaceCoordinator feedSurfaceCoordinator = new FeedSurfaceCoordinator(mActivity, null,
null, null, sectionHeaderView, exploreSurfaceActionHandler, isInNightMode, this); null, sectionHeaderView, exploreSurfaceActionHandler, isInNightMode, this);
feedSurfaceCoordinator.getView().setId(R.id.start_surface_explore_view); feedSurfaceCoordinator.getView().setId(R.id.start_surface_explore_view);
return feedSurfaceCoordinator; return feedSurfaceCoordinator;
// TODO(crbug.com/982018): Customize surface background for incognito and dark mode. // TODO(crbug.com/982018): Customize surface background for incognito and dark mode.
......
...@@ -90,7 +90,6 @@ public class FeedNewTabPage ...@@ -90,7 +90,6 @@ public class FeedNewTabPage
SectionHeaderView sectionHeaderView = (SectionHeaderView) inflater.inflate( SectionHeaderView sectionHeaderView = (SectionHeaderView) inflater.inflate(
R.layout.new_tab_page_snippets_expandable_header, null, false); R.layout.new_tab_page_snippets_expandable_header, null, false);
mCoordinator = new FeedSurfaceCoordinator(((TabImpl) mTab).getActivity(), mCoordinator = new FeedSurfaceCoordinator(((TabImpl) mTab).getActivity(),
host.createHistoryNavigationDelegate(),
new SnapScrollHelper(mNewTabPageManager, mNewTabPageLayout), mNewTabPageLayout, new SnapScrollHelper(mNewTabPageManager, mNewTabPageLayout), mNewTabPageLayout,
sectionHeaderView, actionApi, sectionHeaderView, actionApi,
((TabImpl) mTab).getActivity().getNightModeStateProvider().isInNightMode(), this); ((TabImpl) mTab).getActivity().getNightModeStateProvider().isInNightMode(), this);
......
...@@ -15,6 +15,7 @@ import android.os.Build; ...@@ -15,6 +15,7 @@ import android.os.Build;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.widget.FrameLayout;
import android.widget.ScrollView; import android.widget.ScrollView;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
...@@ -35,8 +36,6 @@ import org.chromium.chrome.browser.feed.library.api.host.stream.SnackbarCallback ...@@ -35,8 +36,6 @@ import org.chromium.chrome.browser.feed.library.api.host.stream.SnackbarCallback
import org.chromium.chrome.browser.feed.library.api.host.stream.StreamConfiguration; import org.chromium.chrome.browser.feed.library.api.host.stream.StreamConfiguration;
import org.chromium.chrome.browser.feed.library.api.host.stream.TooltipApi; import org.chromium.chrome.browser.feed.library.api.host.stream.TooltipApi;
import org.chromium.chrome.browser.feed.tooltip.BasicTooltipApi; import org.chromium.chrome.browser.feed.tooltip.BasicTooltipApi;
import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegate;
import org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout;
import org.chromium.chrome.browser.native_page.ContextMenuManager; import org.chromium.chrome.browser.native_page.ContextMenuManager;
import org.chromium.chrome.browser.ntp.NewTabPageLayout; import org.chromium.chrome.browser.ntp.NewTabPageLayout;
import org.chromium.chrome.browser.ntp.SnapScrollHelper; import org.chromium.chrome.browser.ntp.SnapScrollHelper;
...@@ -67,7 +66,7 @@ public class FeedSurfaceCoordinator { ...@@ -67,7 +66,7 @@ public class FeedSurfaceCoordinator {
private final FeedSurfaceMediator mMediator; private final FeedSurfaceMediator mMediator;
private UiConfig mUiConfig; private UiConfig mUiConfig;
private HistoryNavigationLayout mRootView; private FrameLayout mRootView;
private ContextMenuManager mContextMenuManager; private ContextMenuManager mContextMenuManager;
// Used when Feed is enabled. // Used when Feed is enabled.
...@@ -223,7 +222,7 @@ public class FeedSurfaceCoordinator { ...@@ -223,7 +222,7 @@ public class FeedSurfaceCoordinator {
/** /**
* Provides the additional capabilities needed for the container view. * Provides the additional capabilities needed for the container view.
*/ */
private class RootView extends HistoryNavigationLayout { private class RootView extends FrameLayout {
/** /**
* @param context The context of the application. * @param context The context of the application.
*/ */
...@@ -265,7 +264,6 @@ public class FeedSurfaceCoordinator { ...@@ -265,7 +264,6 @@ public class FeedSurfaceCoordinator {
* Constructs a new FeedSurfaceCoordinator. * Constructs a new FeedSurfaceCoordinator.
* *
* @param activity The containing {@link ChromeActivity}. * @param activity The containing {@link ChromeActivity}.
* @param historyNavigationDelegate The {@link HistoryNavigationDelegate} for the root view.
* @param snapScrollHelper The {@link SnapScrollHelper} for the New Tab Page. * @param snapScrollHelper The {@link SnapScrollHelper} for the New Tab Page.
* @param ntpHeader The extra header on top of the feeds for the New Tab Page. * @param ntpHeader The extra header on top of the feeds for the New Tab Page.
* @param sectionHeaderView The {@link SectionHeaderView} for the feed. * @param sectionHeaderView The {@link SectionHeaderView} for the feed.
...@@ -274,7 +272,6 @@ public class FeedSurfaceCoordinator { ...@@ -274,7 +272,6 @@ public class FeedSurfaceCoordinator {
* @param delegate The constructing {@link FeedSurfaceDelegate}. * @param delegate The constructing {@link FeedSurfaceDelegate}.
*/ */
public FeedSurfaceCoordinator(ChromeActivity activity, public FeedSurfaceCoordinator(ChromeActivity activity,
@Nullable HistoryNavigationDelegate historyNavigationDelegate,
@Nullable SnapScrollHelper snapScrollHelper, @Nullable View ntpHeader, @Nullable SnapScrollHelper snapScrollHelper, @Nullable View ntpHeader,
@Nullable SectionHeaderView sectionHeaderView, ActionApi actionApi, @Nullable SectionHeaderView sectionHeaderView, ActionApi actionApi,
boolean showDarkBackground, FeedSurfaceDelegate delegate) { boolean showDarkBackground, FeedSurfaceDelegate delegate) {
...@@ -292,9 +289,6 @@ public class FeedSurfaceCoordinator { ...@@ -292,9 +289,6 @@ public class FeedSurfaceCoordinator {
mRootView = new RootView(mActivity); mRootView = new RootView(mActivity);
mRootView.setPadding(0, resources.getDimensionPixelOffset(R.dimen.tab_strip_height), 0, 0); mRootView.setPadding(0, resources.getDimensionPixelOffset(R.dimen.tab_strip_height), 0, 0);
if (historyNavigationDelegate != null) {
mRootView.setNavigationDelegate(historyNavigationDelegate);
}
mUiConfig = new UiConfig(mRootView); mUiConfig = new UiConfig(mRootView);
// Mediator should be created before any Stream changes. // Mediator should be created before any Stream changes.
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
Use of this source code is governed by a BSD-style license that can be Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. --> found in the LICENSE file. -->
<org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout <FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/history_navigation" android:id="@+id/history_navigation"
...@@ -15,4 +15,4 @@ ...@@ -15,4 +15,4 @@
android:scrollbars="vertical" android:scrollbars="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
</org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout> </FrameLayout>
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
found in the LICENSE file. --> found in the LICENSE file. -->
<!-- This single-child FrameLayout is needed for its top padding. --> <!-- This single-child FrameLayout is needed for its top padding. -->
<org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout <FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/history_navigation" android:id="@+id/history_navigation"
android:layout_width="match_parent" android:layout_width="match_parent"
...@@ -33,4 +33,4 @@ ...@@ -33,4 +33,4 @@
android:scrollbarStyle="outsideOverlay" /> android:scrollbarStyle="outsideOverlay" />
</org.chromium.chrome.browser.ntp.NativePageRootFrameLayout> </org.chromium.chrome.browser.ntp.NativePageRootFrameLayout>
</org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout> </FrameLayout>
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
android:layout_height="@dimen/toolbar_height_no_shadow" android:layout_height="@dimen/toolbar_height_no_shadow"
android:background="@color/default_primary_color" /> android:background="@color/default_primary_color" />
<org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout <FrameLayout
android:id="@+id/list_content" android:id="@+id/list_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" /> android:layout_gravity="center" />
</org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout> </FrameLayout>
<org.chromium.components.browser_ui.widget.FadingShadowView <org.chromium.components.browser_ui.widget.FadingShadowView
android:id="@+id/shadow" android:id="@+id/shadow"
......
...@@ -2165,14 +2165,15 @@ public class ChromeTabbedActivity extends ChromeActivity implements ScreenshotMo ...@@ -2165,14 +2165,15 @@ public class ChromeTabbedActivity extends ChromeActivity implements ScreenshotMo
} }
private void showFullHistoryOnNavigationSheet(Tab tab) { private void showFullHistoryOnNavigationSheet(Tab tab) {
// TODO(jinsukkim): Make NavigationSheet a per-activity object using RootUiCoordinator. // Another instance of NavigationSheet(for gesture navigation) may be running.
if (NavigationSheet.isInstanceShowing(getBottomSheetController())) { if (NavigationSheet.isInstanceShowing(getBottomSheetController())) {
mNavigationSheet = null; mNavigationSheet = null;
return; return;
} }
mNavigationSheet = NavigationSheet.create( mNavigationSheet = NavigationSheet.create(
getWindow().getDecorView().findViewById(android.R.id.content), this, getWindow().getDecorView().findViewById(android.R.id.content), this,
this::getBottomSheetController, new TabbedSheetDelegate(tab)); this::getBottomSheetController);
mNavigationSheet.setDelegate(new TabbedSheetDelegate(tab));
if (!mNavigationSheet.startAndExpand(/* forward=*/false, /* animate=*/true)) { if (!mNavigationSheet.startAndExpand(/* forward=*/false, /* animate=*/true)) {
mNavigationSheet = null; mNavigationSheet = null;
} else { } else {
......
...@@ -6,8 +6,6 @@ package org.chromium.chrome.browser; ...@@ -6,8 +6,6 @@ package org.chromium.chrome.browser;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams; import android.view.ViewGroup.LayoutParams;
...@@ -18,9 +16,6 @@ import org.chromium.base.TraceEvent; ...@@ -18,9 +16,6 @@ import org.chromium.base.TraceEvent;
import org.chromium.base.metrics.RecordUserAction; import org.chromium.base.metrics.RecordUserAction;
import org.chromium.base.task.PostTask; import org.chromium.base.task.PostTask;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegate;
import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegateFactory;
import org.chromium.chrome.browser.gesturenav.NavigationGlowFactory;
import org.chromium.chrome.browser.gesturenav.NavigationHandler; import org.chromium.chrome.browser.gesturenav.NavigationHandler;
import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.EmptyTabObserver;
import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab;
...@@ -35,8 +30,8 @@ import org.chromium.ui.OverscrollRefreshHandler; ...@@ -35,8 +30,8 @@ import org.chromium.ui.OverscrollRefreshHandler;
* An overscroll handler implemented in terms a modified version of the Android * An overscroll handler implemented in terms a modified version of the Android
* compat library's SwipeRefreshLayout effect. * compat library's SwipeRefreshLayout effect.
*/ */
public class SwipeRefreshHandler extends TabWebContentsUserData public class SwipeRefreshHandler
implements OverscrollRefreshHandler, OnAttachStateChangeListener { extends TabWebContentsUserData implements OverscrollRefreshHandler {
private static final Class<SwipeRefreshHandler> USER_DATA_KEY = SwipeRefreshHandler.class; private static final Class<SwipeRefreshHandler> USER_DATA_KEY = SwipeRefreshHandler.class;
// Synthetic delay between the {@link #didStopRefreshing()} signal and the // Synthetic delay between the {@link #didStopRefreshing()} signal and the
...@@ -73,15 +68,11 @@ public class SwipeRefreshHandler extends TabWebContentsUserData ...@@ -73,15 +68,11 @@ public class SwipeRefreshHandler extends TabWebContentsUserData
// Accessibility utterance used to indicate refresh activation. // Accessibility utterance used to indicate refresh activation.
private String mAccessibilityRefreshString; private String mAccessibilityRefreshString;
// Overscroll Navigation delegate providing info/object constructor. // Handles overscroll history navigation. Gesture events from native layer are forwarded
private HistoryNavigationDelegate mNavigationDelegate = // to this object. Remains null while navigation feature is disabled due to feature flag,
HistoryNavigationDelegateFactory.DEFAULT; // system settings (Q and forward), etc.
// Handles overscroll history navigation.
private NavigationHandler mNavigationHandler; private NavigationHandler mNavigationHandler;
private NavigationHandler.ActionDelegate mActionDelegate;
public static SwipeRefreshHandler from(Tab tab) { public static SwipeRefreshHandler from(Tab tab) {
SwipeRefreshHandler handler = get(tab); SwipeRefreshHandler handler = get(tab);
if (handler == null) { if (handler == null) {
...@@ -117,7 +108,6 @@ public class SwipeRefreshHandler extends TabWebContentsUserData ...@@ -117,7 +108,6 @@ public class SwipeRefreshHandler extends TabWebContentsUserData
} }
}; };
mTab.addObserver(mTabObserver); mTab.addObserver(mTabObserver);
mNavigationDelegate = HistoryNavigationDelegateFactory.create(tab);
} }
private void initSwipeRefreshLayout(final Context context) { private void initSwipeRefreshLayout(final Context context) {
...@@ -156,9 +146,6 @@ public class SwipeRefreshHandler extends TabWebContentsUserData ...@@ -156,9 +146,6 @@ public class SwipeRefreshHandler extends TabWebContentsUserData
public void initWebContents(WebContents webContents) { public void initWebContents(WebContents webContents) {
webContents.setOverscrollRefreshHandler(this); webContents.setOverscrollRefreshHandler(this);
mContainerView = mTab.getContentView(); mContainerView = mTab.getContentView();
mContainerView.addOnAttachStateChangeListener(this);
mNavigationDelegate.setWindowInsetsChangeObserver(
mContainerView, () -> updateNavigationHandler());
setEnabled(true); setEnabled(true);
} }
...@@ -166,25 +153,11 @@ public class SwipeRefreshHandler extends TabWebContentsUserData ...@@ -166,25 +153,11 @@ public class SwipeRefreshHandler extends TabWebContentsUserData
@Override @Override
public void cleanupWebContents(WebContents webContents) { public void cleanupWebContents(WebContents webContents) {
if (mSwipeRefreshLayout != null) detachSwipeRefreshLayoutIfNecessary(); if (mSwipeRefreshLayout != null) detachSwipeRefreshLayoutIfNecessary();
mContainerView.removeOnAttachStateChangeListener(this);
mNavigationDelegate.setWindowInsetsChangeObserver(mContainerView, null);
mContainerView = null; mContainerView = null;
if (mNavigationHandler != null) {
mNavigationHandler.destroy();
mNavigationHandler = null; mNavigationHandler = null;
mActionDelegate = null;
}
setEnabled(false); setEnabled(false);
} }
@Override
public void onViewAttachedToWindow(View v) {
updateNavigationHandler();
}
@Override
public void onViewDetachedFromWindow(View v) {}
@Override @Override
public void destroyInternal() { public void destroyInternal() {
if (mSwipeRefreshLayout != null) { if (mSwipeRefreshLayout != null) {
...@@ -215,36 +188,22 @@ public class SwipeRefreshHandler extends TabWebContentsUserData ...@@ -215,36 +188,22 @@ public class SwipeRefreshHandler extends TabWebContentsUserData
return mSwipeRefreshLayout.start(); return mSwipeRefreshLayout.start();
} else if (type == OverscrollAction.HISTORY_NAVIGATION) { } else if (type == OverscrollAction.HISTORY_NAVIGATION) {
if (mNavigationHandler != null) { if (mNavigationHandler != null) {
boolean navigable = mActionDelegate.canNavigate(navigateForward);
boolean showGlow = navigateForward && !mTab.canGoForward();
mNavigationHandler.onDown(); // Simulates the initial onDown event. mNavigationHandler.onDown(); // Simulates the initial onDown event.
if (navigable) { boolean navigable = mNavigationHandler.navigate(navigateForward, startX, startY);
mNavigationHandler.showArrowWidget(navigateForward); boolean showGlow = navigateForward && !mTab.canGoForward();
} else if (showGlow) { return showGlow || navigable;
mNavigationHandler.showGlow(startX, startY);
}
return navigable || showGlow;
} }
} }
mSwipeType = OverscrollAction.NONE; mSwipeType = OverscrollAction.NONE;
return false; return false;
} }
private void updateNavigationHandler() { /**
if (mNavigationDelegate.isNavigationEnabled(mContainerView)) { * Sets {@link NavigationHandler} object.
if (mNavigationHandler == null) { * @param layout {@link NavigationHandler} object.
mActionDelegate = mNavigationDelegate.createActionDelegate(); */
mNavigationHandler = new NavigationHandler(mContainerView, mTab.getContext(), public void setNavigationHandler(NavigationHandler navigationHandler) {
mNavigationDelegate, mNavigationHandler = navigationHandler;
NavigationGlowFactory.forRenderedPage(
mContainerView, mTab.getWebContents()));
}
} else {
if (mNavigationHandler != null) {
mNavigationHandler.destroy();
mNavigationHandler = null;
}
}
} }
@Override @Override
......
...@@ -25,7 +25,6 @@ import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; ...@@ -25,7 +25,6 @@ import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem;
import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver;
import org.chromium.chrome.browser.favicon.LargeIconBridge; import org.chromium.chrome.browser.favicon.LargeIconBridge;
import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegate;
import org.chromium.chrome.browser.native_page.BasicNativePage; import org.chromium.chrome.browser.native_page.BasicNativePage;
import org.chromium.chrome.browser.partnerbookmarks.PartnerBookmarksReader; import org.chromium.chrome.browser.partnerbookmarks.PartnerBookmarksReader;
import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.Profile;
...@@ -357,14 +356,6 @@ public class BookmarkManager ...@@ -357,14 +356,6 @@ public class BookmarkManager
mNativePage = nativePage; mNativePage = nativePage;
} }
/**
* Sets the delegate object needed for history navigation logic.
* @param delegate {@link HistoryNavigationDelegate} object.
*/
public void setHistoryNavigationDelegate(HistoryNavigationDelegate delegate) {
mSelectableListLayout.setHistoryNavigationDelegate(delegate);
}
/** /**
* @return Current URL representing the UI state of bookmark manager. If no state has been shown * @return Current URL representing the UI state of bookmark manager. If no state has been shown
* yet in this session, on phone return last used state stored in preference; on tablet * yet in this session, on phone return last used state stored in preference; on tablet
......
...@@ -29,7 +29,6 @@ public class BookmarkPage extends BasicNativePage { ...@@ -29,7 +29,6 @@ public class BookmarkPage extends BasicNativePage {
mManager = new BookmarkManager(activity, false, activity.getSnackbarManager()); mManager = new BookmarkManager(activity, false, activity.getSnackbarManager());
mManager.setBasicNativePage(this); mManager.setBasicNativePage(this);
mManager.setHistoryNavigationDelegate(host.createHistoryNavigationDelegate());
mTitle = host.getContext().getResources().getString(R.string.bookmarks); mTitle = host.getContext().getResources().getString(R.string.bookmarks);
initWithView(mManager.getView()); initWithView(mManager.getView());
......
...@@ -32,6 +32,7 @@ import android.widget.FrameLayout; ...@@ -32,6 +32,7 @@ import android.widget.FrameLayout;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.ObserverList;
import org.chromium.base.SysUtils; import org.chromium.base.SysUtils;
import org.chromium.base.TraceEvent; import org.chromium.base.TraceEvent;
import org.chromium.base.compat.ApiHelperForN; import org.chromium.base.compat.ApiHelperForN;
...@@ -87,6 +88,27 @@ public class CompositorViewHolder extends FrameLayout ...@@ -87,6 +88,27 @@ public class CompositorViewHolder extends FrameLayout
CompositorViewResizer.Observer { CompositorViewResizer.Observer {
private static final long SYSTEM_UI_VIEWPORT_UPDATE_DELAY_MS = 500; private static final long SYSTEM_UI_VIEWPORT_UPDATE_DELAY_MS = 500;
/**
* Observer interface for any object that needs to process touch events.
*/
public interface TouchEventObserver {
/**
* Determine if touch events should be forwarded to the observing object.
* Should return {@link true} if the object decided to consume the events.
* @param e {@link MotionEvent} object to process.
* @return {@code true} if the observer will process touch events going forward.
*/
boolean shouldInterceptTouchEvent(MotionEvent e);
/**
* Handle touch events.
* @param e {@link MotionEvent} object to process.
*/
void handleTouchEvent(MotionEvent e);
}
private ObserverList<TouchEventObserver> mTouchEventObservers = new ObserverList<>();
private EventOffsetHandler mEventOffsetHandler; private EventOffsetHandler mEventOffsetHandler;
private boolean mIsKeyboardShowing; private boolean mIsKeyboardShowing;
...@@ -558,10 +580,28 @@ public class CompositorViewHolder extends FrameLayout ...@@ -558,10 +580,28 @@ public class CompositorViewHolder extends FrameLayout
return mInvalidator; return mInvalidator;
} }
/**
* Add observer that needs to listen and process touch events.
* @param o {@link TouchEventObserver} object.
*/
public void addTouchEventObserver(TouchEventObserver o) {
mTouchEventObservers.addObserver(o);
}
/**
* Remove observer that needs to listen and process touch events.
* @param o {@link TouchEventObserver} object.
*/
public void removeTouchEventObserver(TouchEventObserver o) {
mTouchEventObservers.removeObserver(o);
}
@Override @Override
public boolean onInterceptTouchEvent(MotionEvent e) { public boolean onInterceptTouchEvent(MotionEvent e) {
super.onInterceptTouchEvent(e); super.onInterceptTouchEvent(e);
for (TouchEventObserver o : mTouchEventObservers) {
if (o.shouldInterceptTouchEvent(e)) return true;
}
if (mLayoutManager == null) return false; if (mLayoutManager == null) return false;
mEventOffsetHandler.onInterceptTouchEvent(e); mEventOffsetHandler.onInterceptTouchEvent(e);
...@@ -605,6 +645,7 @@ public class CompositorViewHolder extends FrameLayout ...@@ -605,6 +645,7 @@ public class CompositorViewHolder extends FrameLayout
@Override @Override
public boolean dispatchTouchEvent(MotionEvent e) { public boolean dispatchTouchEvent(MotionEvent e) {
updateLastActiveTouchEvent(e); updateLastActiveTouchEvent(e);
for (TouchEventObserver o : mTouchEventObservers) o.handleTouchEvent(e);
return super.dispatchTouchEvent(e); return super.dispatchTouchEvent(e);
} }
......
...@@ -47,7 +47,6 @@ public class DownloadPage extends BasicNativePage implements DownloadManagerCoor ...@@ -47,7 +47,6 @@ public class DownloadPage extends BasicNativePage implements DownloadManagerCoor
activity.getModalDialogManager()); activity.getModalDialogManager());
mDownloadCoordinator.addObserver(this); mDownloadCoordinator.addObserver(this);
mDownloadCoordinator.setHistoryNavigationDelegate(host.createHistoryNavigationDelegate());
mTitle = activity.getString(R.string.menu_downloads); mTitle = activity.getString(R.string.menu_downloads);
// #destroy() unregisters the ActivityStateListener to avoid checking for externally removed // #destroy() unregisters the ActivityStateListener to avoid checking for externally removed
......
...@@ -6,8 +6,6 @@ package org.chromium.chrome.browser.download.home; ...@@ -6,8 +6,6 @@ package org.chromium.chrome.browser.download.home;
import android.view.View; import android.view.View;
import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegate;
/** /**
* A coordinator that represents the main download manager UI page. This visually shows a list of * A coordinator that represents the main download manager UI page. This visually shows a list of
* downloaded items and allows the user to interact with those items. * downloaded items and allows the user to interact with those items.
...@@ -42,10 +40,4 @@ public interface DownloadManagerCoordinator { ...@@ -42,10 +40,4 @@ public interface DownloadManagerCoordinator {
/** Stops notifying {@code observer} of url state changes. */ /** Stops notifying {@code observer} of url state changes. */
void removeObserver(Observer observer); void removeObserver(Observer observer);
/**
* Sets the {@link HistoryNavigationDelegate} object that takes care of history navigation.
* @param delegate The delegate instance the history navigation logic needs.
*/
void setHistoryNavigationDelegate(HistoryNavigationDelegate delegate);
} }
...@@ -7,6 +7,7 @@ package org.chromium.chrome.browser.download.home; ...@@ -7,6 +7,7 @@ package org.chromium.chrome.browser.download.home;
import android.app.Activity; import android.app.Activity;
import android.view.Gravity; import android.view.Gravity;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ApiCompatibilityUtils;
...@@ -20,8 +21,6 @@ import org.chromium.chrome.browser.download.home.list.ListItem; ...@@ -20,8 +21,6 @@ import org.chromium.chrome.browser.download.home.list.ListItem;
import org.chromium.chrome.browser.download.home.snackbars.DeleteUndoCoordinator; import org.chromium.chrome.browser.download.home.snackbars.DeleteUndoCoordinator;
import org.chromium.chrome.browser.download.home.toolbar.ToolbarCoordinator; import org.chromium.chrome.browser.download.home.toolbar.ToolbarCoordinator;
import org.chromium.chrome.browser.download.items.OfflineContentAggregatorFactory; import org.chromium.chrome.browser.download.items.OfflineContentAggregatorFactory;
import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegate;
import org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout;
import org.chromium.chrome.browser.settings.SettingsLauncher; import org.chromium.chrome.browser.settings.SettingsLauncher;
import org.chromium.chrome.browser.settings.download.DownloadSettings; import org.chromium.chrome.browser.settings.download.DownloadSettings;
import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
...@@ -44,11 +43,10 @@ class DownloadManagerCoordinatorImpl ...@@ -44,11 +43,10 @@ class DownloadManagerCoordinatorImpl
private final ToolbarCoordinator mToolbarCoordinator; private final ToolbarCoordinator mToolbarCoordinator;
private final SelectionDelegate<ListItem> mSelectionDelegate; private final SelectionDelegate<ListItem> mSelectionDelegate;
private SelectionDelegate.SelectionObserver<ListItem> mNavigationCanceller;
private final Activity mActivity; private final Activity mActivity;
private HistoryNavigationLayout mMainView; private ViewGroup mMainView;
private boolean mMuteFilterChanges; private boolean mMuteFilterChanges;
...@@ -75,7 +73,7 @@ class DownloadManagerCoordinatorImpl ...@@ -75,7 +73,7 @@ class DownloadManagerCoordinatorImpl
* TODO(crbug.com/880468) : Investigate if it is better to do in XML. * TODO(crbug.com/880468) : Investigate if it is better to do in XML.
*/ */
private void initializeView() { private void initializeView() {
mMainView = new HistoryNavigationLayout(mActivity); mMainView = new FrameLayout(mActivity);
mMainView.setBackgroundColor(ApiCompatibilityUtils.getColor( mMainView.setBackgroundColor(ApiCompatibilityUtils.getColor(
mActivity.getResources(), R.color.modern_primary_color)); mActivity.getResources(), R.color.modern_primary_color));
...@@ -85,10 +83,6 @@ class DownloadManagerCoordinatorImpl ...@@ -85,10 +83,6 @@ class DownloadManagerCoordinatorImpl
mActivity.getResources().getDimensionPixelOffset(R.dimen.toolbar_height_no_shadow), mActivity.getResources().getDimensionPixelOffset(R.dimen.toolbar_height_no_shadow),
0, 0); 0, 0);
mMainView.addView(mListCoordinator.getView(), listParams); mMainView.addView(mListCoordinator.getView(), listParams);
mNavigationCanceller = (selectedItems) -> {
if (!selectedItems.isEmpty()) mMainView.release();
};
mSelectionDelegate.addObserver(mNavigationCanceller);
FrameLayout.LayoutParams toolbarParams = new FrameLayout.LayoutParams( FrameLayout.LayoutParams toolbarParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT); FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
...@@ -118,7 +112,6 @@ class DownloadManagerCoordinatorImpl ...@@ -118,7 +112,6 @@ class DownloadManagerCoordinatorImpl
mDeleteCoordinator.destroy(); mDeleteCoordinator.destroy();
mListCoordinator.destroy(); mListCoordinator.destroy();
mToolbarCoordinator.destroy(); mToolbarCoordinator.destroy();
mSelectionDelegate.removeObserver(mNavigationCanceller);
} }
@Override @Override
...@@ -150,11 +143,6 @@ class DownloadManagerCoordinatorImpl ...@@ -150,11 +143,6 @@ class DownloadManagerCoordinatorImpl
mObservers.removeObserver(observer); mObservers.removeObserver(observer);
} }
@Override
public void setHistoryNavigationDelegate(HistoryNavigationDelegate delegate) {
mMainView.setNavigationDelegate(delegate);
}
// ToolbarActionDelegate implementation. // ToolbarActionDelegate implementation.
@Override @Override
public void close() { public void close() {
......
...@@ -11,6 +11,7 @@ import android.support.v7.widget.RecyclerView; ...@@ -11,6 +11,7 @@ import android.support.v7.widget.RecyclerView;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.format.DateUtils; import android.text.format.DateUtils;
import android.util.Base64; import android.util.Base64;
import android.view.ViewGroup;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
...@@ -22,7 +23,6 @@ import org.chromium.base.metrics.RecordUserAction; ...@@ -22,7 +23,6 @@ import org.chromium.base.metrics.RecordUserAction;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.favicon.RoundedIconGenerator; import org.chromium.chrome.browser.favicon.RoundedIconGenerator;
import org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout;
import org.chromium.chrome.browser.native_page.BasicNativePage; import org.chromium.chrome.browser.native_page.BasicNativePage;
import org.chromium.chrome.browser.native_page.ContextMenuManager; import org.chromium.chrome.browser.native_page.ContextMenuManager;
import org.chromium.chrome.browser.native_page.NativePageHost; import org.chromium.chrome.browser.native_page.NativePageHost;
...@@ -96,7 +96,7 @@ public class ExploreSitesPage extends BasicNativePage { ...@@ -96,7 +96,7 @@ public class ExploreSitesPage extends BasicNativePage {
private Tab mTab; private Tab mTab;
private TabObserver mTabObserver; private TabObserver mTabObserver;
private Profile mProfile; private Profile mProfile;
private HistoryNavigationLayout mView; private ViewGroup mView;
private RecyclerView mRecyclerView; private RecyclerView mRecyclerView;
private StableScrollLayoutManager mLayoutManager; private StableScrollLayoutManager mLayoutManager;
private String mTitle; private String mTitle;
...@@ -177,7 +177,7 @@ public class ExploreSitesPage extends BasicNativePage { ...@@ -177,7 +177,7 @@ public class ExploreSitesPage extends BasicNativePage {
mTab = tab; mTab = tab;
mTitle = activity.getString(R.string.explore_sites_title); mTitle = activity.getString(R.string.explore_sites_title);
mView = (HistoryNavigationLayout) activity.getLayoutInflater().inflate( mView = (ViewGroup) activity.getLayoutInflater().inflate(
R.layout.explore_sites_page_layout, null); R.layout.explore_sites_page_layout, null);
mProfile = ((TabImpl) mTab).getProfile(); mProfile = ((TabImpl) mTab).getProfile();
...@@ -246,7 +246,6 @@ public class ExploreSitesPage extends BasicNativePage { ...@@ -246,7 +246,6 @@ public class ExploreSitesPage extends BasicNativePage {
CategoryCardAdapter adapterDelegate = new CategoryCardAdapter( CategoryCardAdapter adapterDelegate = new CategoryCardAdapter(
mModel, mLayoutManager, iconGenerator, mContextMenuManager, navDelegate, mProfile); mModel, mLayoutManager, iconGenerator, mContextMenuManager, navDelegate, mProfile);
mView.setNavigationDelegate(host.createHistoryNavigationDelegate());
mRecyclerView = mView.findViewById(R.id.explore_sites_category_recycler); mRecyclerView = mView.findViewById(R.id.explore_sites_category_recycler);
CategoryCardViewHolderFactory factory = createCategoryCardViewHolderFactory(); CategoryCardViewHolderFactory factory = createCategoryCardViewHolderFactory();
......
...@@ -20,7 +20,7 @@ public class AndroidUiNavigationGlow extends NavigationGlow { ...@@ -20,7 +20,7 @@ public class AndroidUiNavigationGlow extends NavigationGlow {
* Amount of time we wait before {@link GlowView} gets detached from parent view * Amount of time we wait before {@link GlowView} gets detached from parent view
* after the glow effect is completed. * after the glow effect is completed.
*/ */
private final static int REMOVE_RUNNABLE_DELAY_MS = 500; private static final int REMOVE_RUNNABLE_DELAY_MS = 500;
private final Runnable mRemoveGlowViewRunnable; private final Runnable mRemoveGlowViewRunnable;
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.gesturenav;
import android.graphics.Insets;
import android.graphics.Rect;
import android.os.Build;
import android.view.View;
import org.chromium.base.supplier.Supplier;
import org.chromium.chrome.browser.ActivityTabProvider;
import org.chromium.chrome.browser.ActivityTabProvider.ActivityTabTabObserver;
import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.InsetObserverView;
import org.chromium.chrome.browser.SwipeRefreshHandler;
import org.chromium.chrome.browser.compositor.CompositorViewHolder;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
import org.chromium.chrome.browser.lifecycle.Destroyable;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabImpl;
import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController;
import org.chromium.content_public.browser.WebContents;
/**
* Coordinator object for gesture navigation.
*/
public class HistoryNavigationCoordinator
implements InsetObserverView.WindowInsetObserver, Destroyable {
private CompositorViewHolder mCompositorViewHolder;
private HistoryNavigationLayout mNavigationLayout;
private InsetObserverView mInsetObserverView;
private ActivityTabTabObserver mActivityTabObserver;
private ActivityLifecycleDispatcher mActivityLifecycleDispatcher;
private Tab mTab;
/**
* Initializes the navigation layout and internal objects.
* @param compositorViewHolder Parent view for navigation layout.
* @param tabProvider Activity tab provider.
* @param insetObserverView View that provides information about the inset and inset
* capabilities of the device.
*/
public void init(ActivityLifecycleDispatcher lifecycleDispatcher,
CompositorViewHolder compositorViewHolder, ActivityTabProvider tabProvider,
InsetObserverView insetObserverView) {
mNavigationLayout = new HistoryNavigationLayout(compositorViewHolder.getContext());
mCompositorViewHolder = compositorViewHolder;
mActivityLifecycleDispatcher = lifecycleDispatcher;
lifecycleDispatcher.register(this);
compositorViewHolder.addView(mNavigationLayout);
compositorViewHolder.addTouchEventObserver(mNavigationLayout);
mActivityTabObserver = new ActivityTabProvider.ActivityTabTabObserver(tabProvider) {
@Override
protected void onObservingDifferentTab(Tab tab) {
if (mTab == tab) return;
onTabSwitched(tab);
}
@Override
public void onContentChanged(Tab tab) {
initNavigationHandler(
tab, createDelegate(tab), tab.getWebContents(), tab.isNativePage());
}
};
// We wouldn't hear about the first tab until the content changed or we switched tabs
// if tabProvider.get() != null. Do here what we do when tab switching happens.
if (tabProvider.get() != null) onTabSwitched(tabProvider.get());
mNavigationLayout.setVisibility(View.INVISIBLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
mInsetObserverView = insetObserverView;
insetObserverView.addObserver(this);
}
}
/**
* Creates {@link HistoryNavigationDelegate} for native/rendered pages on Tab.
*/
private static HistoryNavigationDelegate createDelegate(Tab tab) {
if (!isFeatureFlagEnabled() || ((TabImpl) tab).getActivity() == null) {
return HistoryNavigationDelegate.DEFAULT;
}
return new HistoryNavigationDelegate() {
// TODO(jinsukkim): Avoid getting activity from tab.
private final Supplier<BottomSheetController> mController = () -> {
ChromeActivity activity = ((TabImpl) tab).getActivity();
return activity == null || activity.isActivityFinishingOrDestroyed()
? null
: activity.getBottomSheetController();
};
@Override
public NavigationHandler.ActionDelegate createActionDelegate() {
return new TabbedActionDelegate(tab);
}
@Override
public NavigationSheet.Delegate createSheetDelegate() {
return new TabbedSheetDelegate(tab);
}
@Override
public Supplier<BottomSheetController> getBottomSheetController() {
return mController;
}
};
}
private static boolean isFeatureFlagEnabled() {
return ChromeFeatureList.isEnabled(ChromeFeatureList.OVERSCROLL_HISTORY_NAVIGATION);
}
@Override
public void onInsetChanged(int left, int top, int right, int bottom) {
// Resets navigation handler when the feature becomes disabled.
if (!isNavigationEnabled(mCompositorViewHolder)) {
initNavigationHandler(mTab, HistoryNavigationDelegate.DEFAULT, null, false);
}
}
private void onTabSwitched(Tab tab) {
WebContents webContents = tab != null ? tab.getWebContents() : null;
HistoryNavigationDelegate delegate =
webContents != null && isNavigationEnabled(mCompositorViewHolder)
? createDelegate(tab)
: HistoryNavigationDelegate.DEFAULT;
// Also resets NavigationHandler when there's no tab (going into TabSwitcher).
if (tab == null || webContents != null) {
initNavigationHandler(
tab, delegate, webContents, tab != null ? tab.isNativePage() : false);
}
}
/**
* @param view {@link View} object to obtain the navigation setting from.
* @return {@code true} if overscroll navigation is allowed to run on this page.
*/
private static boolean isNavigationEnabled(View view) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return true;
Insets insets = view.getRootWindowInsets().getSystemGestureInsets();
return insets.left == 0 && insets.right == 0;
}
private void initNavigationHandler(Tab tab, HistoryNavigationDelegate delegate,
WebContents webContents, boolean isNativePage) {
assert mNavigationLayout != null;
mNavigationLayout.initNavigationHandler(delegate, webContents, isNativePage);
if (mTab != tab) {
if (mTab != null) SwipeRefreshHandler.from(mTab).setNavigationHandler(null);
if (tab != null) {
SwipeRefreshHandler.from(tab).setNavigationHandler(
mNavigationLayout.getNavigationHandler());
}
mTab = tab;
}
}
@Override
public void onSafeAreaChanged(Rect area) {}
@Override
public void destroy() {
if (mActivityTabObserver != null) {
mActivityTabObserver.destroy();
mActivityTabObserver = null;
}
if (mInsetObserverView != null) {
mInsetObserverView.removeObserver(this);
mInsetObserverView = null;
}
if (mCompositorViewHolder != null && mNavigationLayout != null) {
mCompositorViewHolder.removeTouchEventObserver(mNavigationLayout);
mCompositorViewHolder = null;
}
if (mNavigationLayout != null) {
mNavigationLayout.destroy();
mNavigationLayout = null;
}
if (mActivityLifecycleDispatcher != null) {
mActivityLifecycleDispatcher.unregister(this);
mActivityLifecycleDispatcher = null;
}
}
}
...@@ -4,8 +4,6 @@ ...@@ -4,8 +4,6 @@
package org.chromium.chrome.browser.gesturenav; package org.chromium.chrome.browser.gesturenav;
import android.view.View;
import org.chromium.base.supplier.Supplier; import org.chromium.base.supplier.Supplier;
import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController; import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController;
...@@ -23,22 +21,29 @@ public interface HistoryNavigationDelegate { ...@@ -23,22 +21,29 @@ public interface HistoryNavigationDelegate {
*/ */
NavigationSheet.Delegate createSheetDelegate(); NavigationSheet.Delegate createSheetDelegate();
/**
* @param view {@link View} object to obtain the navigation setting from.
* @return {@code true} if overscroll navigation is allowed to run on this page.
*/
boolean isNavigationEnabled(View view);
/** /**
* @return {@link BottomSheetController} object. * @return {@link BottomSheetController} object.
*/ */
Supplier<BottomSheetController> getBottomSheetController(); Supplier<BottomSheetController> getBottomSheetController();
/** /**
* Observe window insets change to update navigation configutation dynamically. * Default {@link HistoryNavigationDelegate} that does not support navigation.
* @param view {@link View} to observe the insets change on.
* @param runnable {@link Runnable} to execute when insets change is detected.
* Pass {@code null} to reset the observation.
*/ */
void setWindowInsetsChangeObserver(View view, Runnable runnable); public static final HistoryNavigationDelegate DEFAULT = new HistoryNavigationDelegate() {
@Override
public NavigationHandler.ActionDelegate createActionDelegate() {
return null;
}
@Override
public NavigationSheet.Delegate createSheetDelegate() {
return null;
}
@Override
public Supplier<BottomSheetController> getBottomSheetController() {
assert false : "Should never be called";
return null;
}
};
} }
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.gesturenav;
import android.graphics.Insets;
import android.os.Build;
import android.view.View;
import android.view.WindowInsets;
import org.chromium.base.supplier.Supplier;
import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabImpl;
import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController;
/**
* Factory class for {@link HistoryNavigationDelegate}.
*/
public class HistoryNavigationDelegateFactory {
/**
* Default {@link HistoryNavigationDelegate} that does not support navigation. Mainly
* used for SnackbarActivity-based UI on the phone to disable the feature.
*/
public static final HistoryNavigationDelegate DEFAULT = new HistoryNavigationDelegate() {
@Override
public NavigationHandler.ActionDelegate createActionDelegate() {
return null;
}
@Override
public NavigationSheet.Delegate createSheetDelegate() {
return null;
}
@Override
public Supplier<BottomSheetController> getBottomSheetController() {
assert false : "Should never be called";
return null;
}
@Override
public boolean isNavigationEnabled(View view) {
return false;
}
@Override
public void setWindowInsetsChangeObserver(View view, Runnable runnable) {}
};
private HistoryNavigationDelegateFactory() {}
/**
* Creates {@link HistoryNavigationDelegate} for native/rendered pages on Tab.
*/
public static HistoryNavigationDelegate create(Tab tab) {
if (!isFeatureFlagEnabled() || ((TabImpl) tab).getActivity() == null) return DEFAULT;
return new HistoryNavigationDelegate() {
// TODO(jinsukkim): Avoid getting activity from tab.
private final Supplier<BottomSheetController> mController = () -> {
ChromeActivity activity = ((TabImpl) tab).getActivity();
return activity == null || activity.isActivityFinishingOrDestroyed()
? null
: activity.getBottomSheetController();
};
private Runnable mInsetsChangeRunnable;
@Override
public NavigationHandler.ActionDelegate createActionDelegate() {
return new TabbedActionDelegate(tab);
}
@Override
public NavigationSheet.Delegate createSheetDelegate() {
return new TabbedSheetDelegate(tab);
}
@Override
public Supplier<BottomSheetController> getBottomSheetController() {
return mController;
}
@Override
public boolean isNavigationEnabled(View view) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return true;
Insets insets = view.getRootWindowInsets().getSystemGestureInsets();
return insets.left == 0 && insets.right == 0;
}
@Override
public void setWindowInsetsChangeObserver(View view, Runnable runnable) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return;
mInsetsChangeRunnable = runnable;
view.setOnApplyWindowInsetsListener(
runnable != null ? this::onApplyWindowInsets : null);
}
private WindowInsets onApplyWindowInsets(View view, WindowInsets insets) {
assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q;
mInsetsChangeRunnable.run();
return insets;
}
};
}
private static boolean isFeatureFlagEnabled() {
return ChromeFeatureList.isEnabled(ChromeFeatureList.OVERSCROLL_HISTORY_NAVIGATION);
}
}
...@@ -5,88 +5,123 @@ ...@@ -5,88 +5,123 @@
package org.chromium.chrome.browser.gesturenav; package org.chromium.chrome.browser.gesturenav;
import android.content.Context; import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector; import android.view.GestureDetector;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import org.chromium.chrome.browser.compositor.CompositorViewHolder.TouchEventObserver;
import org.chromium.content_public.browser.WebContents;
/** /**
* FrameLayout that supports side-wise slide gesture for history navigation. Inheriting * FrameLayout that supports side-wise slide gesture for history navigation.
* class may need to override {@link #wasLastSideSwipeGestureConsumed()} if
* {@link #onTouchEvent} cannot be relied upon to know whether the side-swipe related
* event was handled. Namely {@link android.support.v7.widget.RecyclerView}) always
* claims to handle touch events.
* TODO(jinsukkim): Write a test verifying UI logic.
*/ */
public class HistoryNavigationLayout extends FrameLayout { public class HistoryNavigationLayout
extends FrameLayout implements TouchEventObserver, ViewGroup.OnHierarchyChangeListener {
private GestureDetector mDetector; private GestureDetector mDetector;
private NavigationHandler mNavigationHandler; private NavigationHandler mNavigationHandler;
private HistoryNavigationDelegate mDelegate = HistoryNavigationDelegateFactory.DEFAULT; private HistoryNavigationDelegate mDelegate;
private WebContents mWebContents;
private boolean mIsNativePage;
private NavigationGlow mJavaGlowEffect;
private NavigationGlow mCompositorGlowEffect;
public HistoryNavigationLayout(Context context) { public HistoryNavigationLayout(Context context) {
this(context, null); super(context);
} setOnHierarchyChangeListener(this);
public HistoryNavigationLayout(Context context, AttributeSet attrs) {
super(context, attrs);
} }
/** @Override
* Initializes navigation logic and internal objects if navigation is enabled. public void onChildViewAdded(View parent, View child) {
* @param delegate {@link HistoryNavigationDelegate} providing info and a factory method. if (getVisibility() != View.VISIBLE) setVisibility(View.VISIBLE);
*/
public void setNavigationDelegate(HistoryNavigationDelegate delegate) {
mDelegate = delegate;
// Navigation is potentially enabled only when the delegate is set.
delegate.setWindowInsetsChangeObserver(this, () -> updateNavigationHandler());
} }
@Override @Override
protected void onAttachedToWindow() { public void onChildViewRemoved(View parent, View child) {
super.onAttachedToWindow(); // TODO(jinsukkim): Replace INVISIBLE with GONE to avoid performing layout/measurements.
updateNavigationHandler(); if (getChildCount() == 0) setVisibility(View.INVISIBLE);
} }
@Override @Override
public void onDetachedFromWindow() { public void onDetachedFromWindow() {
super.onDetachedFromWindow(); super.onDetachedFromWindow();
// TODO(jinsukkim): There are callsites enabling HistoryNavigationLayout but
// failing to call |setNavigationDelegate| (or |setTab| before renaming).
// Find when it can happen.
if (mNavigationHandler != null) mNavigationHandler.reset(); if (mNavigationHandler != null) mNavigationHandler.reset();
} }
@Override @Override
public boolean dispatchTouchEvent(MotionEvent e) { public boolean shouldInterceptTouchEvent(MotionEvent e) {
if (mNavigationHandler != null) { // Forward gesture events only for native pages. Rendered pages receive events
// from SwipeRefreshHandler.
if (!mIsNativePage) return false;
return mNavigationHandler != null && mNavigationHandler.isActive();
}
@Override
public void handleTouchEvent(MotionEvent e) {
if (mNavigationHandler != null && mIsNativePage) {
mDetector.onTouchEvent(e); mDetector.onTouchEvent(e);
mNavigationHandler.onTouchEvent(e.getAction()); mNavigationHandler.onTouchEvent(e.getAction());
} }
return super.dispatchTouchEvent(e);
} }
private void updateNavigationHandler() { /**
if (mDelegate.isNavigationEnabled(this)) { * Initialize {@link NavigationHandler} object.
* @param delegate {@link HistoryNavigationDelegate} providing info and a factory method.
* @param webContents A new WebContents object.
* @param isNativePage {@code true} if the content is a native page.
*/
public void initNavigationHandler(
HistoryNavigationDelegate delegate, WebContents webContents, boolean isNativePage) {
if (mNavigationHandler == null) { if (mNavigationHandler == null) {
mDetector = new GestureDetector(getContext(), new SideNavGestureListener()); mDetector = new GestureDetector(getContext(), new SideNavGestureListener());
mNavigationHandler = new NavigationHandler( mNavigationHandler = new NavigationHandler(this, getContext(), this::getGlowEffect);
this, getContext(), mDelegate, NavigationGlowFactory.forJavaLayer(this)); }
if (mDelegate != delegate) {
mNavigationHandler.setDelegate(delegate);
mDelegate = delegate;
}
if (isNativePage == mIsNativePage && mWebContents == webContents) return;
if (mWebContents != webContents) resetCompositorGlow();
mWebContents = webContents;
mIsNativePage = isNativePage;
} }
/**
* Create {@link NavigationGlow} object lazily.
*/
private NavigationGlow getGlowEffect() {
if (mIsNativePage) {
if (mJavaGlowEffect == null) mJavaGlowEffect = new AndroidUiNavigationGlow(this);
return mJavaGlowEffect;
} else { } else {
mDetector = null; if (mCompositorGlowEffect == null) {
if (mNavigationHandler != null) { mCompositorGlowEffect = new CompositorNavigationGlow(this, mWebContents);
mNavigationHandler.destroy();
mNavigationHandler = null;
} }
return mCompositorGlowEffect;
} }
} }
@Override /**
public boolean onInterceptTouchEvent(MotionEvent e) { * Reset CompositorGlowEffect for new a WebContents. Destroy the current one
// Do not propagate touch events down to children if navigation UI was triggered. * (for its native object) so it can be created again lazily.
if (mDetector != null && mNavigationHandler.isActive()) return true; */
return super.onInterceptTouchEvent(e); private void resetCompositorGlow() {
if (mCompositorGlowEffect != null) {
mCompositorGlowEffect.destroy();
mCompositorGlowEffect = null;
}
}
/** @return Current {@link HistoryNavigationDelegate} object. */
public HistoryNavigationDelegate getDelegate() {
return mDelegate;
}
/** @return Current {@link NavigationHandler} object. */
public NavigationHandler getNavigationHandler() {
return mNavigationHandler;
} }
private class SideNavGestureListener extends GestureDetector.SimpleOnGestureListener { private class SideNavGestureListener extends GestureDetector.SimpleOnGestureListener {
...@@ -97,8 +132,7 @@ public class HistoryNavigationLayout extends FrameLayout { ...@@ -97,8 +132,7 @@ public class HistoryNavigationLayout extends FrameLayout {
@Override @Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
// |onScroll| needs handling only after the state moves away from |NONE|. This helps // |onScroll| needs handling only after the state moved away from |NONE|.
// invoke |wasLastSideSwipeGestureConsumed| which may be expensive less often.
if (mNavigationHandler.isStopped()) return true; if (mNavigationHandler.isStopped()) return true;
return mNavigationHandler.onScroll( return mNavigationHandler.onScroll(
...@@ -112,4 +146,16 @@ public class HistoryNavigationLayout extends FrameLayout { ...@@ -112,4 +146,16 @@ public class HistoryNavigationLayout extends FrameLayout {
public void release() { public void release() {
if (mNavigationHandler != null) mNavigationHandler.release(false); if (mNavigationHandler != null) mNavigationHandler.release(false);
} }
/**
* Performs cleanup upon destruction.
*/
void destroy() {
resetCompositorGlow();
mDelegate = HistoryNavigationDelegate.DEFAULT;
if (mNavigationHandler != null) {
mNavigationHandler.setDelegate(mDelegate);
mNavigationHandler = null;
}
}
} }
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.gesturenav;
import android.view.ViewGroup;
import org.chromium.base.supplier.Supplier;
import org.chromium.content_public.browser.WebContents;
/**
* Factory class that provides {@link NavigationGlow} according to the actual surface
* the glow effect is rendered on.
*/
public class NavigationGlowFactory {
/**
* @pararm parentView Parent view where the glow view gets attached to.
* @pararm webContents WebContents whose native view's cc layer will be used
* for rendering glow effect.
* @return Supplier for {@link NavigationGlow} object for rendered pages.
*/
public static Supplier<NavigationGlow> forRenderedPage(
ViewGroup parentView, WebContents webContents) {
return () -> new CompositorNavigationGlow(parentView, webContents);
}
/**
* @pararm parentView Parent view where the glow view gets attached to.
* @return Supplier for {@link NavigationGlow} object for pages where glow effect can be
* rendered on the parent android view.
*/
public static Supplier<NavigationGlow> forJavaLayer(ViewGroup parentView) {
return () -> new AndroidUiNavigationGlow(parentView);
}
}
...@@ -46,12 +46,11 @@ public class NavigationHandler { ...@@ -46,12 +46,11 @@ public class NavigationHandler {
private final ViewGroup mParentView; private final ViewGroup mParentView;
private final Context mContext; private final Context mContext;
private final Supplier<NavigationGlow> mGlowEffectSupplier;
private final HistoryNavigationDelegate mDelegate; private HistoryNavigationDelegate mDelegate;
private final ActionDelegate mActionDelegate; private ActionDelegate mActionDelegate;
private NavigationGlow mGlowEffect; private Supplier<NavigationGlow> mGlowEffectSupplier;
private @GestureState int mState = GestureState.NONE; private @GestureState int mState = GestureState.NONE;
...@@ -95,13 +94,11 @@ public class NavigationHandler { ...@@ -95,13 +94,11 @@ public class NavigationHandler {
boolean willBackExitApp(); boolean willBackExitApp();
} }
public NavigationHandler(ViewGroup parentView, Context context, public NavigationHandler(
HistoryNavigationDelegate delegate, Supplier<NavigationGlow> glowEffectSupplier) { ViewGroup parentView, Context context, Supplier<NavigationGlow> glowEffect) {
mParentView = parentView; mParentView = parentView;
mContext = context; mContext = context;
mDelegate = delegate; mGlowEffectSupplier = glowEffect;
mActionDelegate = delegate.createActionDelegate();
mGlowEffectSupplier = glowEffectSupplier;
mEdgeWidthPx = EDGE_WIDTH_DP * parentView.getResources().getDisplayMetrics().density; mEdgeWidthPx = EDGE_WIDTH_DP * parentView.getResources().getDisplayMetrics().density;
} }
...@@ -114,7 +111,6 @@ public class NavigationHandler { ...@@ -114,7 +111,6 @@ public class NavigationHandler {
cancelStopNavigatingRunnable(); cancelStopNavigatingRunnable();
mSideSlideLayout.post(getStopNavigatingRunnable()); mSideSlideLayout.post(getStopNavigatingRunnable());
}); });
mSideSlideLayout.setOnResetListener(() -> { mSideSlideLayout.setOnResetListener(() -> {
if (mDetachLayoutRunnable != null) return; if (mDetachLayoutRunnable != null) return;
mDetachLayoutRunnable = () -> { mDetachLayoutRunnable = () -> {
...@@ -124,10 +120,21 @@ public class NavigationHandler { ...@@ -124,10 +120,21 @@ public class NavigationHandler {
mSideSlideLayout.post(mDetachLayoutRunnable); mSideSlideLayout.post(mDetachLayoutRunnable);
}); });
mNavigationSheet = NavigationSheet.isEnabled() mNavigationSheet = NavigationSheet.isEnabled() ? NavigationSheet.create(
? NavigationSheet.create(mParentView, mContext, mParentView, mContext, mDelegate.getBottomSheetController())
mDelegate.getBottomSheetController(), mDelegate.createSheetDelegate())
: NavigationSheet.DUMMY; : NavigationSheet.DUMMY;
mNavigationSheet.setDelegate(mDelegate.createSheetDelegate());
}
/**
* Sets {@link HistoryNavigationDelegate} object.
* Also creates new delegates, for horizontal gesture and bottom sheet processing.
* @param {@link HistoryNavigationDelegate} object.
*/
void setDelegate(HistoryNavigationDelegate delegate) {
mDelegate = delegate;
mActionDelegate = delegate.createActionDelegate();
if (mNavigationSheet != null) mNavigationSheet.setDelegate(delegate.createSheetDelegate());
} }
/** /**
...@@ -138,8 +145,8 @@ public class NavigationHandler { ...@@ -138,8 +145,8 @@ public class NavigationHandler {
if (mState == GestureState.DRAGGED && mSideSlideLayout != null) { if (mState == GestureState.DRAGGED && mSideSlideLayout != null) {
mSideSlideLayout.release(mNavigationSheet.isHidden()); mSideSlideLayout.release(mNavigationSheet.isHidden());
mNavigationSheet.release(); mNavigationSheet.release();
} else if (mState == GestureState.GLOW && mGlowEffect != null) { } else if (mState == GestureState.GLOW && mGlowEffectSupplier != null) {
mGlowEffect.release(); mGlowEffectSupplier.get().release();
} }
} }
} }
...@@ -167,15 +174,7 @@ public class NavigationHandler { ...@@ -167,15 +174,7 @@ public class NavigationHandler {
if (mState == GestureState.STARTED) { if (mState == GestureState.STARTED) {
if (shouldTriggerUi(startX, distanceX, distanceY)) { if (shouldTriggerUi(startX, distanceX, distanceY)) {
boolean forward = distanceX > 0; navigate(distanceX > 0, endX, endY);
if (mActionDelegate.canNavigate(forward)) {
showArrowWidget(forward);
} else {
// |forward| should be true if we get here, since navigating back
// is always possible.
assert forward;
showGlow(endX, endY);
}
} }
if (!isActive()) mState = GestureState.NONE; if (!isActive()) mState = GestureState.NONE;
} }
...@@ -188,11 +187,29 @@ public class NavigationHandler { ...@@ -188,11 +187,29 @@ public class NavigationHandler {
&& (sX < mEdgeWidthPx || (mParentView.getWidth() - mEdgeWidthPx) < sX); && (sX < mEdgeWidthPx || (mParentView.getWidth() - mEdgeWidthPx) < sX);
} }
/**
* Shows UI in response to gesture events.
* @param forward Direction of the swipe gesture. {@code true} if forward; else back.
* @param x The X position of the event.
* @param y The Y position of the event.
* @return {@code true} if the navigation can be triggered.
*/
public boolean navigate(boolean forward, float x, float y) {
assert mActionDelegate != null;
boolean navigable = mActionDelegate.canNavigate(forward);
if (navigable) {
showArrowWidget(forward);
} else {
showGlow(x, y);
}
return navigable;
}
/** /**
* Start showing arrow widget for navigation back/forward. * Start showing arrow widget for navigation back/forward.
* @param forward {@code true} if navigating forward. * @param forward {@code true} if navigating forward.
*/ */
public void showArrowWidget(boolean forward) { private void showArrowWidget(boolean forward) {
if (mState != GestureState.STARTED) reset(); if (mState != GestureState.STARTED) reset();
if (mSideSlideLayout == null) createLayout(); if (mSideSlideLayout == null) createLayout();
mSideSlideLayout.setEnabled(true); mSideSlideLayout.setEnabled(true);
...@@ -211,10 +228,9 @@ public class NavigationHandler { ...@@ -211,10 +228,9 @@ public class NavigationHandler {
* @param startX X coordinate of the touch event at the beginning. * @param startX X coordinate of the touch event at the beginning.
* @param startY Y coordinate of the touch event at the beginning. * @param startY Y coordinate of the touch event at the beginning.
*/ */
public void showGlow(float startX, float startY) { private void showGlow(float startX, float startY) {
if (mState != GestureState.STARTED) reset(); if (mState != GestureState.STARTED) reset();
if (mGlowEffect == null) mGlowEffect = mGlowEffectSupplier.get(); mGlowEffectSupplier.get().prepare(startX, startY);
mGlowEffect.prepare(startX, startY);
mState = GestureState.GLOW; mState = GestureState.GLOW;
} }
...@@ -252,8 +268,8 @@ public class NavigationHandler { ...@@ -252,8 +268,8 @@ public class NavigationHandler {
mSideSlideLayout.hideArrow(); mSideSlideLayout.hideArrow();
mState = GestureState.NONE; mState = GestureState.NONE;
} }
} else if (mState == GestureState.GLOW && mGlowEffect != null) { } else if (mState == GestureState.GLOW) {
mGlowEffect.onScroll(-delta); mGlowEffectSupplier.get().onScroll(-delta);
} }
} }
...@@ -283,8 +299,8 @@ public class NavigationHandler { ...@@ -283,8 +299,8 @@ public class NavigationHandler {
cancelStopNavigatingRunnable(); cancelStopNavigatingRunnable();
mSideSlideLayout.release(allowNav && mNavigationSheet.isHidden()); mSideSlideLayout.release(allowNav && mNavigationSheet.isHidden());
mNavigationSheet.release(); mNavigationSheet.release();
} else if (mState == GestureState.GLOW && mGlowEffect != null) { } else if (mState == GestureState.GLOW) {
mGlowEffect.release(); mGlowEffectSupplier.get().release();
} }
} }
...@@ -295,19 +311,12 @@ public class NavigationHandler { ...@@ -295,19 +311,12 @@ public class NavigationHandler {
if (mState == GestureState.DRAGGED && mSideSlideLayout != null) { if (mState == GestureState.DRAGGED && mSideSlideLayout != null) {
cancelStopNavigatingRunnable(); cancelStopNavigatingRunnable();
mSideSlideLayout.reset(); mSideSlideLayout.reset();
} else if (mState == GestureState.GLOW && mGlowEffect != null) { } else if (mState == GestureState.GLOW) {
mGlowEffect.reset(); mGlowEffectSupplier.get().reset();
} }
mState = GestureState.NONE; mState = GestureState.NONE;
} }
/**
* Performs cleanup upon destruction.
*/
public void destroy() {
if (mGlowEffect != null) mGlowEffect.destroy();
}
private void cancelStopNavigatingRunnable() { private void cancelStopNavigatingRunnable() {
if (mStopNavigatingRunnable != null) { if (mStopNavigatingRunnable != null) {
mSideSlideLayout.removeCallbacks(mStopNavigatingRunnable); mSideSlideLayout.removeCallbacks(mStopNavigatingRunnable);
......
...@@ -40,13 +40,11 @@ public interface NavigationSheet { ...@@ -40,13 +40,11 @@ public interface NavigationSheet {
* @param rootView Root view whose dimension is used for the sheet. * @param rootView Root view whose dimension is used for the sheet.
* @param context {@link Context} used to retrieve resources. * @param context {@link Context} used to retrieve resources.
* @param bottomSheetController {@link BottomSheetController} object. * @param bottomSheetController {@link BottomSheetController} object.
* @param delegate Delegate used by navigation sheet to perform actions.
* @return NavigationSheet object. * @return NavigationSheet object.
*/ */
public static NavigationSheet create(View rootView, Context context, public static NavigationSheet create(
Supplier<BottomSheetController> bottomSheetController, View rootView, Context context, Supplier<BottomSheetController> bottomSheetController) {
NavigationSheet.Delegate delegate) { return new NavigationSheetCoordinator(rootView, context, bottomSheetController);
return new NavigationSheetCoordinator(rootView, context, bottomSheetController, delegate);
} }
/** /**
...@@ -72,6 +70,9 @@ public interface NavigationSheet { ...@@ -72,6 +70,9 @@ public interface NavigationSheet {
* Dummy object that does nothing. Saves lots of null checks. * Dummy object that does nothing. Saves lots of null checks.
*/ */
static final NavigationSheet DUMMY = new NavigationSheet() { static final NavigationSheet DUMMY = new NavigationSheet() {
@Override
public void setDelegate(Delegate delegate) {}
@Override @Override
public void start(boolean forward, boolean showCloseIndicator) {} public void start(boolean forward, boolean showCloseIndicator) {}
...@@ -100,6 +101,12 @@ public interface NavigationSheet { ...@@ -100,6 +101,12 @@ public interface NavigationSheet {
} }
}; };
/**
* Set a new {@link Delegate} object whenever the dependency is updated.
* @param delegate Delegate used by navigation sheet to perform actions.
*/
void setDelegate(Delegate delegate);
/** /**
* Get the navigation sheet ready as the gesture starts. * Get the navigation sheet ready as the gesture starts.
* @param forward {@code true} if we're navigating forward. * @param forward {@code true} if we're navigating forward.
......
...@@ -60,7 +60,6 @@ class NavigationSheetCoordinator implements BottomSheetContent, NavigationSheet ...@@ -60,7 +60,6 @@ class NavigationSheetCoordinator implements BottomSheetContent, NavigationSheet
private final View mToolbarView; private final View mToolbarView;
private final LayoutInflater mLayoutInflater; private final LayoutInflater mLayoutInflater;
private final Supplier<BottomSheetController> mBottomSheetController; private final Supplier<BottomSheetController> mBottomSheetController;
private final NavigationSheet.Delegate mDelegate;
private final NavigationSheetMediator mMediator; private final NavigationSheetMediator mMediator;
private final BottomSheetObserver mSheetObserver = new EmptyBottomSheetObserver() { private final BottomSheetObserver mSheetObserver = new EmptyBottomSheetObserver() {
@Override @Override
...@@ -80,6 +79,8 @@ class NavigationSheetCoordinator implements BottomSheetContent, NavigationSheet ...@@ -80,6 +79,8 @@ class NavigationSheetCoordinator implements BottomSheetContent, NavigationSheet
private final int mContentPadding; private final int mContentPadding;
private final View mParentView; private final View mParentView;
private NavigationSheet.Delegate mDelegate;
private static class NavigationItemViewBinder { private static class NavigationItemViewBinder {
public static void bind(PropertyModel model, View view, PropertyKey propertyKey) { public static void bind(PropertyModel model, View view, PropertyKey propertyKey) {
if (ItemProperties.ICON == propertyKey) { if (ItemProperties.ICON == propertyKey) {
...@@ -113,11 +114,10 @@ class NavigationSheetCoordinator implements BottomSheetContent, NavigationSheet ...@@ -113,11 +114,10 @@ class NavigationSheetCoordinator implements BottomSheetContent, NavigationSheet
/** /**
* Construct a new NavigationSheet. * Construct a new NavigationSheet.
*/ */
NavigationSheetCoordinator(View parent, Context context, NavigationSheetCoordinator(
Supplier<BottomSheetController> bottomSheetController, Delegate delegate) { View parent, Context context, Supplier<BottomSheetController> bottomSheetController) {
mParentView = parent; mParentView = parent;
mBottomSheetController = bottomSheetController; mBottomSheetController = bottomSheetController;
mDelegate = delegate;
mLayoutInflater = LayoutInflater.from(context); mLayoutInflater = LayoutInflater.from(context);
mToolbarView = mLayoutInflater.inflate(R.layout.navigation_sheet_toolbar, null); mToolbarView = mLayoutInflater.inflate(R.layout.navigation_sheet_toolbar, null);
mMediator = new NavigationSheetMediator(context, mModelList, (position, index) -> { mMediator = new NavigationSheetMediator(context, mModelList, (position, index) -> {
...@@ -183,6 +183,11 @@ class NavigationSheetCoordinator implements BottomSheetContent, NavigationSheet ...@@ -183,6 +183,11 @@ class NavigationSheetCoordinator implements BottomSheetContent, NavigationSheet
// NavigationSheet // NavigationSheet
@Override
public void setDelegate(NavigationSheet.Delegate delegate) {
mDelegate = delegate;
}
@Override @Override
public void start(boolean forward, boolean showCloseIndicator) { public void start(boolean forward, boolean showCloseIndicator) {
if (mBottomSheetController.get() == null) return; if (mBottomSheetController.get() == null) return;
......
...@@ -53,7 +53,7 @@ public class SideSlideLayout extends ViewGroup { ...@@ -53,7 +53,7 @@ public class SideSlideLayout extends ViewGroup {
private static final float DECELERATE_INTERPOLATION_FACTOR = 2f; private static final float DECELERATE_INTERPOLATION_FACTOR = 2f;
private static final int SCALE_DOWN_DURATION_MS = 400; private static final int SCALE_DOWN_DURATION_MS = 600;
private static final int ANIMATE_TO_START_DURATION_MS = 500; private static final int ANIMATE_TO_START_DURATION_MS = 500;
// Minimum number of pull updates necessary to trigger a side nav. // Minimum number of pull updates necessary to trigger a side nav.
...@@ -115,11 +115,7 @@ public class SideSlideLayout extends ViewGroup { ...@@ -115,11 +115,7 @@ public class SideSlideLayout extends ViewGroup {
public void onAnimationEnd(Animation animation) { public void onAnimationEnd(Animation animation) {
mArrowView.setFaded(false, false); mArrowView.setFaded(false, false);
mArrowView.setVisibility(View.INVISIBLE); mArrowView.setVisibility(View.INVISIBLE);
if (mNavigating) { if (!mNavigating) reset();
if (mListener != null) mListener.onNavigate(mIsForward);
} else {
reset();
}
hideCloseIndicator(); hideCloseIndicator();
} }
}; };
...@@ -195,6 +191,9 @@ public class SideSlideLayout extends ViewGroup { ...@@ -195,6 +191,9 @@ public class SideSlideLayout extends ViewGroup {
} }
private void startHidingAnimation(AnimationListener listener) { private void startHidingAnimation(AnimationListener listener) {
// Start animation and navigation simultaneously.
if (mNavigating && mListener != null) mListener.onNavigate(mIsForward);
// ScaleAnimation needs to be created again if the arrow widget width changes over time // ScaleAnimation needs to be created again if the arrow widget width changes over time
// (due to turning on/off close indicator) to set the right x pivot point. // (due to turning on/off close indicator) to set the right x pivot point.
if (mHidingAnimation == null || mAnimationViewWidth != mArrowViewWidth) { if (mHidingAnimation == null || mAnimationViewWidth != mArrowViewWidth) {
......
...@@ -31,7 +31,6 @@ import org.chromium.chrome.browser.ChromeTabbedActivity; ...@@ -31,7 +31,6 @@ import org.chromium.chrome.browser.ChromeTabbedActivity;
import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.IntentHandler;
import org.chromium.chrome.browser.document.ChromeLauncherActivity; import org.chromium.chrome.browser.document.ChromeLauncherActivity;
import org.chromium.chrome.browser.favicon.LargeIconBridge; import org.chromium.chrome.browser.favicon.LargeIconBridge;
import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegate;
import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.preferences.Pref;
import org.chromium.chrome.browser.preferences.PrefChangeRegistrar; import org.chromium.chrome.browser.preferences.PrefChangeRegistrar;
import org.chromium.chrome.browser.preferences.PrefChangeRegistrar.PrefObserver; import org.chromium.chrome.browser.preferences.PrefChangeRegistrar.PrefObserver;
...@@ -296,14 +295,6 @@ public class HistoryManager implements OnMenuItemClickListener, SignInStateObser ...@@ -296,14 +295,6 @@ public class HistoryManager implements OnMenuItemClickListener, SignInStateObser
mPrefChangeRegistrar.destroy(); mPrefChangeRegistrar.destroy();
} }
/**
* Sets the delegate object needed for history navigation logic.
* @param delegate {@link HistoryNavigationDelegate} object.
*/
public void setHistoryNavigationDelegate(HistoryNavigationDelegate delegate) {
mSelectableListLayout.setHistoryNavigationDelegate(delegate);
}
/** /**
* Called when the user presses the back key. This is only going to be called * Called when the user presses the back key. This is only going to be called
* when the history UI is shown in a separate activity rather inside a tab. * when the history UI is shown in a separate activity rather inside a tab.
......
...@@ -33,7 +33,6 @@ public class HistoryPage extends BasicNativePage { ...@@ -33,7 +33,6 @@ public class HistoryPage extends BasicNativePage {
mHistoryManager = new HistoryManager(activity, false, activity.getSnackbarManager(), mHistoryManager = new HistoryManager(activity, false, activity.getSnackbarManager(),
activity.getCurrentTabModel().isIncognito()); activity.getCurrentTabModel().isIncognito());
mTitle = host.getContext().getResources().getString(R.string.menu_history); mTitle = host.getContext().getResources().getString(R.string.menu_history);
mHistoryManager.setHistoryNavigationDelegate(host.createHistoryNavigationDelegate());
initWithView(mHistoryManager.getView()); initWithView(mHistoryManager.getView());
} }
......
...@@ -20,8 +20,6 @@ import org.chromium.chrome.browser.explore_sites.ExploreSitesPage; ...@@ -20,8 +20,6 @@ import org.chromium.chrome.browser.explore_sites.ExploreSitesPage;
import org.chromium.chrome.browser.feed.FeedNewTabPage; import org.chromium.chrome.browser.feed.FeedNewTabPage;
import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegate;
import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegateFactory;
import org.chromium.chrome.browser.history.HistoryPage; import org.chromium.chrome.browser.history.HistoryPage;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
import org.chromium.chrome.browser.ntp.IncognitoNewTabPage; import org.chromium.chrome.browser.ntp.IncognitoNewTabPage;
...@@ -247,11 +245,6 @@ public class NativePageFactory { ...@@ -247,11 +245,6 @@ public class NativePageFactory {
return mTab == TabModelSelector.from(mTab).getCurrentTab(); return mTab == TabModelSelector.from(mTab).getCurrentTab();
} }
@Override
public HistoryNavigationDelegate createHistoryNavigationDelegate() {
return HistoryNavigationDelegateFactory.create(mTab);
}
@Override @Override
public DestroyableObservableSupplier<Rect> createDefaultMarginSupplier() { public DestroyableObservableSupplier<Rect> createDefaultMarginSupplier() {
return new BrowserControlsMarginSupplier(mFullscreenManager); return new BrowserControlsMarginSupplier(mFullscreenManager);
......
...@@ -8,7 +8,6 @@ import android.content.Context; ...@@ -8,7 +8,6 @@ import android.content.Context;
import android.graphics.Rect; import android.graphics.Rect;
import org.chromium.base.supplier.DestroyableObservableSupplier; import org.chromium.base.supplier.DestroyableObservableSupplier;
import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegate;
import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.LoadUrlParams;
/** /**
...@@ -38,12 +37,6 @@ public interface NativePageHost { ...@@ -38,12 +37,6 @@ public interface NativePageHost {
/** @return whether the hosted native page is currently visible. */ /** @return whether the hosted native page is currently visible. */
boolean isVisible(); boolean isVisible();
/**
* Creates a delegate object needed for history navigation logic.
* @return {@link HistoryNavigationDelegate} implementation.
*/
HistoryNavigationDelegate createHistoryNavigationDelegate();
/** /**
* Creates a default margin supplier. Once created, the NativePage is responsible for calling * Creates a default margin supplier. Once created, the NativePage is responsible for calling
* {@link DestroyableObservableSupplier#destroy()} to clean-up the supplier once it is no longer * {@link DestroyableObservableSupplier#destroy()} to clean-up the supplier once it is no longer
......
...@@ -84,7 +84,6 @@ public class IncognitoNewTabPage ...@@ -84,7 +84,6 @@ public class IncognitoNewTabPage
mIncognitoNewTabPageView = mIncognitoNewTabPageView =
(IncognitoNewTabPageView) inflater.inflate(R.layout.new_tab_page_incognito, null); (IncognitoNewTabPageView) inflater.inflate(R.layout.new_tab_page_incognito, null);
mIncognitoNewTabPageView.initialize(mIncognitoNewTabPageManager); mIncognitoNewTabPageView.initialize(mIncognitoNewTabPageManager);
mIncognitoNewTabPageView.setNavigationDelegate(host.createHistoryNavigationDelegate());
TextView newTabIncognitoHeader = TextView newTabIncognitoHeader =
mIncognitoNewTabPageView.findViewById(R.id.new_tab_incognito_title); mIncognitoNewTabPageView.findViewById(R.id.new_tab_incognito_title);
......
...@@ -8,16 +8,16 @@ import android.content.Context; ...@@ -8,16 +8,16 @@ import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.widget.FrameLayout;
import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout;
import org.chromium.ui.base.ViewUtils; import org.chromium.ui.base.ViewUtils;
/** /**
* The New Tab Page for use in the incognito profile. * The New Tab Page for use in the incognito profile.
*/ */
public class IncognitoNewTabPageView extends HistoryNavigationLayout { public class IncognitoNewTabPageView extends FrameLayout {
private IncognitoNewTabPageManager mManager; private IncognitoNewTabPageManager mManager;
private boolean mFirstShow = true; private boolean mFirstShow = true;
private NewTabPageScrollView mScrollView; private NewTabPageScrollView mScrollView;
......
...@@ -12,6 +12,7 @@ import android.support.v7.widget.RecyclerView.AdapterDataObserver; ...@@ -12,6 +12,7 @@ import android.support.v7.widget.RecyclerView.AdapterDataObserver;
import android.support.v7.widget.RecyclerView.ViewHolder; import android.support.v7.widget.RecyclerView.ViewHolder;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.widget.FrameLayout;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
...@@ -20,8 +21,6 @@ import org.chromium.chrome.R; ...@@ -20,8 +21,6 @@ import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.ChromeTabbedActivity;
import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior; import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
import org.chromium.chrome.browser.compositor.layouts.content.InvalidationAwareThumbnailProvider; import org.chromium.chrome.browser.compositor.layouts.content.InvalidationAwareThumbnailProvider;
import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegateFactory;
import org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout;
import org.chromium.chrome.browser.native_page.ContextMenuManager; import org.chromium.chrome.browser.native_page.ContextMenuManager;
import org.chromium.chrome.browser.ntp.cards.NewTabPageAdapter; import org.chromium.chrome.browser.ntp.cards.NewTabPageAdapter;
import org.chromium.chrome.browser.ntp.cards.NewTabPageRecyclerView; import org.chromium.chrome.browser.ntp.cards.NewTabPageRecyclerView;
...@@ -40,7 +39,7 @@ import org.chromium.ui.base.ViewUtils; ...@@ -40,7 +39,7 @@ import org.chromium.ui.base.ViewUtils;
* The native new tab page, represented by some basic data such as title and url, and an Android * The native new tab page, represented by some basic data such as title and url, and an Android
* View that displays the page. * View that displays the page.
*/ */
public class NewTabPageView extends HistoryNavigationLayout { public class NewTabPageView extends FrameLayout {
private static final String TAG = "NewTabPageView"; private static final String TAG = "NewTabPageView";
private NewTabPageRecyclerView mRecyclerView; private NewTabPageRecyclerView mRecyclerView;
...@@ -131,7 +130,6 @@ public class NewTabPageView extends HistoryNavigationLayout { ...@@ -131,7 +130,6 @@ public class NewTabPageView extends HistoryNavigationLayout {
mRecyclerView::setTouchEnabled, closeContextMenuCallback, mRecyclerView::setTouchEnabled, closeContextMenuCallback,
NewTabPage.CONTEXT_MENU_USER_ACTION_PREFIX); NewTabPage.CONTEXT_MENU_USER_ACTION_PREFIX);
mTab.getWindowAndroid().addContextMenuCloseListener(mContextMenuManager); mTab.getWindowAndroid().addContextMenuCloseListener(mContextMenuManager);
setNavigationDelegate(HistoryNavigationDelegateFactory.create(mTab));
OverviewModeBehavior overviewModeBehavior = OverviewModeBehavior overviewModeBehavior =
((TabImpl) tab).getActivity() instanceof ChromeTabbedActivity ((TabImpl) tab).getActivity() instanceof ChromeTabbedActivity
......
...@@ -14,6 +14,7 @@ import android.view.ContextMenu; ...@@ -14,6 +14,7 @@ import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo; import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListView; import android.widget.ExpandableListView;
import org.chromium.base.ActivityState; import org.chromium.base.ActivityState;
...@@ -23,7 +24,6 @@ import org.chromium.chrome.R; ...@@ -23,7 +24,6 @@ import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.compositor.layouts.content.InvalidationAwareThumbnailProvider; import org.chromium.chrome.browser.compositor.layouts.content.InvalidationAwareThumbnailProvider;
import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
import org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout;
import org.chromium.chrome.browser.native_page.NativePage; import org.chromium.chrome.browser.native_page.NativePage;
import org.chromium.chrome.browser.native_page.NativePageHost; import org.chromium.chrome.browser.native_page.NativePageHost;
import org.chromium.chrome.browser.util.UrlConstants; import org.chromium.chrome.browser.util.UrlConstants;
...@@ -45,7 +45,7 @@ public class RecentTabsPage ...@@ -45,7 +45,7 @@ public class RecentTabsPage
private final ChromeFullscreenManager mFullscreenManager; private final ChromeFullscreenManager mFullscreenManager;
private final ExpandableListView mListView; private final ExpandableListView mListView;
private final String mTitle; private final String mTitle;
private final HistoryNavigationLayout mView; private final ViewGroup mView;
private RecentTabsManager mRecentTabsManager; private RecentTabsManager mRecentTabsManager;
private RecentTabsRowAdapter mAdapter; private RecentTabsRowAdapter mAdapter;
...@@ -91,7 +91,7 @@ public class RecentTabsPage ...@@ -91,7 +91,7 @@ public class RecentTabsPage
mTitle = resources.getString(R.string.recent_tabs); mTitle = resources.getString(R.string.recent_tabs);
mRecentTabsManager.setUpdatedCallback(this); mRecentTabsManager.setUpdatedCallback(this);
LayoutInflater inflater = LayoutInflater.from(activity); LayoutInflater inflater = LayoutInflater.from(activity);
mView = (HistoryNavigationLayout) inflater.inflate(R.layout.recent_tabs_page, null); mView = (ViewGroup) inflater.inflate(R.layout.recent_tabs_page, null);
mListView = (ExpandableListView) mView.findViewById(R.id.odp_listview); mListView = (ExpandableListView) mView.findViewById(R.id.odp_listview);
mAdapter = new RecentTabsRowAdapter(activity, recentTabsManager); mAdapter = new RecentTabsRowAdapter(activity, recentTabsManager);
mListView.setAdapter(mAdapter); mListView.setAdapter(mAdapter);
...@@ -114,7 +114,6 @@ public class RecentTabsPage ...@@ -114,7 +114,6 @@ public class RecentTabsPage
mFullscreenManager = null; mFullscreenManager = null;
} }
mView.setNavigationDelegate(mPageHost.createHistoryNavigationDelegate());
onUpdated(); onUpdated();
} }
......
...@@ -18,6 +18,7 @@ import org.chromium.chrome.browser.datareduction.DataReductionPromoScreen; ...@@ -18,6 +18,7 @@ import org.chromium.chrome.browser.datareduction.DataReductionPromoScreen;
import org.chromium.chrome.browser.firstrun.FirstRunStatus; import org.chromium.chrome.browser.firstrun.FirstRunStatus;
import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.flags.FeatureUtilities; import org.chromium.chrome.browser.flags.FeatureUtilities;
import org.chromium.chrome.browser.gesturenav.HistoryNavigationCoordinator;
import org.chromium.chrome.browser.language.LanguageAskPrompt; import org.chromium.chrome.browser.language.LanguageAskPrompt;
import org.chromium.chrome.browser.lifecycle.NativeInitObserver; import org.chromium.chrome.browser.lifecycle.NativeInitObserver;
import org.chromium.chrome.browser.locale.LocaleManager; import org.chromium.chrome.browser.locale.LocaleManager;
...@@ -48,6 +49,7 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator implements Native ...@@ -48,6 +49,7 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator implements Native
private StatusIndicatorCoordinator mStatusIndicatorCoordinator; private StatusIndicatorCoordinator mStatusIndicatorCoordinator;
private StatusIndicatorCoordinator.StatusIndicatorObserver mStatusIndicatorObserver; private StatusIndicatorCoordinator.StatusIndicatorObserver mStatusIndicatorObserver;
private @Nullable ToolbarButtonInProductHelpController mToolbarButtonInProductHelpController; private @Nullable ToolbarButtonInProductHelpController mToolbarButtonInProductHelpController;
private HistoryNavigationCoordinator mHistoryNavigationCoordinator;
private boolean mIntentWithEffect; private boolean mIntentWithEffect;
/** /**
...@@ -95,6 +97,10 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator implements Native ...@@ -95,6 +97,10 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator implements Native
if (mImmersiveModeManager != null) { if (mImmersiveModeManager != null) {
getToolbarManager().setImmersiveModeManager(mImmersiveModeManager); getToolbarManager().setImmersiveModeManager(mImmersiveModeManager);
} }
mHistoryNavigationCoordinator = new HistoryNavigationCoordinator();
mHistoryNavigationCoordinator.init(mActivity.getLifecycleDispatcher(),
mActivity.getCompositorViewHolder(), mActivity.getActivityTabProvider(),
mActivity.getInsetObserverView());
} }
/** /**
......
...@@ -26,8 +26,6 @@ import androidx.annotation.VisibleForTesting; ...@@ -26,8 +26,6 @@ import androidx.annotation.VisibleForTesting;
import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegate;
import org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout;
import org.chromium.chrome.browser.widget.selection.SelectionDelegate.SelectionObserver; import org.chromium.chrome.browser.widget.selection.SelectionDelegate.SelectionObserver;
import org.chromium.components.browser_ui.widget.FadingShadow; import org.chromium.components.browser_ui.widget.FadingShadow;
import org.chromium.components.browser_ui.widget.FadingShadowView; import org.chromium.components.browser_ui.widget.FadingShadowView;
...@@ -286,18 +284,6 @@ public class SelectableListLayout<E> ...@@ -286,18 +284,6 @@ public class SelectableListLayout<E>
@Override @Override
public void onSelectionStateChange(List<E> selectedItems) { public void onSelectionStateChange(List<E> selectedItems) {
setToolbarShadowVisibility(); setToolbarShadowVisibility();
if (!selectedItems.isEmpty()) {
((HistoryNavigationLayout) findViewById(R.id.list_content)).release();
}
}
/**
* Sets the delegate object needed for history navigation logic.
* @param delegate {@link HistoryNavigationDelegate} object.
*/
public void setHistoryNavigationDelegate(HistoryNavigationDelegate delegate) {
HistoryNavigationLayout layout = (HistoryNavigationLayout) findViewById(R.id.list_content);
layout.setNavigationDelegate(delegate);
} }
/** /**
......
...@@ -195,8 +195,8 @@ public class NavigationSheetTest { ...@@ -195,8 +195,8 @@ public class NavigationSheetTest {
Tab tab = mActivityTestRule.getActivity().getActivityTabProvider().get(); Tab tab = mActivityTestRule.getActivity().getActivityTabProvider().get();
NavigationSheet navigationSheet = NavigationSheet navigationSheet =
NavigationSheet.create(tab.getContentView(), mActivityTestRule.getActivity(), NavigationSheet.create(tab.getContentView(), mActivityTestRule.getActivity(),
mActivityTestRule.getActivity()::getBottomSheetController, mActivityTestRule.getActivity()::getBottomSheetController);
new TestSheetDelegate(controller)); navigationSheet.setDelegate(new TestSheetDelegate(controller));
navigationSheet.startAndExpand(false, false); navigationSheet.startAndExpand(false, false);
return navigationSheet; return navigationSheet;
}); });
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment