Commit 40fb1cc7 authored by Matt Jones's avatar Matt Jones Committed by Commit Bot

Move ownership of SceneOverlays to LayoutManager

This patch moves the ownership of SceneOverlays from individual Layouts
to the LayoutManager. Deciding whether an overlay should be shown can
be done at the feature level rather than depending on the LayoutManager
to sort them. For the most part, this patch is a logic move, but checks
for whether an overlay is showing have been added before calling their
respective methods.

Bug: 1100332
Change-Id: Ic7f4bc9823295684bf3cc45007b0b227db11dd82
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2380267Reviewed-by: default avatarMei Liang <meiliang@chromium.org>
Commit-Queue: Matthew Jones <mdjones@chromium.org>
Cr-Commit-Position: refs/heads/master@{#805940}
parent 253d9157
......@@ -17,12 +17,9 @@ import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider
import org.chromium.chrome.browser.compositor.LayerTitleCache;
import org.chromium.chrome.browser.compositor.animation.CompositorAnimationHandler;
import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
import org.chromium.chrome.browser.compositor.layouts.components.VirtualView;
import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
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.SceneLayer;
import org.chromium.chrome.browser.compositor.scene_layer.SceneOverlayLayer;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
......@@ -32,7 +29,6 @@ import org.chromium.ui.resources.ResourceManager;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
/**
......@@ -96,9 +92,6 @@ public abstract class Layout implements TabContentManager.ThumbnailChangeListene
protected TabModelSelector mTabModelSelector;
protected TabContentManager mTabContentManager;
// Tablet tab strip managers.
private final List<SceneOverlay> mSceneOverlays = new ArrayList<SceneOverlay>();
// Helpers
private final LayoutUpdateHost mUpdateHost;
protected final LayoutRenderHost mRenderHost;
......@@ -152,28 +145,6 @@ public abstract class Layout implements TabContentManager.ThumbnailChangeListene
*/
public void onFinishNativeInitialization() {}
/**
* Adds a {@link SceneOverlay} that can be shown in this layout to the first position in the
* scene overlay list, meaning it will be drawn behind all other overlays.
* @param overlay The {@link SceneOverlay} to be added.
*/
void addSceneOverlayToBack(SceneOverlay overlay) {
assert !mSceneOverlays.contains(overlay);
mSceneOverlays.add(0, overlay);
}
/**
* Adds a {@link SceneOverlay} that can potentially be shown on top of this {@link Layout}. The
* {@link SceneOverlay}s added to this {@link Layout} will be cascaded in the order they are
* added. The {@link SceneOverlay} added first will become the content of the
* {@link SceneOverlay} added second, and so on.
* @param helper A {@link SceneOverlay} to add as a potential overlay for this {@link Layout}.
*/
public void addSceneOverlay(SceneOverlay helper) {
assert !mSceneOverlays.contains(helper);
mSceneOverlays.add(helper);
}
/**
* Cleans up any internal state. This object should not be used after this call.
*/
......@@ -194,18 +165,6 @@ public abstract class Layout implements TabContentManager.ThumbnailChangeListene
return mUpdateHost.isActiveLayout(this);
}
/**
* Get a list of virtual views for accessibility.
*
* @param views A List to populate with virtual views.
*/
public void getVirtualViews(List<VirtualView> views) {
// TODO(dtrainor): Investigate order.
for (int i = 0; i < mSceneOverlays.size(); i++) {
mSceneOverlays.get(i).getVirtualViews(views);
}
}
/**
* Creates a {@link LayoutTab}.
* @param id The id of the reference {@link Tab} in the {@link TabModel}.
......@@ -275,11 +234,7 @@ public abstract class Layout implements TabContentManager.ThumbnailChangeListene
* @param time The current time of the app in ms.
* @param dt The delta time between update frames in ms.
*/
protected void updateLayout(long time, long dt) {
for (int i = 0; i < mSceneOverlays.size(); i++) {
mSceneOverlays.get(i).updateOverlay(time, dt);
}
}
protected void updateLayout(long time, long dt) {}
/**
* Update snapping to pixel. To be called once every frame.
......@@ -380,11 +335,6 @@ public abstract class Layout implements TabContentManager.ThumbnailChangeListene
if (layoutPropertiesChanged) {
notifySizeChanged(width, height, orientation);
}
// 5. TODO(dtrainor): Notify the overlay objects.
for (int i = 0; i < mSceneOverlays.size(); i++) {
mSceneOverlays.get(i).onSizeChanged(width, height, visibleViewportPx.top, orientation);
}
}
/**
......@@ -595,10 +545,6 @@ public abstract class Layout implements TabContentManager.ThumbnailChangeListene
* @return Whether or not the layout consumed the event.
*/
public boolean onBackPressed() {
for (int i = 0; i < mSceneOverlays.size(); i++) {
// If the back button was consumed by any overlays, return true.
if (mSceneOverlays.get(i).onBackPressed()) return true;
}
return false;
}
......@@ -744,14 +690,6 @@ public abstract class Layout implements TabContentManager.ThumbnailChangeListene
*/
public boolean handlesTabCreating() {
if (mLayoutTabs == null || mLayoutTabs.length != 1) return false;
for (int i = 0; i < mSceneOverlays.size(); i++) {
if (mSceneOverlays.get(i).handlesTabCreating()) {
// Prevent animation from happening if the overlay handles creation.
startHiding(mLayoutTabs[0].getId(), false);
doneHiding();
return true;
}
}
return false;
}
......@@ -794,15 +732,6 @@ public abstract class Layout implements TabContentManager.ThumbnailChangeListene
*/
public EventFilter findInterceptingEventFilter(
MotionEvent e, PointF offsets, boolean isKeyboardShowing) {
// The last added overlay will be drawn on top of everything else, therefore the last
// filter added should have the first chance to intercept any touch events.
for (int i = mSceneOverlays.size() - 1; i >= 0; i--) {
EventFilter eventFilter = mSceneOverlays.get(i).getEventFilter();
if (eventFilter == null) continue;
if (offsets != null) eventFilter.setCurrentMotionEventOffsets(offsets.x, offsets.y);
if (eventFilter.onInterceptTouchEvent(e, isKeyboardShowing)) return eventFilter;
}
EventFilter layoutEventFilter = getEventFilter();
if (layoutEventFilter != null) {
if (offsets != null) {
......@@ -832,34 +761,13 @@ public abstract class Layout implements TabContentManager.ThumbnailChangeListene
ResourceManager resourceManager, BrowserControlsStateProvider browserControls) {
updateSceneLayer(viewport, visibleViewport, layerTitleCache, tabContentManager,
resourceManager, browserControls);
float offsetPx = browserControls != null ? browserControls.getTopControlOffset() : 0.f;
float dpToPx = getContext().getResources().getDisplayMetrics().density;
float offsetDp = offsetPx / dpToPx;
SceneLayer content = getSceneLayer();
for (int i = 0; i < mSceneOverlays.size(); i++) {
// If the SceneOverlay is not showing, don't bother adding it to the tree.
if (!mSceneOverlays.get(i).isSceneOverlayTreeShowing()) continue;
SceneOverlayLayer overlayLayer = mSceneOverlays.get(i).getUpdatedSceneOverlayTree(
viewport, visibleViewport, layerTitleCache, resourceManager, offsetDp);
overlayLayer.setContentTree(content);
content = overlayLayer;
}
return content;
return getSceneLayer();
}
/**
* @return Whether or not to force the browser controls Android view to hide.
*/
public boolean forceHideBrowserControlsAndroidView() {
for (int i = 0; i < mSceneOverlays.size(); i++) {
// If any overlay wants to hide tha Android version of the browser controls, hide them.
if (mSceneOverlays.get(i).shouldHideAndroidBrowserControls()) return true;
}
return false;
}
......
......@@ -37,6 +37,7 @@ import org.chromium.chrome.browser.compositor.layouts.eventfilter.EventFilter;
import org.chromium.chrome.browser.compositor.overlays.SceneOverlay;
import org.chromium.chrome.browser.compositor.overlays.toolbar.TopToolbarOverlayCoordinator;
import org.chromium.chrome.browser.compositor.scene_layer.SceneLayer;
import org.chromium.chrome.browser.compositor.scene_layer.SceneOverlayLayer;
import org.chromium.chrome.browser.contextualsearch.ContextualSearchManagementDelegate;
import org.chromium.chrome.browser.device.DeviceClassManager;
import org.chromium.chrome.browser.fullscreen.BrowserControlsManager;
......@@ -66,6 +67,7 @@ import org.chromium.ui.resources.ResourceManager;
import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
import org.chromium.ui.util.TokenHolder;
import java.util.ArrayList;
import java.util.List;
/**
......@@ -160,6 +162,9 @@ public class LayoutManager implements LayoutUpdateHost, LayoutProvider,
mBrowserControlsStateProviderSupplier = new ObservableSupplierImpl<>();
private final CompositorModelChangeProcessor.FrameRequestSupplier mFrameRequestSupplier;
/** The overlays that can be drawn on top of the active layout. */
protected final List<SceneOverlay> mSceneOverlays = new ArrayList<>();
/**
* Protected class to handle {@link TabModelObserver} related tasks. Extending classes will
* need to override any related calls to add new functionality */
......@@ -295,8 +300,25 @@ public class LayoutManager implements LayoutUpdateHost, LayoutProvider,
PointF offsets = getMotionOffsets(e);
EventFilter layoutFilter =
mActiveLayout.findInterceptingEventFilter(e, offsets, isKeyboardShowing);
// The last added overlay will be drawn on top of everything else, therefore the last
// filter added should have the first chance to intercept any touch events.
EventFilter layoutFilter = null;
for (int i = mSceneOverlays.size() - 1; i >= 0; i--) {
if (!mSceneOverlays.get(i).isSceneOverlayTreeShowing()) continue;
EventFilter eventFilter = mSceneOverlays.get(i).getEventFilter();
if (eventFilter == null) continue;
if (offsets != null) eventFilter.setCurrentMotionEventOffsets(offsets.x, offsets.y);
if (eventFilter.onInterceptTouchEvent(e, isKeyboardShowing)) {
layoutFilter = eventFilter;
break;
}
}
// If no overlay's filter took the event, check the layout.
if (layoutFilter == null) {
layoutFilter = mActiveLayout.findInterceptingEventFilter(e, offsets, isKeyboardShowing);
}
mIsNewEventFilter = layoutFilter != mActiveEventFilter;
mActiveEventFilter = layoutFilter;
......@@ -382,11 +404,17 @@ public class LayoutManager implements LayoutUpdateHost, LayoutProvider,
// TODO(crbug.com/1070281): Remove after the FrameRequestSupplier migrates to the animation
// system.
final Layout layout = getActiveLayout();
if (layout != null && layout.onUpdate(timeMs, dtMs) && layout.isHiding()
&& areAnimatorsComplete) {
layout.doneHiding();
}
// TODO(1100332): Once overlays are MVC, this should no longer be needed.
for (int i = 0; i < mSceneOverlays.size(); i++) {
mSceneOverlays.get(i).updateOverlay(timeMs, dtMs);
}
mFrameRequestSupplier.set(timeMs);
return mUpdateRequested;
}
......@@ -542,8 +570,27 @@ public class LayoutManager implements LayoutUpdateHost, LayoutProvider,
updateControlsHidingState(browserControlsManager);
getViewportPixel(mCachedVisibleViewport);
mHost.getWindowViewport(mCachedWindowViewport);
return mActiveLayout.getUpdatedSceneLayer(mCachedWindowViewport, mCachedVisibleViewport,
layerTitleCache, tabContentManager, resourceManager, browserControlsManager);
SceneLayer layer = mActiveLayout.getUpdatedSceneLayer(mCachedWindowViewport,
mCachedVisibleViewport, layerTitleCache, tabContentManager, resourceManager,
browserControlsManager);
float offsetPx = mBrowserControlsStateProviderSupplier.get() == null
? 0
: mBrowserControlsStateProviderSupplier.get().getTopControlOffset();
for (int i = 0; i < mSceneOverlays.size(); i++) {
// If the SceneOverlay is not showing, don't bother adding it to the tree.
if (!mSceneOverlays.get(i).isSceneOverlayTreeShowing()) continue;
SceneOverlayLayer overlayLayer = mSceneOverlays.get(i).getUpdatedSceneOverlayTree(
mCachedWindowViewport, mCachedVisibleViewport, layerTitleCache, resourceManager,
offsetPx * mPxToDp);
overlayLayer.setContentTree(layer);
layer = overlayLayer;
}
return layer;
}
private void updateControlsHidingState(
......@@ -551,7 +598,17 @@ public class LayoutManager implements LayoutUpdateHost, LayoutProvider,
if (controlsVisibilityManager == null) {
return;
}
if (mActiveLayout.forceHideBrowserControlsAndroidView()) {
boolean overlayHidesControls = false;
for (int i = 0; i < mSceneOverlays.size(); i++) {
// If any overlay wants to hide tha Android version of the browser controls, hide them.
if (mSceneOverlays.get(i).shouldHideAndroidBrowserControls()) {
overlayHidesControls = true;
break;
}
}
if (overlayHidesControls || mActiveLayout.forceHideBrowserControlsAndroidView()) {
mControlsHidingToken = controlsVisibilityManager.hideAndroidControlsAndClearOldToken(
mControlsHidingToken);
mAndroidViewShownSupplier.set(false);
......@@ -573,11 +630,23 @@ public class LayoutManager implements LayoutUpdateHost, LayoutProvider,
*/
public void onViewportChanged() {
if (getActiveLayout() != null) {
float previousWidth = getActiveLayout().getWidth();
float previousHeight = getActiveLayout().getHeight();
mHost.getWindowViewport(mCachedWindowViewport);
mHost.getVisibleViewport(mCachedVisibleViewport);
getActiveLayout().sizeChanged(mCachedVisibleViewport, mCachedWindowViewport,
mHost.getTopControlsHeightPixels(), mHost.getBottomControlsHeightPixels(),
getOrientation());
float width = mCachedWindowViewport.width() * mPxToDp;
float height = mCachedWindowViewport.height() * mPxToDp;
if (width != previousWidth || height != previousHeight) {
for (int i = 0; i < mSceneOverlays.size(); i++) {
mSceneOverlays.get(i).onSizeChanged(
width, height, mCachedVisibleViewport.top, getOrientation());
}
}
}
for (int i = 0; i < mTabCache.size(); i++) {
......@@ -928,6 +997,12 @@ public class LayoutManager implements LayoutUpdateHost, LayoutProvider,
* @return Whether or not the back button was consumed by the active {@link Layout}.
*/
public boolean onBackPressed() {
for (int i = 0; i < mSceneOverlays.size(); i++) {
if (!mSceneOverlays.get(i).isSceneOverlayTreeShowing()) continue;
// If the back button was consumed by any overlays, return true.
if (mSceneOverlays.get(i).onBackPressed()) return true;
}
return getActiveLayout() != null && getActiveLayout().onBackPressed();
}
......@@ -939,14 +1014,6 @@ public class LayoutManager implements LayoutUpdateHost, LayoutProvider,
mStatusIndicatorSceneOverlay = overlay;
}
/**
* Adds the {@link SceneOverlay} across all {@link Layout}s owned by this class.
* @param helper A {@link SceneOverlay} instance.
*/
protected void addGlobalSceneOverlay(SceneOverlay helper) {
mStaticLayout.addSceneOverlay(helper);
}
/**
* Add any {@link SceneOverlay}s to the layout. This can be used to add the overlays in a
* particular order.
......@@ -955,11 +1022,11 @@ public class LayoutManager implements LayoutUpdateHost, LayoutProvider,
* on top of another positioned.
*/
protected void addAllSceneOverlays() {
addGlobalSceneOverlay(mToolbarOverlay);
mSceneOverlays.add(mToolbarOverlay);
if (mStatusIndicatorSceneOverlay != null) {
addGlobalSceneOverlay(mStatusIndicatorSceneOverlay);
mSceneOverlays.add(mStatusIndicatorSceneOverlay);
}
mStaticLayout.addSceneOverlay(mContextualSearchPanel);
mSceneOverlays.add(mContextualSearchPanel);
}
/**
......@@ -968,7 +1035,8 @@ public class LayoutManager implements LayoutUpdateHost, LayoutProvider,
* @param overlay The overlay to be added to the back of the list.
*/
public void addSceneOverlayToFront(SceneOverlay overlay) {
mStaticLayout.addSceneOverlay(overlay);
assert !mSceneOverlays.contains(overlay);
mSceneOverlays.add(overlay);
}
/**
......@@ -977,7 +1045,8 @@ public class LayoutManager implements LayoutUpdateHost, LayoutProvider,
* @param overlay The overlay to be added to the back of the list.
*/
public void addSceneOverlayToBack(SceneOverlay overlay) {
mStaticLayout.addSceneOverlayToBack(overlay);
assert !mSceneOverlays.contains(overlay);
mSceneOverlays.add(0, overlay);
}
/**
......
......@@ -25,7 +25,6 @@ import org.chromium.chrome.browser.compositor.layouts.eventfilter.EdgeSwipeHandl
import org.chromium.chrome.browser.compositor.layouts.eventfilter.EmptyEdgeSwipeHandler;
import org.chromium.chrome.browser.compositor.layouts.eventfilter.ScrollDirection;
import org.chromium.chrome.browser.compositor.layouts.phone.StackLayout;
import org.chromium.chrome.browser.compositor.overlays.SceneOverlay;
import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutHelperManager;
import org.chromium.chrome.browser.contextualsearch.ContextualSearchManagementDelegate;
import org.chromium.chrome.browser.device.DeviceClassManager;
......@@ -142,8 +141,10 @@ public class LayoutManagerChrome
*/
@Override
public void getVirtualViews(List<VirtualView> views) {
if (getActiveLayout() != null) {
getActiveLayout().getVirtualViews(views);
// TODO(dtrainor): Investigate order.
for (int i = 0; i < mSceneOverlays.size(); i++) {
if (!mSceneOverlays.get(i).isSceneOverlayTreeShowing()) continue;
mSceneOverlays.get(i).getVirtualViews(views);
}
}
......@@ -227,14 +228,6 @@ public class LayoutManagerChrome
}
}
@Override
protected void addGlobalSceneOverlay(SceneOverlay helper) {
super.addGlobalSceneOverlay(helper);
mOverviewListLayout.addSceneOverlay(helper);
mToolbarSwipeLayout.addSceneOverlay(helper);
if (mOverviewLayout != null) mOverviewLayout.addSceneOverlay(helper);
}
/**
* Simulates a click on the view at the specified pixel offset
* from the top left of the view.
......
......@@ -91,12 +91,6 @@ public class LayoutManagerChromePhone extends LayoutManagerChrome {
};
}
@Override
protected void addGlobalSceneOverlay(SceneOverlay helper) {
super.addGlobalSceneOverlay(helper);
mSimpleAnimationLayout.addSceneOverlay(helper);
}
@Override
protected void emptyCachesExcept(int tabId) {
super.emptyCachesExcept(tabId);
......@@ -138,7 +132,8 @@ public class LayoutManagerChromePhone extends LayoutManagerChrome {
@Override
protected void tabCreating(int sourceId, String url, boolean isIncognito) {
if (!getActiveLayout().isHiding() && getActiveLayout().handlesTabCreating()) {
if (!getActiveLayout().isHiding() && overlaysHandleTabCreating()
&& getActiveLayout().handlesTabCreating()) {
// If the current layout in the foreground, let it handle the tab creation animation.
// This check allows us to switch from the StackLayout to the SimpleAnimationLayout
// smoothly.
......@@ -157,6 +152,25 @@ public class LayoutManagerChromePhone extends LayoutManagerChrome {
}
}
/** @return Whether the {@link SceneOverlay}s handle tab creation. */
private boolean overlaysHandleTabCreating() {
Layout layout = getActiveLayout();
if (layout == null || layout.getLayoutTabsToRender() == null
|| layout.getLayoutTabsToRender().length != 1) {
return false;
}
for (int i = 0; i < mSceneOverlays.size(); i++) {
if (!mSceneOverlays.get(i).isSceneOverlayTreeShowing()) continue;
if (mSceneOverlays.get(i).handlesTabCreating()) {
// Prevent animation from happening if the overlay handles creation.
startHiding(layout.getLayoutTabsToRender()[0].getId(), false);
doneHiding();
return true;
}
}
return false;
}
@Override
protected void tabCreated(int id, int sourceId, @TabLaunchType int launchType,
boolean isIncognito, boolean willBeSelected, float originX, float originY) {
......
......@@ -49,7 +49,7 @@ public class LayoutManagerChromeTablet extends LayoutManagerChrome {
@Override
protected void addAllSceneOverlays() {
// Add the tab strip overlay before any others.
addGlobalSceneOverlay(mTabStripLayoutHelperManager);
mSceneOverlays.add(mTabStripLayoutHelperManager);
super.addAllSceneOverlays();
}
......
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