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

GestureNav: Adopt SceneOverlay for overscroll glow effect

This CL adopts SceneOverlay for overscroll glow effect. Previously
the glow effect was rendered on a cc layer attached to the current
WebContent's cc layer. This requires that the WebContents be
used as View property, and swapped for every tab/WebContents change.
Rendering it on scene overlay saves us from maintaining the logic
above, and having to use the heavy object like WebContents for
MVC view properties.

Bug: 1112573
Change-Id: I0b80c7e78007051d2d94c76a14dcd265cb0607c1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2351267Reviewed-by: default avatarDavid Trainor <dtrainor@chromium.org>
Reviewed-by: default avatarMatthew Jones <mdjones@chromium.org>
Commit-Queue: Jinsuk Kim <jinsukkim@chromium.org>
Cr-Commit-Position: refs/heads/master@{#799067}
parent 2fcc801e
...@@ -3005,7 +3005,7 @@ generate_jni("chrome_jni_headers") { ...@@ -3005,7 +3005,7 @@ generate_jni("chrome_jni_headers") {
"java/src/org/chromium/chrome/browser/feedback/SystemInfoFeedbackSource.java", "java/src/org/chromium/chrome/browser/feedback/SystemInfoFeedbackSource.java",
"java/src/org/chromium/chrome/browser/firstrun/FirstRunUtils.java", "java/src/org/chromium/chrome/browser/firstrun/FirstRunUtils.java",
"java/src/org/chromium/chrome/browser/flags/ChromeSessionState.java", "java/src/org/chromium/chrome/browser/flags/ChromeSessionState.java",
"java/src/org/chromium/chrome/browser/gesturenav/CompositorNavigationGlow.java", "java/src/org/chromium/chrome/browser/gesturenav/OverscrollSceneLayer.java",
"java/src/org/chromium/chrome/browser/history/BrowsingHistoryBridge.java", "java/src/org/chromium/chrome/browser/history/BrowsingHistoryBridge.java",
"java/src/org/chromium/chrome/browser/history/HistoryDeletionBridge.java", "java/src/org/chromium/chrome/browser/history/HistoryDeletionBridge.java",
"java/src/org/chromium/chrome/browser/history/HistoryDeletionInfo.java", "java/src/org/chromium/chrome/browser/history/HistoryDeletionInfo.java",
......
...@@ -755,7 +755,6 @@ chrome_java_sources = [ ...@@ -755,7 +755,6 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/gcore/GoogleApiClientHelper.java", "java/src/org/chromium/chrome/browser/gcore/GoogleApiClientHelper.java",
"java/src/org/chromium/chrome/browser/gcore/LifecycleHook.java", "java/src/org/chromium/chrome/browser/gcore/LifecycleHook.java",
"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/GestureNavMetrics.java", "java/src/org/chromium/chrome/browser/gesturenav/GestureNavMetrics.java",
"java/src/org/chromium/chrome/browser/gesturenav/GestureNavigationProperties.java", "java/src/org/chromium/chrome/browser/gesturenav/GestureNavigationProperties.java",
"java/src/org/chromium/chrome/browser/gesturenav/GestureNavigationViewBinder.java", "java/src/org/chromium/chrome/browser/gesturenav/GestureNavigationViewBinder.java",
...@@ -769,6 +768,8 @@ chrome_java_sources = [ ...@@ -769,6 +768,8 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetCoordinator.java", "java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetCoordinator.java",
"java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetMediator.java", "java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetMediator.java",
"java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetView.java", "java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetView.java",
"java/src/org/chromium/chrome/browser/gesturenav/OverscrollGlowOverlay.java",
"java/src/org/chromium/chrome/browser/gesturenav/OverscrollSceneLayer.java",
"java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java", "java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java",
"java/src/org/chromium/chrome/browser/gesturenav/TabbedActionDelegate.java", "java/src/org/chromium/chrome/browser/gesturenav/TabbedActionDelegate.java",
"java/src/org/chromium/chrome/browser/gesturenav/TabbedSheetDelegate.java", "java/src/org/chromium/chrome/browser/gesturenav/TabbedSheetDelegate.java",
......
...@@ -129,6 +129,7 @@ public class LayoutManager implements LayoutUpdateHost, LayoutProvider, ...@@ -129,6 +129,7 @@ public class LayoutManager implements LayoutUpdateHost, LayoutProvider,
private final OverlayPanelManager mOverlayPanelManager; private final OverlayPanelManager mOverlayPanelManager;
private TopToolbarOverlayCoordinator mToolbarOverlay; private TopToolbarOverlayCoordinator mToolbarOverlay;
private SceneOverlay mStatusIndicatorSceneOverlay; private SceneOverlay mStatusIndicatorSceneOverlay;
private SceneOverlay mGestureNavigationOverscrollGlow;
/** A delegate for interacting with the Contextual Search manager. */ /** A delegate for interacting with the Contextual Search manager. */
protected ContextualSearchManagementDelegate mContextualSearchDelegate; protected ContextualSearchManagementDelegate mContextualSearchDelegate;
...@@ -980,6 +981,15 @@ public class LayoutManager implements LayoutUpdateHost, LayoutProvider, ...@@ -980,6 +981,15 @@ public class LayoutManager implements LayoutUpdateHost, LayoutProvider,
mStaticLayout.addSceneOverlay(mContextualSearchPanel); mStaticLayout.addSceneOverlay(mContextualSearchPanel);
} }
/**
* Add a {@link SceneOverlay} to the front of the list. This means the overlay will be drawn
* last and therefore above all other overlays currently in the list.
* @param overlay The overlay to be added to the back of the list.
*/
public void addSceneOverlayToFront(SceneOverlay overlay) {
mStaticLayout.addSceneOverlay(overlay);
}
/** /**
* Add a {@link SceneOverlay} to the back of the list. This means the overlay will be drawn * Add a {@link SceneOverlay} to the back of the list. This means the overlay will be drawn
* first and therefore behind all other overlays currently in the list. * first and therefore behind all other overlays currently in the list.
......
...@@ -47,11 +47,6 @@ public class AndroidUiNavigationGlow extends NavigationGlow { ...@@ -47,11 +47,6 @@ public class AndroidUiNavigationGlow extends NavigationGlow {
if (mGlowView.getParent() == null) mParentView.addView(mGlowView); if (mGlowView.getParent() == null) mParentView.addView(mGlowView);
} }
@Override
public float getPullOffset() {
return mTotalPullOffset;
}
@Override @Override
public void onScroll(float offset) { public void onScroll(float offset) {
float xDelta = -(offset - mTotalPullOffset); float xDelta = -(offset - mTotalPullOffset);
......
// 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.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.content_public.browser.WebContents;
/**
* Implements navigation glow using compositor layer for tab switcher or rendered web contents.
*/
@JNINamespace("android")
class CompositorNavigationGlow extends NavigationGlow {
private float mAccumulatedScroll;
private long mNativeNavigationGlow;
/**
* @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 NavigationGlow object for rendered pages
*/
public CompositorNavigationGlow(ViewGroup parentView, WebContents webContents) {
super(parentView);
mNativeNavigationGlow =
CompositorNavigationGlowJni.get().init(CompositorNavigationGlow.this, webContents);
}
@Override
public void prepare(float startX, float startY) {
CompositorNavigationGlowJni.get().prepare(mNativeNavigationGlow,
CompositorNavigationGlow.this, startX, startY, mParentView.getWidth(),
mParentView.getHeight());
}
@Override
public float getPullOffset() {
return mAccumulatedScroll;
}
@Override
public void onScroll(float offset) {
if (mNativeNavigationGlow == 0) return;
float xDelta = -(offset - mAccumulatedScroll);
mAccumulatedScroll = offset;
CompositorNavigationGlowJni.get().onOverscroll(
mNativeNavigationGlow, CompositorNavigationGlow.this, mAccumulatedScroll, xDelta);
}
@Override
public void release() {
if (mNativeNavigationGlow == 0) return;
CompositorNavigationGlowJni.get().onOverscroll(
mNativeNavigationGlow, CompositorNavigationGlow.this, 0, 0);
mAccumulatedScroll = 0;
}
@Override
public void reset() {
if (mNativeNavigationGlow == 0) return;
CompositorNavigationGlowJni.get().onReset(
mNativeNavigationGlow, CompositorNavigationGlow.this);
mAccumulatedScroll = 0;
}
@Override
public void destroy() {
if (mNativeNavigationGlow == 0) return;
CompositorNavigationGlowJni.get().destroy(
mNativeNavigationGlow, CompositorNavigationGlow.this);
mNativeNavigationGlow = 0;
}
@NativeMethods
interface Natives {
long init(CompositorNavigationGlow caller, WebContents webContents);
void prepare(long nativeNavigationGlow, CompositorNavigationGlow caller, float startX,
float startY, int width, int height);
void onOverscroll(long nativeNavigationGlow, CompositorNavigationGlow caller,
float accumulatedScroll, float delta);
void onReset(long nativeNavigationGlow, CompositorNavigationGlow caller);
void destroy(long nativeNavigationGlow, CompositorNavigationGlow caller);
}
}
...@@ -18,6 +18,7 @@ import org.chromium.chrome.browser.ActivityTabProvider; ...@@ -18,6 +18,7 @@ import org.chromium.chrome.browser.ActivityTabProvider;
import org.chromium.chrome.browser.ActivityTabProvider.ActivityTabTabObserver; import org.chromium.chrome.browser.ActivityTabProvider.ActivityTabTabObserver;
import org.chromium.chrome.browser.SwipeRefreshHandler; import org.chromium.chrome.browser.SwipeRefreshHandler;
import org.chromium.chrome.browser.compositor.CompositorViewHolder; import org.chromium.chrome.browser.compositor.CompositorViewHolder;
import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
import org.chromium.chrome.browser.lifecycle.PauseResumeWithNativeObserver; import org.chromium.chrome.browser.lifecycle.PauseResumeWithNativeObserver;
...@@ -25,6 +26,7 @@ import org.chromium.chrome.browser.tab.Tab; ...@@ -25,6 +26,7 @@ import org.chromium.chrome.browser.tab.Tab;
import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
import org.chromium.components.browser_ui.widget.InsetObserverView; import org.chromium.components.browser_ui.widget.InsetObserverView;
import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.modelutil.PropertyModelChangeProcessor; import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
/** /**
...@@ -51,10 +53,7 @@ public class HistoryNavigationCoordinator ...@@ -51,10 +53,7 @@ public class HistoryNavigationCoordinator
private HistoryNavigationDelegate mDelegate; private HistoryNavigationDelegate mDelegate;
private NavigationSheet mNavigationSheet; private NavigationSheet mNavigationSheet;
private NavigationGlow mCompositorGlowEffect; private OverscrollGlowOverlay mOverscrollGlowOverlay;
private NavigationGlow mJavaGlowEffect;
private WebContents mWebContents;
private Runnable mInitRunnable; private Runnable mInitRunnable;
private Runnable mCleanupRunnable; private Runnable mCleanupRunnable;
...@@ -69,35 +68,38 @@ public class HistoryNavigationCoordinator ...@@ -69,35 +68,38 @@ public class HistoryNavigationCoordinator
* @param backShouldCloseTab Boolean function that returns true if back button press * @param backShouldCloseTab Boolean function that returns true if back button press
* will close the tab. * will close the tab.
* @param onBackPressed Runnable that performs an action when back button is pressed. * @param onBackPressed Runnable that performs an action when back button is pressed.
* @param layoutManager LayoutManager for handling overscroll glow effect as scene layer.
* @param showHistoryManager Function that shows full navigation history UI. * @param showHistoryManager Function that shows full navigation history UI.
* @param historyMenu UI string for full history UI in its header. * @param historyMenu UI string for full history UI in its header.
* @param bottomSheetControllerSupplier Supplier for {@link BottomSheetController}. * @param bottomSheetControllerSupplier Supplier for {@link BottomSheetController}.
* @return HistoryNavigationCoordinator object or null if not enabled via feature flag. * @return HistoryNavigationCoordinator object or null if not enabled via feature flag.
*/ */
public static HistoryNavigationCoordinator create( public static HistoryNavigationCoordinator create(WindowAndroid window,
ActivityLifecycleDispatcher lifecycleDispatcher, ActivityLifecycleDispatcher lifecycleDispatcher,
CompositorViewHolder compositorViewHolder, ActivityTabProvider tabProvider, CompositorViewHolder compositorViewHolder, ActivityTabProvider tabProvider,
InsetObserverView insetObserverView, Function<Tab, Boolean> backShouldCloseTab, InsetObserverView insetObserverView, Function<Tab, Boolean> backShouldCloseTab,
Runnable onBackPressed, Consumer<Tab> showHistoryManager, String historyMenu, Runnable onBackPressed, LayoutManager layoutManager, Consumer<Tab> showHistoryManager,
Supplier<BottomSheetController> bottomSheetControllerSupplier) { String historyMenu, Supplier<BottomSheetController> bottomSheetControllerSupplier) {
if (!isFeatureFlagEnabled()) return null; if (!isFeatureFlagEnabled()) return null;
HistoryNavigationCoordinator coordinator = new HistoryNavigationCoordinator(); HistoryNavigationCoordinator coordinator = new HistoryNavigationCoordinator();
coordinator.init(lifecycleDispatcher, compositorViewHolder, tabProvider, insetObserverView, coordinator.init(window, lifecycleDispatcher, compositorViewHolder, tabProvider,
backShouldCloseTab, onBackPressed, showHistoryManager, historyMenu, insetObserverView, backShouldCloseTab, onBackPressed, layoutManager,
bottomSheetControllerSupplier); showHistoryManager, historyMenu, bottomSheetControllerSupplier);
return coordinator; return coordinator;
} }
/** /**
* Initializes the navigation layout and internal objects. * Initializes the navigation layout and internal objects.
*/ */
private void init(ActivityLifecycleDispatcher lifecycleDispatcher, private void init(WindowAndroid window, ActivityLifecycleDispatcher lifecycleDispatcher,
CompositorViewHolder compositorViewHolder, ActivityTabProvider tabProvider, CompositorViewHolder compositorViewHolder, ActivityTabProvider tabProvider,
InsetObserverView insetObserverView, Function<Tab, Boolean> backShouldCloseTab, InsetObserverView insetObserverView, Function<Tab, Boolean> backShouldCloseTab,
Runnable onBackPressed, Consumer<Tab> showHistoryManager, String historyMenu, Runnable onBackPressed, LayoutManager layoutManager, Consumer<Tab> showHistoryManager,
Supplier<BottomSheetController> bottomSheetControllerSupplier) { String historyMenu, Supplier<BottomSheetController> bottomSheetControllerSupplier) {
mOverscrollGlowOverlay = new OverscrollGlowOverlay(window, compositorViewHolder,
() -> compositorViewHolder.getLayoutManager().getActiveLayout().requestUpdate());
mNavigationLayout = new HistoryNavigationLayout(compositorViewHolder.getContext(), mNavigationLayout = new HistoryNavigationLayout(compositorViewHolder.getContext(),
this::getGlowEffect, this::getNavigationSheet, this::isNativePage, mOverscrollGlowOverlay, this::getNavigationSheet,
(direction) -> mNavigationHandler.navigate(direction)); (direction) -> mNavigationHandler.navigate(direction));
mParentView = compositorViewHolder; mParentView = compositorViewHolder;
...@@ -153,6 +155,7 @@ public class HistoryNavigationCoordinator ...@@ -153,6 +155,7 @@ public class HistoryNavigationCoordinator
mInsetObserverView = insetObserverView; mInsetObserverView = insetObserverView;
insetObserverView.addObserver(this); insetObserverView.addObserver(this);
} }
layoutManager.addSceneOverlayToFront(mOverscrollGlowOverlay);
} }
private boolean isNativePage() { private boolean isNativePage() {
...@@ -238,40 +241,11 @@ public class HistoryNavigationCoordinator ...@@ -238,40 +241,11 @@ public class HistoryNavigationCoordinator
mShowHistoryManager, mHistoryMenu, mBottomSheetControllerSupplier) mShowHistoryManager, mHistoryMenu, mBottomSheetControllerSupplier)
: HistoryNavigationDelegate.DEFAULT; : HistoryNavigationDelegate.DEFAULT;
initNavigationHandler(delegate); initNavigationHandler(delegate);
// Reset CompositorGlowEffect for new a WebContents. Destroy the current one
// (for its native object) so it can be created again lazily.
if (mWebContents != webContents) {
resetCompositorGlowEffect();
mWebContents = webContents;
}
} }
} else {
resetCompositorGlowEffect();
} }
if (mTab != null) SwipeRefreshHandler.from(mTab).setNavigationCoordinator(this); if (mTab != null) SwipeRefreshHandler.from(mTab).setNavigationCoordinator(this);
} }
/**
* Create {@link NavigationGlow} object lazily.
* TODO(jinsukkim): Consider using SceneOverlay to replace this.
*/
private NavigationGlow getGlowEffect() {
if (isNativePage()) {
if (mJavaGlowEffect == null) {
mJavaGlowEffect = new AndroidUiNavigationGlow(mNavigationLayout);
}
return mJavaGlowEffect;
} else {
// TODO(crbug.com/1102275): Investigate when this is called with nulled mWebContents.
if (mCompositorGlowEffect == null && mWebContents != null) {
mCompositorGlowEffect =
new CompositorNavigationGlow(mNavigationLayout, mWebContents);
}
return mCompositorGlowEffect;
}
}
/** /**
* Initialize {@link NavigationHandler} object. * Initialize {@link NavigationHandler} object.
* @param delegate {@link HistoryNavigationDelegate} providing info and a factory method. * @param delegate {@link HistoryNavigationDelegate} providing info and a factory method.
...@@ -377,7 +351,10 @@ public class HistoryNavigationCoordinator ...@@ -377,7 +351,10 @@ public class HistoryNavigationCoordinator
} }
mCleanupRunnable.run(); mCleanupRunnable.run();
mNavigationLayout = null; mNavigationLayout = null;
resetCompositorGlowEffect(); if (mOverscrollGlowOverlay != null) {
mOverscrollGlowOverlay.destroy();
mOverscrollGlowOverlay = null;
}
mDelegate = HistoryNavigationDelegate.DEFAULT; mDelegate = HistoryNavigationDelegate.DEFAULT;
if (mNavigationHandler != null) { if (mNavigationHandler != null) {
mNavigationHandler.setDelegate(mDelegate); mNavigationHandler.setDelegate(mDelegate);
...@@ -390,13 +367,6 @@ public class HistoryNavigationCoordinator ...@@ -390,13 +367,6 @@ public class HistoryNavigationCoordinator
} }
} }
private void resetCompositorGlowEffect() {
if (mCompositorGlowEffect != null) {
mCompositorGlowEffect.destroy();
mCompositorGlowEffect = null;
}
}
@VisibleForTesting @VisibleForTesting
NavigationHandler getNavigationHandlerForTesting() { NavigationHandler getNavigationHandlerForTesting() {
return mNavigationHandler; return mNavigationHandler;
......
...@@ -20,8 +20,11 @@ import org.chromium.chrome.browser.gesturenav.NavigationBubble.CloseTarget; ...@@ -20,8 +20,11 @@ import org.chromium.chrome.browser.gesturenav.NavigationBubble.CloseTarget;
* FrameLayout that supports side-wise slide gesture for history navigation. * FrameLayout that supports side-wise slide gesture for history navigation.
*/ */
class HistoryNavigationLayout extends FrameLayout implements ViewGroup.OnHierarchyChangeListener { class HistoryNavigationLayout extends FrameLayout implements ViewGroup.OnHierarchyChangeListener {
// Supplies a {@link NavigationGlow} object for either native or rendered page. // {@link NavigationGlow} object for rendered pages.
private final Supplier<NavigationGlow> mGlowEffect; private final NavigationGlow mCompositorGlowEffect;
// Whether the current tab shows a native or rendered page.
private final Supplier<Boolean> mIsNativePage;
// Callback that performs navigation action in response to UI., // Callback that performs navigation action in response to UI.,
private final Callback<Boolean> mNavigateCallback; private final Callback<Boolean> mNavigateCallback;
...@@ -29,6 +32,9 @@ class HistoryNavigationLayout extends FrameLayout implements ViewGroup.OnHierarc ...@@ -29,6 +32,9 @@ class HistoryNavigationLayout extends FrameLayout implements ViewGroup.OnHierarc
// Frame layout hosting the arrow puck UI. // Frame layout hosting the arrow puck UI.
private SideSlideLayout mSideSlideLayout; private SideSlideLayout mSideSlideLayout;
// {@link NavigationGlow} object for native pages. Lazily created.
private NavigationGlow mJavaGlowEffect;
// Navigation sheet showing the navigation history. // Navigation sheet showing the navigation history.
private Supplier<NavigationSheet> mNavigationSheet; private Supplier<NavigationSheet> mNavigationSheet;
...@@ -40,10 +46,12 @@ class HistoryNavigationLayout extends FrameLayout implements ViewGroup.OnHierarc ...@@ -40,10 +46,12 @@ class HistoryNavigationLayout extends FrameLayout implements ViewGroup.OnHierarc
// it does not conflict with pending Android draws. // it does not conflict with pending Android draws.
private Runnable mDetachLayoutRunnable; private Runnable mDetachLayoutRunnable;
public HistoryNavigationLayout(Context context, Supplier<NavigationGlow> glowEffect, public HistoryNavigationLayout(Context context, Supplier<Boolean> isNativePage,
Supplier<NavigationSheet> navigationSheet, Callback<Boolean> navigateCallback) { NavigationGlow compositorGlowEffect, Supplier<NavigationSheet> navigationSheet,
Callback<Boolean> navigateCallback) {
super(context); super(context);
mGlowEffect = glowEffect; mIsNativePage = isNativePage;
mCompositorGlowEffect = compositorGlowEffect;
mNavigationSheet = navigationSheet; mNavigationSheet = navigationSheet;
mNavigateCallback = navigateCallback; mNavigateCallback = navigateCallback;
setOnHierarchyChangeListener(this); setOnHierarchyChangeListener(this);
...@@ -98,12 +106,24 @@ class HistoryNavigationLayout extends FrameLayout implements ViewGroup.OnHierarc ...@@ -98,12 +106,24 @@ class HistoryNavigationLayout extends FrameLayout implements ViewGroup.OnHierarc
mNavigationSheet.get().start(forward, closeIndicator != CloseTarget.NONE); mNavigationSheet.get().start(forward, closeIndicator != CloseTarget.NONE);
} }
/**
* Create {@link NavigationGlow} object, lazily when possible.
*/
private NavigationGlow getGlowEffect() {
if (mIsNativePage.get()) {
if (mJavaGlowEffect == null) mJavaGlowEffect = new AndroidUiNavigationGlow(this);
return mJavaGlowEffect;
} else {
return mCompositorGlowEffect;
}
}
/** /**
* Start showing edge glow effect. * Start showing edge glow effect.
* @param p Current position of the touch event. * @param p Current position of the touch event.
*/ */
void showGlow(GesturePoint p) { void showGlow(GesturePoint p) {
if (mGlowEffect.get() != null) mGlowEffect.get().prepare(p.x, p.y); getGlowEffect().prepare(p.x, p.y);
} }
/** /**
...@@ -127,7 +147,7 @@ class HistoryNavigationLayout extends FrameLayout implements ViewGroup.OnHierarc ...@@ -127,7 +147,7 @@ class HistoryNavigationLayout extends FrameLayout implements ViewGroup.OnHierarc
* @param offset The change in horizontal pull distance. * @param offset The change in horizontal pull distance.
*/ */
void pullGlow(float offset) { void pullGlow(float offset) {
if (mGlowEffect.get() != null) mGlowEffect.get().onScroll(offset); getGlowEffect().onScroll(offset);
} }
/** /**
...@@ -147,7 +167,7 @@ class HistoryNavigationLayout extends FrameLayout implements ViewGroup.OnHierarc ...@@ -147,7 +167,7 @@ class HistoryNavigationLayout extends FrameLayout implements ViewGroup.OnHierarc
* Release the glow effect. * Release the glow effect.
*/ */
void releaseGlow() { void releaseGlow() {
if (mGlowEffect.get() != null) mGlowEffect.get().release(); getGlowEffect().release();
} }
/** /**
...@@ -163,7 +183,7 @@ class HistoryNavigationLayout extends FrameLayout implements ViewGroup.OnHierarc ...@@ -163,7 +183,7 @@ class HistoryNavigationLayout extends FrameLayout implements ViewGroup.OnHierarc
* Reset the glow effect. * Reset the glow effect.
*/ */
void resetGlow() { void resetGlow() {
if (mGlowEffect.get() != null) mGlowEffect.get().reset(); getGlowEffect().reset();
} }
/** /**
......
...@@ -23,11 +23,6 @@ abstract class NavigationGlow { ...@@ -23,11 +23,6 @@ abstract class NavigationGlow {
*/ */
public abstract void prepare(float startX, float startY); public abstract void prepare(float startX, float startY);
/**
* @return The total amount of pull offset.
*/
public abstract float getPullOffset();
/** /**
* Called when user scroll is performed. * Called when user scroll is performed.
* @param offset Newly updated pull offset. * @param offset Newly updated pull offset.
......
// 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.RectF;
import android.view.ViewGroup;
import org.chromium.chrome.browser.compositor.LayerTitleCache;
import org.chromium.chrome.browser.compositor.layouts.components.VirtualView;
import org.chromium.chrome.browser.compositor.layouts.eventfilter.EventFilter;
import org.chromium.chrome.browser.compositor.overlays.SceneOverlay;
import org.chromium.chrome.browser.compositor.scene_layer.SceneOverlayLayer;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.resources.ResourceManager;
import java.util.List;
/**
* Handles overscroll glow effect when gesture navigation can't go forward any more.
* Renders the effect on a compositor layer in scene overlay layer tree.
*/
class OverscrollGlowOverlay extends NavigationGlow implements SceneOverlay {
private final OverscrollSceneLayer mSceneLayer;
private final Runnable mRequestLayerUpdate;
// True while the overlay is visible for showing overscroll effect.
private boolean mIsShowing;
private float mOffset;
OverscrollGlowOverlay(WindowAndroid window, ViewGroup parentView, Runnable requestLayerUpdate) {
super(parentView);
mSceneLayer = new OverscrollSceneLayer(window, parentView);
mRequestLayerUpdate = requestLayerUpdate;
}
// NavigationGlow implementation
@Override
public void prepare(float startX, float startY) {
mSceneLayer.prepare(startX, startY);
setIsShowing(true);
}
private void setIsShowing(boolean isShowing) {
mIsShowing = isShowing;
mOffset = 0.f;
}
@Override
public void onScroll(float offset) {
mOffset = offset;
if (mIsShowing) mRequestLayerUpdate.run();
}
@Override
public void release() {
mSceneLayer.release();
mOffset = 0.f;
}
@Override
public void reset() {
setIsShowing(false);
mSceneLayer.reset();
}
@Override
public void destroy() {
mSceneLayer.destroy();
}
// SceneOverlay implementation
@Override
public SceneOverlayLayer getUpdatedSceneOverlayTree(RectF viewport, RectF visibleViewport,
LayerTitleCache layerTitleCache, ResourceManager resourceManager, float yOffset) {
if (!mSceneLayer.update(resourceManager, mOffset)) setIsShowing(false);
return mSceneLayer;
}
@Override
public boolean isSceneOverlayTreeShowing() {
return mIsShowing;
}
@Override
public EventFilter getEventFilter() {
return null;
}
@Override
public void onSizeChanged(
float width, float height, float visibleViewportOffsetY, int orientation) {}
@Override
public void getVirtualViews(List<VirtualView> views) {}
@Override
public boolean shouldHideAndroidBrowserControls() {
return false;
}
@Override
public boolean updateOverlay(long time, long dt) {
return true;
}
@Override
public boolean onBackPressed() {
return false;
}
@Override
public boolean handlesTabCreating() {
return false;
}
}
// 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.view.View;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.chrome.browser.compositor.scene_layer.SceneLayer;
import org.chromium.chrome.browser.compositor.scene_layer.SceneOverlayLayer;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.resources.ResourceManager;
/**
* {@link SceneOverlayLayer} implementation for gesture navigation overscroll effect.
*/
@JNINamespace("android")
class OverscrollSceneLayer extends SceneOverlayLayer {
private final View mParentView;
// NOTE: If you use SceneLayer's native pointer here, the JNI generator will try to
// downcast using reinterpret_cast<>. We keep a separate pointer to avoid it.
private long mNativePtr;
private float mAccumulatedScroll;
OverscrollSceneLayer(WindowAndroid window, View parentView) {
mParentView = parentView;
mNativePtr = OverscrollSceneLayerJni.get().init(OverscrollSceneLayer.this, window);
assert mNativePtr != 0;
}
/**
* Initialize a new overscroll effect.
*/
void prepare(float startX, float startY) {
mAccumulatedScroll = 0.f;
OverscrollSceneLayerJni.get().prepare(mNativePtr, OverscrollSceneLayer.this, startX, startY,
mParentView.getWidth(), mParentView.getHeight());
}
/**
* Send down the swipe offset to update animation for overscroll effect.
* @param resourceManager An object for accessing static and dynamic resources.
* @param offset Swipe offset from touch events.
* @return {@code true} if the animation is still in progress; {@code false} if the animation
* is completed.
*/
boolean update(ResourceManager resourceManager, float offset) {
float xDelta = -(offset - mAccumulatedScroll);
mAccumulatedScroll = offset;
// Do not go down with zero delta since it can make the animation jerky. But return true
// to keep the animation going on.
if (xDelta == 0.f) return true;
return OverscrollSceneLayerJni.get().update(
mNativePtr, OverscrollSceneLayer.this, resourceManager, mAccumulatedScroll, xDelta);
}
/** Release the glow effect to recede slowly. */
void release() {
OverscrollSceneLayerJni.get().update(mNativePtr, OverscrollSceneLayer.this, null, 0.f, 0.f);
mAccumulatedScroll = 0.f;
}
/** Reset the glow effect. */
void reset() {
OverscrollSceneLayerJni.get().onReset(mNativePtr, OverscrollSceneLayer.this);
}
@Override
public void setContentTree(SceneLayer contentTree) {
OverscrollSceneLayerJni.get().setContentTree(
mNativePtr, OverscrollSceneLayer.this, contentTree);
}
@Override
protected void initializeNative() {
// Native side is initialized in the constructor to use the passed WindowAndroid.
}
@Override
public void destroy() {
super.destroy();
mNativePtr = 0;
}
@NativeMethods
interface Natives {
long init(OverscrollSceneLayer caller, WindowAndroid window);
void prepare(long nativeOverscrollSceneLayer, OverscrollSceneLayer caller, float startX,
float startY, int width, int height);
void setContentTree(long nativeOverscrollSceneLayer, OverscrollSceneLayer caller,
SceneLayer contentTree);
boolean update(long nativeOverscrollSceneLayer, OverscrollSceneLayer caller,
ResourceManager resourceManager, float accumulatedScroll, float delta);
void onReset(long nativeOverscrollSceneLayer, OverscrollSceneLayer caller);
}
}
...@@ -226,9 +226,10 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator implements Native ...@@ -226,9 +226,10 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator implements Native
// clang-format off // clang-format off
mHistoryNavigationCoordinator = HistoryNavigationCoordinator.create( mHistoryNavigationCoordinator = HistoryNavigationCoordinator.create(
mActivity.getLifecycleDispatcher(), mActivity.getCompositorViewHolder(), mActivity.getWindowAndroid(), mActivity.getLifecycleDispatcher(),
mActivity.getActivityTabProvider(), mActivity.getInsetObserverView(), mActivity.getCompositorViewHolder(), mActivity.getActivityTabProvider(),
mActivity::backShouldCloseTab, mActivity::onBackPressed, mActivity.getInsetObserverView(), mActivity::backShouldCloseTab,
mActivity::onBackPressed, layoutManager,
tab -> HistoryManagerUtils.showHistoryManager(mActivity, tab), tab -> HistoryManagerUtils.showHistoryManager(mActivity, tab),
mActivity.getResources().getString(R.string.show_full_history), mActivity.getResources().getString(R.string.show_full_history),
() -> mActivity.isActivityFinishingOrDestroyed() ? null () -> mActivity.isActivityFinishingOrDestroyed() ? null
......
...@@ -2312,13 +2312,13 @@ static_library("browser") { ...@@ -2312,13 +2312,13 @@ static_library("browser") {
"android/compositor/layer/toolbar_layer.h", "android/compositor/layer/toolbar_layer.h",
"android/compositor/layer_title_cache.cc", "android/compositor/layer_title_cache.cc",
"android/compositor/layer_title_cache.h", "android/compositor/layer_title_cache.h",
"android/compositor/navigation_glow.cc",
"android/compositor/navigation_glow.h",
"android/compositor/resources/resource_factory.cc", "android/compositor/resources/resource_factory.cc",
"android/compositor/resources/toolbar_resource.cc", "android/compositor/resources/toolbar_resource.cc",
"android/compositor/resources/toolbar_resource.h", "android/compositor/resources/toolbar_resource.h",
"android/compositor/scene_layer/contextual_search_scene_layer.cc", "android/compositor/scene_layer/contextual_search_scene_layer.cc",
"android/compositor/scene_layer/contextual_search_scene_layer.h", "android/compositor/scene_layer/contextual_search_scene_layer.h",
"android/compositor/scene_layer/overscroll_scene_layer.cc",
"android/compositor/scene_layer/overscroll_scene_layer.h",
"android/compositor/scene_layer/scene_layer.cc", "android/compositor/scene_layer/scene_layer.cc",
"android/compositor/scene_layer/scene_layer.h", "android/compositor/scene_layer/scene_layer.h",
"android/compositor/scene_layer/scrolling_bottom_view_scene_layer.cc", "android/compositor/scene_layer/scrolling_bottom_view_scene_layer.cc",
......
// 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.
#include "chrome/browser/android/compositor/navigation_glow.h"
#include "chrome/android/chrome_jni_headers/CompositorNavigationGlow_jni.h"
#include "chrome/browser/android/compositor/scene_layer/scene_layer.h"
#include "content/public/browser/web_contents.h"
#include "ui/android/edge_effect.h"
#include "ui/android/resources/resource_manager.h"
#include "ui/android/window_android.h"
#include "ui/android/window_android_compositor.h"
using base::android::JavaParamRef;
namespace android {
NavigationGlow::NavigationGlow(content::WebContents* web_contents)
: glow_effect_(std::make_unique<ui::OverscrollGlow>(this)) {
DCHECK(web_contents);
view_ = web_contents->GetNativeView();
view_->AddObserver(this);
layer_ = view_->GetLayer();
OnAttachedToWindow();
}
NavigationGlow::~NavigationGlow() = default;
void NavigationGlow::OnAttachedToWindow() {
window_ = view_->GetWindowAndroid();
if (window_ != nullptr) {
window_->AddObserver(this);
if (!glow_effect_)
glow_effect_ = std::make_unique<ui::OverscrollGlow>(this);
}
}
void NavigationGlow::OnDetachedFromWindow() {
if (window_ != nullptr) {
window_->RemoveObserver(this);
glow_effect_.reset();
}
window_ = nullptr;
}
void NavigationGlow::OnViewAndroidDestroyed() {
// Ideally, ViewAndroid should be detaching itself as part of destruction, but
// this also clears the window reference as the View is being destroyed prior
// to the Window.
OnDetachedFromWindow();
view_ = nullptr;
layer_ = nullptr;
}
void NavigationGlow::Prepare(JNIEnv* env,
const JavaParamRef<jobject>& obj,
jfloat start_x,
jfloat start_y,
jint width,
jint height) {
start_pos_ = gfx::Vector2dF(start_x, start_y);
const gfx::SizeF viewport_size(width, height);
// |OverscrollGlow| activates glow effect only when content is bigger than
// viewport. Make it bigger by 1.f.
const gfx::SizeF content_size(width + 1.f, height);
const gfx::Vector2dF content_scroll_offset(1, 0);
glow_effect_->OnFrameUpdated(viewport_size, content_size,
content_scroll_offset);
}
void NavigationGlow::OnOverscroll(JNIEnv* env,
const JavaParamRef<jobject>& obj,
jfloat accumulated_overscroll_x,
jfloat delta_x) {
gfx::Vector2dF accumulated_overscroll(accumulated_overscroll_x, 0);
gfx::Vector2dF overscroll_delta(delta_x, 0);
if (glow_effect_->OnOverscrolled(base::TimeTicks::Now(),
accumulated_overscroll, overscroll_delta,
gfx::Vector2dF(0, 0), start_pos_)) {
window_->SetNeedsAnimate();
}
}
void NavigationGlow::OnReset(JNIEnv* env, const JavaParamRef<jobject>& obj) {
glow_effect_->Reset();
}
void NavigationGlow::Destroy(JNIEnv* env, const JavaParamRef<jobject>& obj) {
OnDetachedFromWindow();
if (view_ != nullptr)
view_->RemoveObserver(this);
delete this;
}
void NavigationGlow::OnAnimate(base::TimeTicks frame_time) {
if (layer_ != nullptr && glow_effect_->Animate(frame_time, layer_))
window_->SetNeedsAnimate();
}
std::unique_ptr<ui::EdgeEffect> NavigationGlow::CreateEdgeEffect() {
auto& resource_manager = window_->GetCompositor()->GetResourceManager();
return std::make_unique<ui::EdgeEffect>(&resource_manager);
}
static jlong JNI_CompositorNavigationGlow_Init(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& jweb_contents) {
auto* web_contents = content::WebContents::FromJavaWebContents(jweb_contents);
if (web_contents == nullptr)
return 0;
return reinterpret_cast<intptr_t>(new NavigationGlow(web_contents));
}
} // namespace android
// 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.
#include "chrome/browser/android/compositor/scene_layer/overscroll_scene_layer.h"
#include "chrome/android/chrome_jni_headers/OverscrollSceneLayer_jni.h"
#include "ui/android/resources/resource_manager_impl.h"
#include "ui/android/window_android.h"
using base::android::JavaParamRef;
namespace android {
OverscrollSceneLayer::OverscrollSceneLayer(JNIEnv* env,
const JavaParamRef<jobject>& jobj,
const JavaParamRef<jobject>& jwindow)
: SceneLayer(env, jobj),
window_(ui::WindowAndroid::FromJavaWindowAndroid(jwindow)),
glow_effect_(std::make_unique<ui::OverscrollGlow>(this)) {
window_->AddObserver(this);
}
OverscrollSceneLayer::~OverscrollSceneLayer() {
window_->RemoveObserver(this);
}
std::unique_ptr<ui::EdgeEffect> OverscrollSceneLayer::CreateEdgeEffect() {
return std::make_unique<ui::EdgeEffect>(resource_manager_);
}
void OverscrollSceneLayer::Prepare(JNIEnv* env,
const JavaParamRef<jobject>& obj,
jfloat start_x,
jfloat start_y,
jint width,
jint height) {
start_pos_ = gfx::Vector2dF(start_x, start_y);
const gfx::SizeF viewport_size(width, height);
// |OverscrollGlow| activates glow effect only when content is bigger than
// viewport. Make it bigger by 1.f.
const gfx::SizeF content_size(width + 1.f, height);
const gfx::Vector2dF content_scroll_offset(1, 0);
glow_effect_->OnFrameUpdated(viewport_size, content_size,
content_scroll_offset);
}
jboolean OverscrollSceneLayer::Update(
JNIEnv* env,
const JavaParamRef<jobject>& object,
const JavaParamRef<jobject>& jresource_manager,
jfloat accumulated_overscroll_x,
jfloat delta_x) {
if (!resource_manager_) {
resource_manager_ =
ui::ResourceManagerImpl::FromJavaObject(jresource_manager);
}
gfx::Vector2dF accumulated_overscroll(accumulated_overscroll_x, 0);
gfx::Vector2dF overscroll_delta(delta_x, 0);
if (glow_effect_->OnOverscrolled(base::TimeTicks::Now(),
accumulated_overscroll, overscroll_delta,
gfx::Vector2dF(0, 0), start_pos_)) {
window_->SetNeedsAnimate();
return true;
}
return false;
}
void OverscrollSceneLayer::OnAnimate(base::TimeTicks frame_time) {
if (glow_effect_->Animate(frame_time, layer().get()))
window_->SetNeedsAnimate();
}
void OverscrollSceneLayer::SetContentTree(
JNIEnv* env,
const JavaParamRef<jobject>& jobj,
const JavaParamRef<jobject>& jcontent_tree) {
SceneLayer* content_tree = FromJavaObject(env, jcontent_tree);
if (!content_tree || !content_tree->layer())
return;
if (!content_tree->layer()->parent() ||
(content_tree->layer()->parent()->id() != layer()->id())) {
layer()->AddChild(content_tree->layer());
}
}
void OverscrollSceneLayer::OnReset(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
glow_effect_->Reset();
}
static jlong JNI_OverscrollSceneLayer_Init(
JNIEnv* env,
const JavaParamRef<jobject>& jobj,
const JavaParamRef<jobject>& jwindow) {
// This will automatically bind to the Java object and pass ownership there.
OverscrollSceneLayer* tree_provider =
new OverscrollSceneLayer(env, jobj, jwindow);
return reinterpret_cast<intptr_t>(tree_provider);
}
} // namespace android
// Copyright 2019 The Chromium Authors. All rights reserved. // Copyright 2020 The Chromium Authors. All rights reserved.
// 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.
#ifndef CHROME_BROWSER_ANDROID_COMPOSITOR_NAVIGATION_GLOW_H_ #ifndef CHROME_BROWSER_ANDROID_COMPOSITOR_SCENE_LAYER_OVERSCROLL_SCENE_LAYER_H_
#define CHROME_BROWSER_ANDROID_COMPOSITOR_NAVIGATION_GLOW_H_ #define CHROME_BROWSER_ANDROID_COMPOSITOR_SCENE_LAYER_OVERSCROLL_SCENE_LAYER_H_
#include "base/android/scoped_java_ref.h" #include "base/android/jni_weak_ref.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "chrome/browser/android/compositor/scene_layer/scene_layer.h"
#include "ui/android/overscroll_glow.h" #include "ui/android/overscroll_glow.h"
#include "ui/android/view_android_observer.h"
#include "ui/android/window_android_observer.h" #include "ui/android/window_android_observer.h"
namespace content {
class WebContents;
}
namespace ui { namespace ui {
class ViewAndroid; class ResourceManager;
class WindowAndroid; class WindowAndroid;
} // namespace ui } // namespace ui
namespace android { namespace android {
// Native part handling the edge glow effect in history navigation UI. // Native layer that handles the overscroll glow animation effect for
class NavigationGlow : public ui::OverscrollGlowClient, // gesture navigation.
public ui::WindowAndroidObserver, class OverscrollSceneLayer : public SceneLayer,
public ui::ViewAndroidObserver { public ui::WindowAndroidObserver,
public ui::OverscrollGlowClient {
public: public:
explicit NavigationGlow(content::WebContents* web_contents); OverscrollSceneLayer(JNIEnv* env,
~NavigationGlow() override; const base::android::JavaParamRef<jobject>& jobj,
const base::android::JavaParamRef<jobject>& jwindow);
~OverscrollSceneLayer() override;
void Prepare(JNIEnv* env, void Prepare(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj, const base::android::JavaParamRef<jobject>& obj,
jfloat start_x, jfloat start_x,
jfloat start_y, jfloat start_y,
jint width, jint width,
jint height); jint height);
void OnOverscroll(JNIEnv* env, jboolean Update(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj, const base::android::JavaParamRef<jobject>& object,
jfloat accumulated_overscroll_x, const base::android::JavaParamRef<jobject>& jresource_manager,
jfloat delta_x); jfloat accumulated_overscroll_x,
void OnReset(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); jfloat delta_x);
void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); void SetContentTree(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& jobj,
const base::android::JavaParamRef<jobject>& jcontent_tree);
void OnReset(JNIEnv* env, const base::android::JavaParamRef<jobject>& jobj);
void SetNeedsAnimate();
// ui::WindowAndroidObserver implementation. // ui::WindowAndroidObserver implementation.
void OnCompositingDidCommit() override {} void OnCompositingDidCommit() override {}
...@@ -52,22 +58,19 @@ class NavigationGlow : public ui::OverscrollGlowClient, ...@@ -52,22 +58,19 @@ class NavigationGlow : public ui::OverscrollGlowClient,
void OnActivityStopped() override {} void OnActivityStopped() override {}
void OnActivityStarted() override {} void OnActivityStarted() override {}
// ui::ViewAndroidObserver implementation.
void OnAttachedToWindow() override;
void OnDetachedFromWindow() override;
void OnViewAndroidDestroyed() override;
private: private:
// OverscrollGlowClient implementation. // OverscrollGlowClient implementation.
std::unique_ptr<ui::EdgeEffect> CreateEdgeEffect() override; std::unique_ptr<ui::EdgeEffect> CreateEdgeEffect() override;
cc::Layer* layer_ = nullptr; ui::WindowAndroid* const window_;
ui::WindowAndroid* window_ = nullptr;
ui::ViewAndroid* view_ = nullptr;
std::unique_ptr<ui::OverscrollGlow> glow_effect_; std::unique_ptr<ui::OverscrollGlow> glow_effect_;
ui::ResourceManager* resource_manager_ = nullptr;
gfx::Vector2dF start_pos_; gfx::Vector2dF start_pos_;
DISALLOW_COPY_AND_ASSIGN(OverscrollSceneLayer);
}; };
} // namespace android } // namespace android
#endif // CHROME_BROWSER_ANDROID_COMPOSITOR_NAVIGATION_GLOW_H_ #endif // CHROME_BROWSER_ANDROID_COMPOSITOR_SCENE_LAYER_OVERSCROLL_SCENE_LAYER_H_
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