blob: 81eabffb7d7c6318a10ebe38188e7f93fe7cb723 [file] [log] [blame]
// Copyright 2015 The Chromium Authors
// 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.compositor.scene_layer;
import android.content.Context;
import androidx.annotation.ColorInt;
import androidx.annotation.VisibleForTesting;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.chrome.browser.compositor.LayerTitleCache;
import org.chromium.chrome.browser.compositor.layouts.components.CompositorButton;
import org.chromium.chrome.browser.compositor.layouts.components.TintedCompositorButton;
import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutHelperManager;
import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutTab;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.layouts.scene_layer.SceneLayer;
import org.chromium.chrome.browser.layouts.scene_layer.SceneOverlayLayer;
import org.chromium.ui.base.LocalizationUtils;
import org.chromium.ui.resources.ResourceManager;
/**
* The Java component of what is basically a CC Layer that manages drawing the Tab Strip (which is
* composed of {@link StripLayoutTab}s) to the screen. This object keeps the layers up to date and
* removes/creates children as necessary. This object is built by its native counterpart.
*/
@JNINamespace("android")
public class TabStripSceneLayer extends SceneOverlayLayer {
private static boolean sTestFlag;
private long mNativePtr;
private final float mDpToPx;
public TabStripSceneLayer(Context context) {
mDpToPx = context.getResources().getDisplayMetrics().density;
}
public static void setTestFlag(boolean testFlag) {
sTestFlag = testFlag;
}
@Override
protected void initializeNative() {
if (mNativePtr == 0) {
mNativePtr = TabStripSceneLayerJni.get().init(
TabStripSceneLayer.this, ChromeFeatureList.sTabStripRedesign.isEnabled());
}
// Set flag for testing
if (!sTestFlag) {
assert mNativePtr != 0;
}
}
@Override
public void setContentTree(SceneLayer contentTree) {
TabStripSceneLayerJni.get().setContentTree(
mNativePtr, TabStripSceneLayer.this, contentTree);
}
/**
* Pushes all relevant {@link StripLayoutTab}s to the CC Layer tree.
* This also pushes any other assets required to draw the Tab Strip. This should only be called
* when the Compositor has disabled ScheduleComposite calls as this will change the tree and
* could subsequently cause unnecessary follow up renders.
*
* @param layoutHelper A layout helper for the tab strip.
* @param layerTitleCache A layer title cache.
* @param resourceManager A resource manager.
* @param stripLayoutTabsToRender Array of strip layout tabs.
* @param yOffset Current browser controls offset in dp.
*/
public void pushAndUpdateStrip(StripLayoutHelperManager layoutHelper,
LayerTitleCache layerTitleCache, ResourceManager resourceManager,
StripLayoutTab[] stripLayoutTabsToRender, float yOffset, int selectedTabId) {
if (mNativePtr == 0) return;
final boolean visible = yOffset > -layoutHelper.getHeight();
// This will hide the tab strips if necessary.
TabStripSceneLayerJni.get().beginBuildingFrame(
mNativePtr, TabStripSceneLayer.this, visible);
// When strip tabs are completely off screen, we don't need to update it.
if (visible) {
pushButtonsAndBackground(layoutHelper, resourceManager, yOffset);
pushStripTabs(layoutHelper, layerTitleCache, resourceManager, stripLayoutTabsToRender,
selectedTabId);
}
TabStripSceneLayerJni.get().finishBuildingFrame(mNativePtr, TabStripSceneLayer.this);
}
private void pushButtonsAndBackground(StripLayoutHelperManager layoutHelper,
ResourceManager resourceManager, float yOffset) {
final int width = Math.round(layoutHelper.getWidth() * mDpToPx);
final int height = Math.round(layoutHelper.getHeight() * mDpToPx);
TabStripSceneLayerJni.get().updateTabStripLayer(mNativePtr, TabStripSceneLayer.this, width,
height, yOffset * mDpToPx, layoutHelper.getBackgroundColor());
TintedCompositorButton newTabButton = layoutHelper.getNewTabButton();
CompositorButton modelSelectorButton = layoutHelper.getModelSelectorButton();
boolean modelSelectorButtonVisible = modelSelectorButton.isVisible();
boolean newTabButtonVisible = newTabButton.isVisible();
TabStripSceneLayerJni.get().updateNewTabButton(mNativePtr, TabStripSceneLayer.this,
newTabButton.getResourceId(), newTabButton.getBackgroundResourceId(),
newTabButton.getX() * mDpToPx, newTabButton.getY() * mDpToPx,
layoutHelper.getNewTabBtnTouchTargetOffset() * mDpToPx, newTabButtonVisible,
newTabButton.getTint(), newTabButton.getBackgroundTint(), newTabButton.getOpacity(),
resourceManager);
if (!ChromeFeatureList.sTabStripRedesign.isEnabled()) {
TabStripSceneLayerJni.get().updateModelSelectorButton(mNativePtr,
TabStripSceneLayer.this, modelSelectorButton.getResourceId(),
modelSelectorButton.getX() * mDpToPx, modelSelectorButton.getY() * mDpToPx,
modelSelectorButton.getWidth() * mDpToPx,
modelSelectorButton.getHeight() * mDpToPx, modelSelectorButton.isIncognito(),
modelSelectorButtonVisible, modelSelectorButton.getOpacity(), resourceManager);
} else {
TabStripSceneLayerJni.get().updateModelSelectorButtonBackground(mNativePtr,
TabStripSceneLayer.this, modelSelectorButton.getResourceId(),
((TintedCompositorButton) modelSelectorButton).getBackgroundResourceId(),
modelSelectorButton.getX() * mDpToPx, modelSelectorButton.getY() * mDpToPx,
modelSelectorButton.getWidth() * mDpToPx,
modelSelectorButton.getHeight() * mDpToPx, modelSelectorButton.isIncognito(),
modelSelectorButtonVisible,
((TintedCompositorButton) modelSelectorButton).getTint(),
((TintedCompositorButton) modelSelectorButton).getBackgroundTint(),
modelSelectorButton.getOpacity(), resourceManager);
}
boolean tabStripRedesignEnabled = ChromeFeatureList.sTabStripRedesign.isEnabled();
boolean isLayoutRtl = LocalizationUtils.isLayoutRtl();
boolean showLeftTabStripFade = tabStripRedesignEnabled || isLayoutRtl;
boolean showRightTabStripFade = tabStripRedesignEnabled || !isLayoutRtl;
if (showLeftTabStripFade) {
int leftFadeDrawable = layoutHelper.getLeftFadeDrawable();
TabStripSceneLayerJni.get().updateTabStripLeftFade(mNativePtr, TabStripSceneLayer.this,
leftFadeDrawable, layoutHelper.getLeftFadeOpacity(), resourceManager,
layoutHelper.getBackgroundColor());
}
if (showRightTabStripFade) {
int rightFadeDrawable = layoutHelper.getRightFadeDrawable();
TabStripSceneLayerJni.get().updateTabStripRightFade(mNativePtr, TabStripSceneLayer.this,
rightFadeDrawable, layoutHelper.getRightFadeOpacity(), resourceManager,
layoutHelper.getBackgroundColor());
}
}
private void pushStripTabs(StripLayoutHelperManager layoutHelper,
LayerTitleCache layerTitleCache, ResourceManager resourceManager,
StripLayoutTab[] stripTabs, int selectedTabId) {
final int tabsCount = stripTabs != null ? stripTabs.length : 0;
for (int i = 0; i < tabsCount; i++) {
final StripLayoutTab st = stripTabs[i];
boolean isSelected = st.getId() == selectedTabId;
TabStripSceneLayerJni.get().putStripTabLayer(mNativePtr, TabStripSceneLayer.this,
st.getId(), st.getCloseButton().getResourceId(), st.getDividerResourceId(),
st.getResourceId(), st.getOutlineResourceId(), st.getCloseButton().getTint(),
st.getDividerTint(), st.getTint(isSelected), st.getOutlineTint(isSelected),
isSelected, st.getClosePressed(), layoutHelper.getWidth() * mDpToPx,
st.getDrawX() * mDpToPx, st.getDrawY() * mDpToPx, st.getWidth() * mDpToPx,
st.getHeight() * mDpToPx, st.getContentOffsetX() * mDpToPx,
st.getContentOffsetY() * mDpToPx, st.getDividerOffsetX() * mDpToPx,
st.getBottomMargin() * mDpToPx, st.getCloseButtonPadding() * mDpToPx,
st.getCloseButton().getOpacity(), st.isStartDividerVisible(),
st.isEndDividerVisible(), st.isLoading(), st.getLoadingSpinnerRotation(),
st.getBrightness(), st.getContainerOpacity(), layerTitleCache, resourceManager);
}
}
@Override
public void destroy() {
super.destroy();
mNativePtr = 0;
}
@NativeMethods
public interface Natives {
long init(TabStripSceneLayer caller, boolean isTabStripRedesignEnabled);
void beginBuildingFrame(
long nativeTabStripSceneLayer, TabStripSceneLayer caller, boolean visible);
void finishBuildingFrame(long nativeTabStripSceneLayer, TabStripSceneLayer caller);
void updateTabStripLayer(long nativeTabStripSceneLayer, TabStripSceneLayer caller,
int width, int height, float yOffset, @ColorInt int backgroundColor);
void updateNewTabButton(long nativeTabStripSceneLayer, TabStripSceneLayer caller,
int resourceId, int backgroundResourceId, float x, float y, float touchTargetOffset,
boolean visible, int tint, int backgroundTint, float buttonAlpha,
ResourceManager resourceManager);
void updateModelSelectorButton(long nativeTabStripSceneLayer, TabStripSceneLayer caller,
int resourceId, float x, float y, float width, float height, boolean incognito,
boolean visible, float buttonAlpha, ResourceManager resourceManager);
void updateModelSelectorButtonBackground(long nativeTabStripSceneLayer,
TabStripSceneLayer caller, int resourceId, int backgroundResourceId, float x,
float y, float width, float height, boolean incognito, boolean visible, int tint,
int backgroundTint, float buttonAlpha, ResourceManager resourceManager);
void updateTabStripLeftFade(long nativeTabStripSceneLayer, TabStripSceneLayer caller,
int resourceId, float opacity, ResourceManager resourceManager,
@ColorInt int leftFadeColor);
void updateTabStripRightFade(long nativeTabStripSceneLayer, TabStripSceneLayer caller,
int resourceId, float opacity, ResourceManager resourceManager,
@ColorInt int rightFadeColor);
void putStripTabLayer(long nativeTabStripSceneLayer, TabStripSceneLayer caller, int id,
int closeResourceId, int dividerResourceId, int handleResourceId,
int handleOutlineResourceId, int closeTint, int dividerTint, int handleTint,
int handleOutlineTint, boolean foreground, boolean closePressed, float toolbarWidth,
float x, float y, float width, float height, float contentOffsetX,
float contentOffsetY, float dividerOffsetX, float bottomOffsetY,
float closeButtonPadding, float closeButtonAlpha, boolean isStartDividerVisible,
boolean isEndDividerVisible, boolean isLoading, float spinnerRotation,
float brightness, float opacity, LayerTitleCache layerTitleCache,
ResourceManager resourceManager);
void setContentTree(
long nativeTabStripSceneLayer, TabStripSceneLayer caller, SceneLayer contentTree);
}
@VisibleForTesting
public void initializeNativeForTesting() {
this.initializeNative();
}
}