| Index: chrome/android/java_staging/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
|
| diff --git a/chrome/android/java_staging/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java_staging/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
|
| deleted file mode 100644
|
| index ef454af67f3c07c6ca6e4338cc7fda6e9600f334..0000000000000000000000000000000000000000
|
| --- a/chrome/android/java_staging/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
|
| +++ /dev/null
|
| @@ -1,1113 +0,0 @@
|
| -// Copyright 2015 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.compositor;
|
| -
|
| -import android.content.Context;
|
| -import android.graphics.Canvas;
|
| -import android.graphics.Paint;
|
| -import android.graphics.Rect;
|
| -import android.graphics.RectF;
|
| -import android.os.Bundle;
|
| -import android.os.Handler;
|
| -import android.support.v4.view.ViewCompat;
|
| -import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
|
| -import android.support.v4.widget.ExploreByTouchHelper;
|
| -import android.util.AttributeSet;
|
| -import android.util.Pair;
|
| -import android.view.MotionEvent;
|
| -import android.view.SurfaceHolder;
|
| -import android.view.SurfaceView;
|
| -import android.view.View;
|
| -import android.view.ViewGroup;
|
| -import android.view.accessibility.AccessibilityEvent;
|
| -import android.view.inputmethod.InputMethodManager;
|
| -import android.widget.FrameLayout;
|
| -
|
| -import org.chromium.base.SysUtils;
|
| -import org.chromium.base.TraceEvent;
|
| -import org.chromium.base.annotations.SuppressFBWarnings;
|
| -import org.chromium.chrome.R;
|
| -import org.chromium.chrome.browser.EmptyTabObserver;
|
| -import org.chromium.chrome.browser.Tab;
|
| -import org.chromium.chrome.browser.TabObserver;
|
| -import org.chromium.chrome.browser.compositor.Invalidator.Client;
|
| -import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
|
| -import org.chromium.chrome.browser.compositor.layouts.LayoutManagerHost;
|
| -import org.chromium.chrome.browser.compositor.layouts.LayoutRenderHost;
|
| -import org.chromium.chrome.browser.compositor.layouts.components.VirtualView;
|
| -import org.chromium.chrome.browser.compositor.layouts.content.ContentOffsetProvider;
|
| -import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
|
| -import org.chromium.chrome.browser.contextualsearch.ContextualSearchManagementDelegate;
|
| -import org.chromium.chrome.browser.device.DeviceClassManager;
|
| -import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
|
| -import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager.FullscreenListener;
|
| -import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
|
| -import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
|
| -import org.chromium.chrome.browser.tabmodel.TabModelSelector;
|
| -import org.chromium.chrome.browser.widget.ControlContainer;
|
| -import org.chromium.content.browser.ContentReadbackHandler;
|
| -import org.chromium.content.browser.ContentViewCore;
|
| -import org.chromium.content.browser.SPenSupport;
|
| -import org.chromium.ui.UiUtils;
|
| -import org.chromium.ui.base.DeviceFormFactor;
|
| -import org.chromium.ui.base.WindowAndroid;
|
| -import org.chromium.ui.resources.ResourceManager;
|
| -import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
|
| -import org.chromium.ui.resources.dynamics.ViewResourceAdapter;
|
| -
|
| -import java.util.ArrayList;
|
| -import java.util.List;
|
| -
|
| -/**
|
| - * This class holds a {@link CompositorView}. This level of indirection is needed to benefit from
|
| - * the {@link android.view.ViewGroup#onInterceptTouchEvent(android.view.MotionEvent)} capability on
|
| - * available on {@link android.view.ViewGroup}s.
|
| - * This class also holds the {@link LayoutManager} responsible to describe the items to be
|
| - * drawn by the UI compositor on the native side.
|
| - */
|
| -public class CompositorViewHolder extends FrameLayout
|
| - implements LayoutManagerHost, LayoutRenderHost, Invalidator.Host, FullscreenListener {
|
| - private static List<View> sCachedViewList = new ArrayList<View>();
|
| - private static List<ContentViewCore> sCachedCVCList = new ArrayList<ContentViewCore>();
|
| -
|
| - private boolean mIsKeyboardShowing = false;
|
| -
|
| - private final Invalidator mInvalidator = new Invalidator();
|
| - private LayoutManager mLayoutManager;
|
| - private LayerTitleCache mLayerTitleCache;
|
| - private CompositorView mCompositorView;
|
| -
|
| - private boolean mContentOverlayVisiblity = true;
|
| -
|
| - private int mPendingSwapBuffersCount;
|
| -
|
| - private final ArrayList<Invalidator.Client> mPendingInvalidations =
|
| - new ArrayList<Invalidator.Client>();
|
| - private boolean mSkipInvalidation = false;
|
| -
|
| - private boolean mSkipNextToolbarTextureUpdate = false;
|
| -
|
| - /**
|
| - * A task to be performed after a resize event.
|
| - */
|
| - private Runnable mPostHideKeyboardTask;
|
| -
|
| - private TabModelSelector mTabModelSelector;
|
| - private ChromeFullscreenManager mFullscreenManager;
|
| - private View mAccessibilityView;
|
| - private CompositorAccessibilityProvider mNodeProvider;
|
| - private boolean mFullscreenTouchEvent = false;
|
| - private float mLastContentOffset = 0;
|
| - private float mLastVisibleContentOffset = 0;
|
| -
|
| - /** The toolbar control container. **/
|
| - private ControlContainer mControlContainer;
|
| -
|
| - /** The currently visible Tab. */
|
| - private Tab mTabVisible;
|
| -
|
| - /** The currently attached View. */
|
| - private View mView;
|
| -
|
| - private TabObserver mTabObserver;
|
| - private boolean mEnableCompositorTabStrip;
|
| -
|
| - // Cache objects that should not be created frequently.
|
| - private final Rect mCacheViewport = new Rect();
|
| - private final Rect mCacheVisibleViewport = new Rect();
|
| -
|
| - // If we've drawn at least one frame.
|
| - private boolean mHasDrawnOnce = false;
|
| -
|
| - /**
|
| - * This view is created on demand to display debugging information.
|
| - */
|
| - private static class DebugOverlay extends View {
|
| - private final List<Pair<Rect, Integer>> mRectangles = new ArrayList<Pair<Rect, Integer>>();
|
| - private final Paint mPaint = new Paint();
|
| - private boolean mFirstPush = true;
|
| -
|
| - /**
|
| - * @param context The current Android's context.
|
| - */
|
| - public DebugOverlay(Context context) {
|
| - super(context);
|
| - }
|
| -
|
| - /**
|
| - * Pushes a rectangle to be drawn on the screen on top of everything.
|
| - *
|
| - * @param rect The rectangle to be drawn on screen
|
| - * @param color The color of the rectangle
|
| - */
|
| - public void pushRect(Rect rect, int color) {
|
| - if (mFirstPush) {
|
| - mRectangles.clear();
|
| - mFirstPush = false;
|
| - }
|
| - mRectangles.add(new Pair<Rect, Integer>(rect, color));
|
| - invalidate();
|
| - }
|
| -
|
| - @SuppressFBWarnings("NP_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD")
|
| - @Override
|
| - protected void onDraw(Canvas canvas) {
|
| - for (int i = 0; i < mRectangles.size(); i++) {
|
| - mPaint.setColor(mRectangles.get(i).second);
|
| - canvas.drawRect(mRectangles.get(i).first, mPaint);
|
| - }
|
| - mFirstPush = true;
|
| - }
|
| - }
|
| -
|
| - private DebugOverlay mDebugOverlay;
|
| -
|
| - private View mUrlBar;
|
| -
|
| - /**
|
| - * Creates a {@link CompositorView}.
|
| - * @param c The Context to create this {@link CompositorView} in.
|
| - */
|
| - public CompositorViewHolder(Context c) {
|
| - super(c);
|
| -
|
| - internalInit();
|
| - }
|
| -
|
| - /**
|
| - * Creates a {@link CompositorView}.
|
| - * @param c The Context to create this {@link CompositorView} in.
|
| - * @param attrs The AttributeSet used to create this {@link CompositorView}.
|
| - */
|
| - public CompositorViewHolder(Context c, AttributeSet attrs) {
|
| - super(c, attrs);
|
| -
|
| - internalInit();
|
| - }
|
| -
|
| - private void internalInit() {
|
| - mTabObserver = new EmptyTabObserver() {
|
| - @Override
|
| - public void onContentChanged(Tab tab) {
|
| - CompositorViewHolder.this.onContentChanged();
|
| - }
|
| -
|
| - @Override
|
| - public void onOverlayContentViewCoreAdded(Tab tab, ContentViewCore content) {
|
| - initializeContentViewCore(content);
|
| - setSizeOfUnattachedView(content.getContainerView());
|
| - }
|
| - };
|
| -
|
| - mEnableCompositorTabStrip = DeviceFormFactor.isTablet(getContext());
|
| -
|
| - addOnLayoutChangeListener(new OnLayoutChangeListener() {
|
| - @Override
|
| - public void onLayoutChange(View v, int left, int top, int right, int bottom,
|
| - int oldLeft, int oldTop, int oldRight, int oldBottom) {
|
| - propagateViewportToLayouts(right - left, bottom - top);
|
| -
|
| - // If there's an event that needs to occur after the keyboard is hidden, post
|
| - // it as a delayed event. Otherwise this happens in the midst of the
|
| - // ContentView's relayout, which causes the ContentView to relayout on top of the
|
| - // stack view. The 30ms is arbitrary, hoping to let the view get one repaint
|
| - // in so the full page is shown.
|
| - if (mPostHideKeyboardTask != null) {
|
| - new Handler().postDelayed(mPostHideKeyboardTask, 30);
|
| - mPostHideKeyboardTask = null;
|
| - }
|
| - }
|
| - });
|
| -
|
| - mCompositorView = new CompositorView(getContext(), this);
|
| - addView(mCompositorView,
|
| - new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
|
| - }
|
| -
|
| - /**
|
| - * @param layoutManager The {@link LayoutManager} instance that will be driving what
|
| - * shows in this {@link CompositorViewHolder}.
|
| - */
|
| - public void setLayoutManager(LayoutManager layoutManager) {
|
| - mLayoutManager = layoutManager;
|
| - propagateViewportToLayouts(getWidth(), getHeight());
|
| - }
|
| -
|
| - /**
|
| - * @param view The root view of the hierarchy.
|
| - */
|
| - public void setRootView(View view) {
|
| - mCompositorView.setRootView(view);
|
| - }
|
| -
|
| - /**
|
| - * @param controlContainer The ControlContainer.
|
| - */
|
| - public void setControlContainer(ControlContainer controlContainer) {
|
| - DynamicResourceLoader loader = mCompositorView.getResourceManager() != null
|
| - ? mCompositorView.getResourceManager().getDynamicResourceLoader()
|
| - : null;
|
| - if (loader != null && mControlContainer != null) {
|
| - loader.unregisterResource(R.id.control_container);
|
| - loader.unregisterResource(R.id.progress);
|
| - }
|
| - mControlContainer = controlContainer;
|
| - if (loader != null && mControlContainer != null) {
|
| - loader.registerResource(
|
| - R.id.control_container, mControlContainer.getToolbarResourceAdapter());
|
| -
|
| - ViewResourceAdapter progressAdapter = mControlContainer.getProgressResourceAdapter();
|
| - if (progressAdapter != null) {
|
| - loader.registerResource(R.id.progress, progressAdapter);
|
| - }
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * @return The CompositorView.
|
| - */
|
| - public SurfaceHolder.Callback2 getSurfaceHolderCallback2() {
|
| - return mCompositorView;
|
| - }
|
| -
|
| - /**
|
| - * Reset command line flags. This gets called after the native library finishes
|
| - * loading.
|
| - */
|
| - public void resetFlags() {
|
| - mCompositorView.resetFlags();
|
| - }
|
| -
|
| - /**
|
| - * Should be called for cleanup when the CompositorView instance is no longer used.
|
| - */
|
| - public void shutDown() {
|
| - setTab(null);
|
| - if (mLayerTitleCache != null) mLayerTitleCache.shutDown();
|
| - mCompositorView.shutDown();
|
| - }
|
| -
|
| - /**
|
| - * This is called when the native library are ready.
|
| - */
|
| - public void onNativeLibraryReady(
|
| - WindowAndroid windowAndroid, TabContentManager tabContentManager) {
|
| - assert mLayerTitleCache == null : "Should be called once";
|
| -
|
| - if (DeviceClassManager.enableLayerDecorationCache()) {
|
| - mLayerTitleCache = new LayerTitleCache(getContext());
|
| - }
|
| -
|
| - mCompositorView.initNativeCompositor(
|
| - SysUtils.isLowEndDevice(), windowAndroid, mLayerTitleCache, tabContentManager);
|
| -
|
| - if (mLayerTitleCache != null) {
|
| - mLayerTitleCache.setResourceManager(getResourceManager());
|
| - }
|
| -
|
| - if (mControlContainer != null) {
|
| - mCompositorView.getResourceManager().getDynamicResourceLoader().registerResource(
|
| - R.id.control_container, mControlContainer.getToolbarResourceAdapter());
|
| -
|
| - ViewResourceAdapter progressAdapter = mControlContainer.getProgressResourceAdapter();
|
| - if (progressAdapter != null) {
|
| - mCompositorView.getResourceManager().getDynamicResourceLoader().registerResource(
|
| - R.id.progress, progressAdapter);
|
| - }
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public ResourceManager getResourceManager() {
|
| - return mCompositorView.getResourceManager();
|
| - }
|
| -
|
| - public ContentOffsetProvider getContentOffsetProvider() {
|
| - return mCompositorView;
|
| - }
|
| -
|
| - /**
|
| - * @return The content readback handler.
|
| - */
|
| - public ContentReadbackHandler getContentReadbackHandler() {
|
| - if (mCompositorView == null) return null;
|
| - return mCompositorView.getContentReadbackHandler();
|
| - }
|
| -
|
| - /**
|
| - * @return The {@link DynamicResourceLoader} for registering resources.
|
| - */
|
| - public DynamicResourceLoader getDynamicResourceLoader() {
|
| - return mCompositorView.getResourceManager().getDynamicResourceLoader();
|
| - }
|
| -
|
| - /**
|
| - * @return The {@link Invalidator} instance that is driven by this {@link CompositorViewHolder}.
|
| - */
|
| - public Invalidator getInvalidator() {
|
| - return mInvalidator;
|
| - }
|
| -
|
| - @Override
|
| - public boolean onInterceptTouchEvent(MotionEvent e) {
|
| - super.onInterceptTouchEvent(e);
|
| -
|
| - if (mLayoutManager == null) return false;
|
| -
|
| - mFullscreenTouchEvent = false;
|
| - if (mFullscreenManager != null && mFullscreenManager.onInterceptMotionEvent(e)
|
| - && !mEnableCompositorTabStrip) {
|
| - // Don't eat the event if the new tab strip is enabled.
|
| - mFullscreenTouchEvent = true;
|
| - return true;
|
| - }
|
| -
|
| - setContentViewMotionEventOffsets(e, false);
|
| - return mLayoutManager.onInterceptTouchEvent(e, mIsKeyboardShowing);
|
| - }
|
| -
|
| - @Override
|
| - public boolean onTouchEvent(MotionEvent e) {
|
| - if (mFullscreenManager != null) mFullscreenManager.onMotionEvent(e);
|
| - if (mFullscreenTouchEvent) return true;
|
| - boolean consumed = mLayoutManager != null && mLayoutManager.onTouchEvent(e);
|
| - setContentViewMotionEventOffsets(e, true);
|
| - return consumed;
|
| - }
|
| -
|
| - @Override
|
| - public boolean onInterceptHoverEvent(MotionEvent e) {
|
| - setContentViewMotionEventOffsets(e, true);
|
| - return super.onInterceptHoverEvent(e);
|
| - }
|
| -
|
| - @Override
|
| - public boolean dispatchHoverEvent(MotionEvent e) {
|
| - if (mNodeProvider != null) {
|
| - if (mNodeProvider.dispatchHoverEvent(e)) {
|
| - return true;
|
| - }
|
| - }
|
| - return super.dispatchHoverEvent(e);
|
| - }
|
| -
|
| - /**
|
| - * @return The {@link LayoutManager} associated with this view.
|
| - */
|
| - public LayoutManager getLayoutManager() {
|
| - return mLayoutManager;
|
| - }
|
| -
|
| - /**
|
| - * @return The SurfaceView used by the Compositor.
|
| - */
|
| - public SurfaceView getSurfaceView() {
|
| - return mCompositorView;
|
| - }
|
| -
|
| - @Override
|
| - protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
| - super.onSizeChanged(w, h, oldw, oldh);
|
| - if (mLayoutManager == null) return;
|
| -
|
| - sCachedViewList.clear();
|
| - mLayoutManager.getActiveLayout().getAllViews(sCachedViewList);
|
| -
|
| - boolean resized = false;
|
| - for (int i = 0; i < sCachedViewList.size(); i++) {
|
| - resized |= setSizeOfUnattachedView(sCachedViewList.get(i));
|
| - }
|
| - sCachedViewList.clear();
|
| -
|
| - if (resized) requestRender();
|
| - }
|
| -
|
| - @Override
|
| - public void onPhysicalBackingSizeChanged(int width, int height) {
|
| - if (mLayoutManager == null) return;
|
| -
|
| - sCachedCVCList.clear();
|
| - mLayoutManager.getActiveLayout().getAllContentViewCores(sCachedCVCList);
|
| -
|
| - for (int i = 0; i < sCachedCVCList.size(); i++) {
|
| - sCachedCVCList.get(i).onPhysicalBackingSizeChanged(width, height);
|
| - }
|
| - sCachedCVCList.clear();
|
| - }
|
| -
|
| - @Override
|
| - public void onOverdrawBottomHeightChanged(int overdrawHeight) {
|
| - if (mLayoutManager == null) return;
|
| -
|
| - sCachedCVCList.clear();
|
| - mLayoutManager.getActiveLayout().getAllContentViewCores(sCachedCVCList);
|
| -
|
| - for (int i = 0; i < sCachedCVCList.size(); i++) {
|
| - sCachedCVCList.get(i).onOverdrawBottomHeightChanged(overdrawHeight);
|
| - }
|
| - sCachedCVCList.clear();
|
| -
|
| - mSkipNextToolbarTextureUpdate = true;
|
| - requestRender();
|
| - }
|
| -
|
| - @Override
|
| - public int getCurrentOverdrawBottomHeight() {
|
| - if (mTabVisible != null) {
|
| - float overdrawBottomHeight = mTabVisible.getFullscreenOverdrawBottomHeightPix();
|
| - if (!Float.isNaN(overdrawBottomHeight)) {
|
| - return (int) overdrawBottomHeight;
|
| - }
|
| - }
|
| - return mCompositorView.getOverdrawBottomHeight();
|
| - }
|
| -
|
| - /**
|
| - * Called whenever the host activity is started.
|
| - */
|
| - public void onStart() {
|
| - if (mFullscreenManager != null) {
|
| - mLastContentOffset = mFullscreenManager.getContentOffset();
|
| - mLastVisibleContentOffset = mFullscreenManager.getVisibleContentOffset();
|
| - mFullscreenManager.addListener(this);
|
| - }
|
| - requestRender();
|
| - }
|
| -
|
| - /**
|
| - * Called whenever the host activity is stopped.
|
| - */
|
| - public void onStop() {
|
| - if (mFullscreenManager != null) mFullscreenManager.removeListener(this);
|
| - }
|
| -
|
| - @Override
|
| - public void onContentOffsetChanged(float offset) {
|
| - mLastContentOffset = offset;
|
| - propagateViewportToLayouts(getWidth(), getHeight());
|
| - }
|
| -
|
| - @Override
|
| - public void onVisibleContentOffsetChanged(float offset) {
|
| - mLastVisibleContentOffset = offset;
|
| - propagateViewportToLayouts(getWidth(), getHeight());
|
| - requestRender();
|
| - }
|
| -
|
| - @Override
|
| - public void onToggleOverlayVideoMode(boolean enabled) {
|
| - if (mCompositorView != null) {
|
| - mCompositorView.setOverlayVideoMode(enabled);
|
| - }
|
| - }
|
| -
|
| - private void setContentViewMotionEventOffsets(MotionEvent e, boolean canClear) {
|
| - // TODO(dtrainor): Factor this out to LayoutDriver.
|
| - if (e == null || mTabVisible == null) return;
|
| -
|
| - ContentViewCore contentViewCore = mTabVisible.getContentViewCore();
|
| - if (contentViewCore == null) return;
|
| -
|
| - int actionMasked = e.getActionMasked();
|
| -
|
| - if (SPenSupport.isSPenSupported(getContext())) {
|
| - actionMasked = SPenSupport.convertSPenEventAction(actionMasked);
|
| - }
|
| -
|
| - if (actionMasked == MotionEvent.ACTION_DOWN
|
| - || actionMasked == MotionEvent.ACTION_HOVER_ENTER) {
|
| - if (mLayoutManager != null) mLayoutManager.getViewportPixel(mCacheViewport);
|
| - contentViewCore.setCurrentMotionEventOffsets(-mCacheViewport.left, -mCacheViewport.top);
|
| - } else if (canClear && (actionMasked == MotionEvent.ACTION_UP
|
| - || actionMasked == MotionEvent.ACTION_CANCEL
|
| - || actionMasked == MotionEvent.ACTION_HOVER_EXIT)) {
|
| - contentViewCore.setCurrentMotionEventOffsets(0.f, 0.f);
|
| - }
|
| - }
|
| -
|
| - private void propagateViewportToLayouts(int contentWidth, int contentHeight) {
|
| - int heightMinusTopControls = contentHeight - getTopControlsHeightPixels();
|
| - mCacheViewport.set(0, (int) mLastContentOffset, contentWidth, contentHeight);
|
| - mCacheVisibleViewport.set(0, (int) mLastVisibleContentOffset, contentWidth, contentHeight);
|
| - // TODO(changwan): check if this can be merged with setContentMotionEventOffsets.
|
| - if (mTabVisible != null && mTabVisible.getContentViewCore() != null) {
|
| - mTabVisible.getContentViewCore().setSmartClipOffsets(
|
| - -mCacheViewport.left, -mCacheViewport.top);
|
| - }
|
| - if (mLayoutManager != null) {
|
| - mLayoutManager.pushNewViewport(
|
| - mCacheViewport, mCacheVisibleViewport, heightMinusTopControls);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * To be called once a frame before commit.
|
| - */
|
| - @Override
|
| - public void onCompositorLayout() {
|
| - TraceEvent.begin("CompositorViewHolder:layout");
|
| - if (mLayoutManager != null) {
|
| - mLayoutManager.onUpdate();
|
| - mCompositorView.finalizeLayers(mLayoutManager, mSkipNextToolbarTextureUpdate);
|
| - // TODO(changwan): Check if this hack can be removed.
|
| - // This is a hack to draw one more frame if the screen just rotated for Nexus 10 + L.
|
| - // See http://crbug/440469 for more.
|
| - if (mSkipNextToolbarTextureUpdate) {
|
| - requestRender();
|
| - }
|
| - }
|
| -
|
| - TraceEvent.end("CompositorViewHolder:layout");
|
| - mSkipNextToolbarTextureUpdate = false;
|
| - }
|
| -
|
| - @Override
|
| - public void requestRender() {
|
| - mCompositorView.requestRender();
|
| - }
|
| -
|
| - @Override
|
| - public void onSurfaceCreated() {
|
| - mPendingSwapBuffersCount = 0;
|
| - flushInvalidation();
|
| - }
|
| -
|
| - @Override
|
| - public void onSwapBuffersCompleted(int pendingSwapBuffersCount) {
|
| - TraceEvent.instant("onSwapBuffersCompleted");
|
| -
|
| - // Wait until the second frame to turn off the placeholder background on
|
| - // tablets so the tab strip has time to start drawing.
|
| - final ViewGroup controlContainer = (ViewGroup) mControlContainer;
|
| - if (controlContainer != null && controlContainer.getBackground() != null && mHasDrawnOnce) {
|
| - post(new Runnable() {
|
| - @Override
|
| - public void run() {
|
| - controlContainer.setBackgroundResource(0);
|
| - }
|
| - });
|
| - }
|
| -
|
| - mHasDrawnOnce = true;
|
| -
|
| - mPendingSwapBuffersCount = pendingSwapBuffersCount;
|
| -
|
| - if (!mSkipInvalidation || pendingSwapBuffersCount == 0) flushInvalidation();
|
| - mSkipInvalidation = !mSkipInvalidation;
|
| - }
|
| -
|
| - @Override
|
| - public void setContentOverlayVisibility(boolean show) {
|
| - if (show != mContentOverlayVisiblity) {
|
| - mContentOverlayVisiblity = show;
|
| - updateContentOverlayVisibility(mContentOverlayVisiblity);
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public LayoutRenderHost getLayoutRenderHost() {
|
| - return this;
|
| - }
|
| -
|
| - @Override
|
| - public int getLayoutTabsDrawnCount() {
|
| - return mCompositorView.getLastLayerCount();
|
| - }
|
| -
|
| - @Override
|
| - public void pushDebugRect(Rect rect, int color) {
|
| - if (mDebugOverlay == null) {
|
| - mDebugOverlay = new DebugOverlay(getContext());
|
| - addView(mDebugOverlay);
|
| - }
|
| - mDebugOverlay.pushRect(rect, color);
|
| - }
|
| -
|
| - @Override
|
| - public void loadPersitentTextureDataIfNeeded() {}
|
| -
|
| - @Override
|
| - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
| - super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
| - mIsKeyboardShowing = UiUtils.isKeyboardShowing(getContext(), this);
|
| - }
|
| -
|
| - @Override
|
| - protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
| - if (changed) {
|
| - propagateViewportToLayouts(r - l, b - t);
|
| - }
|
| - super.onLayout(changed, l, t, r, b);
|
| -
|
| - invalidateAccessibilityProvider();
|
| - }
|
| -
|
| - @Override
|
| - public void clearChildFocus(View child) {
|
| - // Override this method so that the ViewRoot doesn't go looking for a new
|
| - // view to take focus. It will find the URL Bar, focus it, then refocus this
|
| - // later, causing a keyboard flicker.
|
| - }
|
| -
|
| - @Override
|
| - public ChromeFullscreenManager getFullscreenManager() {
|
| - return mFullscreenManager;
|
| - }
|
| -
|
| - /**
|
| - * Sets a fullscreen handler.
|
| - * @param fullscreen A fullscreen handler.
|
| - */
|
| - public void setFullscreenHandler(ChromeFullscreenManager fullscreen) {
|
| - mFullscreenManager = fullscreen;
|
| - if (mFullscreenManager != null) {
|
| - mLastContentOffset = mFullscreenManager.getContentOffset();
|
| - mLastVisibleContentOffset = mFullscreenManager.getVisibleContentOffset();
|
| - mFullscreenManager.addListener(this);
|
| - }
|
| - propagateViewportToLayouts(getWidth(), getHeight());
|
| - }
|
| -
|
| - /**
|
| - * Note that the returned rect is reused for other calls.
|
| - */
|
| - @Override
|
| - public Rect getVisibleViewport(Rect rect) {
|
| - if (rect == null) rect = new Rect();
|
| - rect.set(0, (int) mLastVisibleContentOffset, getWidth(), getHeight());
|
| - return rect;
|
| - }
|
| -
|
| - @Override
|
| - public boolean areTopControlsPermanentlyHidden() {
|
| - return mFullscreenManager != null && mFullscreenManager.areTopControlsPermanentlyHidden();
|
| - }
|
| -
|
| - @Override
|
| - public int getTopControlsHeightPixels() {
|
| - return mFullscreenManager != null ? mFullscreenManager.getTopControlsHeight() : 0;
|
| - }
|
| -
|
| - /**
|
| - * Sets the URL bar. This is needed so that the ContentViewHolder can find out
|
| - * whether it can claim focus.
|
| - */
|
| - public void setUrlBar(View urlBar) {
|
| - mUrlBar = urlBar;
|
| - }
|
| -
|
| - @Override
|
| - protected void onAttachedToWindow() {
|
| - mInvalidator.set(this);
|
| - super.onAttachedToWindow();
|
| - }
|
| -
|
| - @Override
|
| - protected void onDetachedFromWindow() {
|
| - if (mLayoutManager != null) mLayoutManager.destroy();
|
| - flushInvalidation();
|
| - mInvalidator.set(null);
|
| - super.onDetachedFromWindow();
|
| -
|
| - // Removes the accessibility node provider from this view.
|
| - if (mNodeProvider != null) {
|
| - mAccessibilityView.setAccessibilityDelegate(null);
|
| - mNodeProvider = null;
|
| - removeView(mAccessibilityView);
|
| - mAccessibilityView = null;
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * @return True if the currently active content view is shown in the normal interactive mode.
|
| - */
|
| - public boolean isTabInteractive() {
|
| - return mLayoutManager != null && mLayoutManager.getActiveLayout() != null
|
| - && mLayoutManager.getActiveLayout().isTabInteractive() && mContentOverlayVisiblity
|
| - && mView != null;
|
| - }
|
| -
|
| - /**
|
| - * Hides the the keyboard if it was opened for the ContentView.
|
| - * @param postHideTask A task to run after the keyboard is done hiding and the view's
|
| - * layout has been updated. If the keyboard was not shown, the task will run
|
| - * immediately.
|
| - */
|
| - public void hideKeyboard(Runnable postHideTask) {
|
| - // When this is called we actually want to hide the keyboard whatever owns it.
|
| - // This includes hiding the keyboard, and dropping focus from the URL bar.
|
| - // See http://crbug/236424
|
| - // TODO(aberent) Find a better place to put this, possibly as part of a wider
|
| - // redesign of focus control.
|
| - if (mUrlBar != null) mUrlBar.clearFocus();
|
| - boolean wasVisible = false;
|
| - if (hasFocus()) {
|
| - wasVisible = UiUtils.hideKeyboard(this);
|
| - }
|
| - if (wasVisible) {
|
| - mPostHideKeyboardTask = postHideTask;
|
| - } else {
|
| - postHideTask.run();
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Sets the appropriate objects this class should represent.
|
| - * @param tabModelSelector The {@link TabModelSelector} this View should hold and
|
| - * represent.
|
| - * @param tabCreatorManager The {@link TabCreatorManager} for this view.
|
| - * @param tabContentManager The {@link TabContentManager} for the tabs.
|
| - * @param androidContentContainer The {@link ViewGroup} the {@link LayoutManager} should bind
|
| - * Android content to.
|
| - * @param contextualSearchManager A {@link ContextualSearchManagementDelegate} instance.
|
| - */
|
| - public void onFinishNativeInitialization(TabModelSelector tabModelSelector,
|
| - TabCreatorManager tabCreatorManager, TabContentManager tabContentManager,
|
| - ViewGroup androidContentContainer,
|
| - ContextualSearchManagementDelegate contextualSearchManager) {
|
| - assert mLayoutManager != null;
|
| - mLayoutManager.init(tabModelSelector, tabCreatorManager, tabContentManager,
|
| - androidContentContainer, contextualSearchManager,
|
| - mCompositorView.getResourceManager().getDynamicResourceLoader());
|
| - mTabModelSelector = tabModelSelector;
|
| - tabModelSelector.addObserver(new EmptyTabModelSelectorObserver() {
|
| - @Override
|
| - public void onChange() {
|
| - onContentChanged();
|
| - }
|
| -
|
| - @Override
|
| - public void onNewTabCreated(Tab tab) {
|
| - initializeTab(tab);
|
| - }
|
| - });
|
| -
|
| - onContentChanged();
|
| - }
|
| -
|
| - private void updateContentOverlayVisibility(boolean show) {
|
| - if (mView == null) return;
|
| -
|
| - sCachedCVCList.clear();
|
| - if (mLayoutManager != null) {
|
| - mLayoutManager.getActiveLayout().getAllContentViewCores(sCachedCVCList);
|
| - }
|
| - if (show) {
|
| - if (mView.getParent() != this) {
|
| - // Make sure the view isn't a child of something else before we attempt to add it.
|
| - if (mView.getParent() != null && mView.getParent() instanceof ViewGroup) {
|
| - ((ViewGroup) mView.getParent()).removeView(mView);
|
| - }
|
| -
|
| - for (int i = 0; i < sCachedCVCList.size(); i++) {
|
| - ContentViewCore content = sCachedCVCList.get(i);
|
| - assert content.isAlive();
|
| - content.getContainerView().setVisibility(View.VISIBLE);
|
| - if (mFullscreenManager != null) {
|
| - mFullscreenManager.updateContentViewViewportSize(content);
|
| - }
|
| - }
|
| -
|
| - FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
|
| - LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
|
| - if (mView.getLayoutParams() instanceof MarginLayoutParams) {
|
| - MarginLayoutParams existingLayoutParams =
|
| - (MarginLayoutParams) mView.getLayoutParams();
|
| - layoutParams.leftMargin = existingLayoutParams.leftMargin;
|
| - layoutParams.rightMargin = existingLayoutParams.rightMargin;
|
| - layoutParams.topMargin = existingLayoutParams.topMargin;
|
| - layoutParams.bottomMargin = existingLayoutParams.bottomMargin;
|
| - }
|
| - addView(mView, layoutParams);
|
| -
|
| - setFocusable(false);
|
| - setFocusableInTouchMode(false);
|
| -
|
| - // Claim focus for the new view unless the user is currently using the URL bar.
|
| - if (mUrlBar == null || !mUrlBar.hasFocus()) mView.requestFocus();
|
| - }
|
| - } else {
|
| - if (mView.getParent() == this) {
|
| - setFocusable(true);
|
| - setFocusableInTouchMode(true);
|
| -
|
| - for (int i = 0; i < sCachedCVCList.size(); i++) {
|
| - ContentViewCore content = sCachedCVCList.get(i);
|
| - if (content.isAlive()) content.getContainerView().setVisibility(View.INVISIBLE);
|
| - }
|
| -
|
| - if (hasFocus()) {
|
| - InputMethodManager manager = (InputMethodManager) getContext().getSystemService(
|
| - Context.INPUT_METHOD_SERVICE);
|
| - if (manager.isActive(this)) {
|
| - manager.hideSoftInputFromWindow(getWindowToken(), 0, null);
|
| - }
|
| - }
|
| - removeView(mView);
|
| - }
|
| - }
|
| - sCachedCVCList.clear();
|
| - }
|
| -
|
| - @Override
|
| - public void onContentChanged() {
|
| - if (mTabModelSelector == null) {
|
| - // Not yet initialized, onContentChanged() will eventually get called by
|
| - // setTabModelSelector.
|
| - return;
|
| - }
|
| - Tab tab = mTabModelSelector.getCurrentTab();
|
| - setTab(tab);
|
| - }
|
| -
|
| - @Override
|
| - public void onContentViewCoreAdded(ContentViewCore content) {
|
| - // TODO(dtrainor): Look into rolling this into onContentChanged().
|
| - initializeContentViewCore(content);
|
| - setSizeOfUnattachedView(content.getContainerView());
|
| - }
|
| -
|
| - private void setTab(Tab tab) {
|
| - if (tab != null && tab.isFrozen()) tab.unfreezeContents();
|
| -
|
| - View newView = tab != null ? tab.getView() : null;
|
| - if (mView == newView) return;
|
| -
|
| - // TODO(dtrainor): Look into changing this only if the views differ, but still parse the
|
| - // ContentViewCore list even if they're the same.
|
| - updateContentOverlayVisibility(false);
|
| -
|
| - if (mTabVisible != tab) {
|
| - if (mTabVisible != null) mTabVisible.removeObserver(mTabObserver);
|
| - if (tab != null) tab.addObserver(mTabObserver);
|
| - }
|
| -
|
| - mTabVisible = tab;
|
| - mView = newView;
|
| -
|
| - updateContentOverlayVisibility(mContentOverlayVisiblity);
|
| -
|
| - if (mTabVisible != null) initializeTab(mTabVisible);
|
| - }
|
| -
|
| - /**
|
| - * Sets the correct size for all {@link View}s on {@code tab} and sets the correct rendering
|
| - * parameters on all {@link ContentViewCore}s on {@code tab}.
|
| - * @param tab The {@link Tab} to initialize.
|
| - */
|
| - private void initializeTab(Tab tab) {
|
| - sCachedCVCList.clear();
|
| - if (mLayoutManager != null) {
|
| - mLayoutManager.getActiveLayout().getAllContentViewCores(sCachedCVCList);
|
| - }
|
| -
|
| - for (int i = 0; i < sCachedCVCList.size(); i++) {
|
| - initializeContentViewCore(sCachedCVCList.get(i));
|
| - }
|
| - sCachedCVCList.clear();
|
| -
|
| - sCachedViewList.clear();
|
| - tab.getAllViews(sCachedViewList);
|
| -
|
| - for (int i = 0; i < sCachedViewList.size(); i++) {
|
| - View view = sCachedViewList.get(i);
|
| - // Calling View#measure() and View#layout() on a View before adding it to the view
|
| - // hierarchy seems to cause issues with compound drawables on some versions of Android.
|
| - // We don't need to proactively size the NTP as we don't need the Android view to render
|
| - // if it's not actually attached to the view hierarchy (http://crbug.com/462114).
|
| - if (view == tab.getView() && tab.isNativePage()) continue;
|
| - setSizeOfUnattachedView(view);
|
| - }
|
| - sCachedViewList.clear();
|
| - }
|
| -
|
| - /**
|
| - * Initializes the rendering surface parameters of {@code contentViewCore}. Note that this does
|
| - * not size the actual {@link ContentViewCore}.
|
| - * @param contentViewCore The {@link ContentViewCore} to initialize.
|
| - */
|
| - private void initializeContentViewCore(ContentViewCore contentViewCore) {
|
| - contentViewCore.setCurrentMotionEventOffsets(0.f, 0.f);
|
| - contentViewCore.setTopControlsHeight(
|
| - getTopControlsHeightPixels(), contentViewCore.doTopControlsShrinkBlinkSize());
|
| - contentViewCore.onPhysicalBackingSizeChanged(
|
| - mCompositorView.getWidth(), mCompositorView.getHeight());
|
| - contentViewCore.onOverdrawBottomHeightChanged(mCompositorView.getOverdrawBottomHeight());
|
| - }
|
| -
|
| - /**
|
| - * Resize {@code view} to match the size of this {@link FrameLayout}. This will only happen if
|
| - * {@code view} is not {@code null} and if {@link View#getWindowToken()} returns {@code null}
|
| - * (the {@link View} is not part of the view hierarchy).
|
| - * @param view The {@link View} to resize.
|
| - * @return Whether or not {@code view} was resized.
|
| - */
|
| - private boolean setSizeOfUnattachedView(View view) {
|
| - // Need to call layout() for the following View if it is not attached to the view hierarchy.
|
| - // Calling onSizeChanged() is dangerous because if the View has a different size than the
|
| - // ContentViewCore it might think a future size update is a NOOP and not call
|
| - // onSizeChanged() on the ContentViewCore.
|
| - if (view == null || view.getWindowToken() != null) return false;
|
| - int width = getWidth();
|
| - int height = getHeight();
|
| - view.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
|
| - MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
|
| - view.layout(0, 0, width, height);
|
| - return true;
|
| - }
|
| -
|
| - @Override
|
| - public TitleCache getTitleCache() {
|
| - return mLayerTitleCache;
|
| - }
|
| -
|
| - @Override
|
| - public void deferInvalidate(Client client) {
|
| - if (mPendingSwapBuffersCount <= 0) {
|
| - client.doInvalidate();
|
| - } else if (!mPendingInvalidations.contains(client)) {
|
| - mPendingInvalidations.add(client);
|
| - }
|
| - }
|
| -
|
| - private void flushInvalidation() {
|
| - if (mPendingInvalidations.isEmpty()) return;
|
| - TraceEvent.instant("CompositorViewHolder.flushInvalidation");
|
| - for (int i = 0; i < mPendingInvalidations.size(); i++) {
|
| - mPendingInvalidations.get(i).doInvalidate();
|
| - }
|
| - mPendingInvalidations.clear();
|
| - }
|
| -
|
| - @Override
|
| - public void invalidateAccessibilityProvider() {
|
| - if (mNodeProvider != null) {
|
| - mNodeProvider.invalidateRoot();
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Called when the accessibility enabled state changes.
|
| - * @param enabled Whether accessibility is enabled.
|
| - */
|
| - public void onAccessibilityStatusChanged(boolean enabled) {
|
| - // Instantiate and install the accessibility node provider on this view if necessary.
|
| - // This overrides any hover event listeners or accessibility delegates
|
| - // that may have been added elsewhere.
|
| - if (enabled && (mNodeProvider == null)) {
|
| - mAccessibilityView = new View(getContext());
|
| - addView(mAccessibilityView);
|
| - mNodeProvider = new CompositorAccessibilityProvider(mAccessibilityView);
|
| - ViewCompat.setAccessibilityDelegate(mAccessibilityView, mNodeProvider);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Class used to provide a virtual view hierarchy to the Accessibility
|
| - * framework for this view and its contained items.
|
| - * <p>
|
| - * <strong>NOTE:</strong> This class is fully backwards compatible for
|
| - * compilation, but will only provide touch exploration on devices running
|
| - * Ice Cream Sandwich and above.
|
| - * </p>
|
| - */
|
| - private class CompositorAccessibilityProvider extends ExploreByTouchHelper {
|
| - private final float mDpToPx;
|
| - List<VirtualView> mVirtualViews = new ArrayList<VirtualView>();
|
| - private final Rect mPlaceHolderRect = new Rect(0, 0, 1, 1);
|
| - private static final String PLACE_HOLDER_STRING = "";
|
| - private final RectF mTouchTarget = new RectF();
|
| - private final Rect mPixelRect = new Rect();
|
| -
|
| - public CompositorAccessibilityProvider(View forView) {
|
| - super(forView);
|
| - mDpToPx = getContext().getResources().getDisplayMetrics().density;
|
| - }
|
| -
|
| - @Override
|
| - protected int getVirtualViewAt(float x, float y) {
|
| - if (mVirtualViews == null) return INVALID_ID;
|
| - for (int i = 0; i < mVirtualViews.size(); i++) {
|
| - if (mVirtualViews.get(i).checkClicked(x / mDpToPx, y / mDpToPx)) {
|
| - return i;
|
| - }
|
| - }
|
| - return INVALID_ID;
|
| - }
|
| -
|
| - @Override
|
| - protected void getVisibleVirtualViews(List<Integer> virtualViewIds) {
|
| - if (mLayoutManager == null) return;
|
| - mVirtualViews.clear();
|
| - mLayoutManager.getVirtualViews(mVirtualViews);
|
| - for (int i = 0; i < mVirtualViews.size(); i++) {
|
| - virtualViewIds.add(i);
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - protected boolean onPerformActionForVirtualView(
|
| - int virtualViewId, int action, Bundle arguments) {
|
| - switch (action) {
|
| - case AccessibilityNodeInfoCompat.ACTION_CLICK:
|
| - return true;
|
| - }
|
| -
|
| - return false;
|
| - }
|
| -
|
| - @Override
|
| - protected void onPopulateEventForVirtualView(int virtualViewId, AccessibilityEvent event) {
|
| - if (mVirtualViews == null || mVirtualViews.size() <= virtualViewId) {
|
| - // TODO(clholgat): Remove this work around when the Android bug is fixed.
|
| - // crbug.com/420177
|
| - event.setContentDescription(PLACE_HOLDER_STRING);
|
| - return;
|
| - }
|
| - VirtualView view = mVirtualViews.get(virtualViewId);
|
| -
|
| - event.setContentDescription(view.getAccessibilityDescription());
|
| - event.setClassName(CompositorViewHolder.class.getName());
|
| - }
|
| -
|
| - @Override
|
| - protected void onPopulateNodeForVirtualView(
|
| - int virtualViewId, AccessibilityNodeInfoCompat node) {
|
| - if (mVirtualViews == null || mVirtualViews.size() <= virtualViewId) {
|
| - // TODO(clholgat): Remove this work around when the Android bug is fixed.
|
| - // crbug.com/420177
|
| - node.setBoundsInParent(mPlaceHolderRect);
|
| - node.setContentDescription(PLACE_HOLDER_STRING);
|
| - return;
|
| - }
|
| - VirtualView view = mVirtualViews.get(virtualViewId);
|
| - view.getTouchTarget(mTouchTarget);
|
| -
|
| - node.setBoundsInParent(rectToPx(mTouchTarget));
|
| - node.setContentDescription(view.getAccessibilityDescription());
|
| - node.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
|
| - node.addAction(AccessibilityNodeInfoCompat.ACTION_FOCUS);
|
| - node.addAction(AccessibilityNodeInfoCompat.ACTION_LONG_CLICK);
|
| - }
|
| -
|
| - private Rect rectToPx(RectF rect) {
|
| - rect.roundOut(mPixelRect);
|
| - mPixelRect.left = (int) (mPixelRect.left * mDpToPx);
|
| - mPixelRect.top = (int) (mPixelRect.top * mDpToPx);
|
| - mPixelRect.right = (int) (mPixelRect.right * mDpToPx);
|
| - mPixelRect.bottom = (int) (mPixelRect.bottom * mDpToPx);
|
| -
|
| - // Don't let any zero sized rects through, they'll cause parent
|
| - // size errors in L.
|
| - if (mPixelRect.width() == 0) {
|
| - mPixelRect.right = mPixelRect.left + 1;
|
| - }
|
| - if (mPixelRect.height() == 0) {
|
| - mPixelRect.bottom = mPixelRect.top + 1;
|
| - }
|
| - return mPixelRect;
|
| - }
|
| - }
|
| -}
|
|
|