1 // Copyright 2019 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.chrome.browser.tab; 6 7 import androidx.annotation.NonNull; 8 9 import org.chromium.base.ObserverList.RewindableIterator; 10 import org.chromium.base.UserData; 11 12 /** 13 * Helper that coordinates the browser controls offsets from the perspective of a particular Tab. 14 */ 15 public class TabBrowserControlsOffsetHelper extends EmptyTabObserver implements UserData { 16 private static final Class<TabBrowserControlsOffsetHelper> USER_DATA_KEY = 17 TabBrowserControlsOffsetHelper.class; 18 19 private final TabImpl mTab; 20 21 private int mTopControlsOffset; 22 private int mBottomControlsOffset; 23 private int mContentOffset; 24 private int mTopControlsMinHeightOffset; 25 private int mBottomControlsMinHeightOffset; 26 27 /** {@code true} if offset was changed by compositor. */ 28 private boolean mOffsetInitialized; 29 30 /** 31 * Get (or lazily create) the offset helper for a particular Tab. 32 * @param tab The tab whose helper is being retrieved. 33 * @return The offset helper for a given tab. 34 */ 35 @NonNull get(Tab tab)36 public static TabBrowserControlsOffsetHelper get(Tab tab) { 37 TabBrowserControlsOffsetHelper helper = tab.getUserDataHost().getUserData(USER_DATA_KEY); 38 if (helper == null) { 39 helper = new TabBrowserControlsOffsetHelper(tab); 40 tab.getUserDataHost().setUserData(USER_DATA_KEY, helper); 41 } 42 return helper; 43 } 44 TabBrowserControlsOffsetHelper(Tab tab)45 private TabBrowserControlsOffsetHelper(Tab tab) { 46 mTab = (TabImpl) tab; 47 tab.addObserver(this); 48 } 49 50 /** 51 * Sets new top control, content, and min-height offset from renderer. 52 * @param topControlsOffset Top control offset. 53 * @param contentOffset Content offset. 54 * @param topControlsMinHeightOffset Current min-height offset for the top controls that may be 55 * changing as a result of an in-progress min-height change 56 * animation in the renderer. 57 */ setTopOffset(int topControlsOffset, int contentOffset, int topControlsMinHeightOffset)58 void setTopOffset(int topControlsOffset, int contentOffset, int topControlsMinHeightOffset) { 59 if (mOffsetInitialized && topControlsOffset == mTopControlsOffset 60 && mContentOffset == contentOffset 61 && mTopControlsMinHeightOffset == topControlsMinHeightOffset) { 62 return; 63 } 64 mTopControlsOffset = topControlsOffset; 65 mContentOffset = contentOffset; 66 mTopControlsMinHeightOffset = topControlsMinHeightOffset; 67 notifyControlsOffsetChanged(); 68 } 69 70 /** 71 * Sets new bottom control offset from renderer. 72 * @param bottomControlsOffset Bottom control offset. 73 * @param bottomControlsMinHeightOffset Current min-height offset for the bottom controls that 74 * may be changing as a result of an in-progress min-height 75 * change animation in the renderer. 76 */ setBottomOffset(int bottomControlsOffset, int bottomControlsMinHeightOffset)77 void setBottomOffset(int bottomControlsOffset, int bottomControlsMinHeightOffset) { 78 if (mOffsetInitialized && mBottomControlsOffset == bottomControlsOffset 79 && mBottomControlsMinHeightOffset == bottomControlsMinHeightOffset) { 80 return; 81 } 82 mBottomControlsOffset = bottomControlsOffset; 83 mBottomControlsMinHeightOffset = bottomControlsMinHeightOffset; 84 notifyControlsOffsetChanged(); 85 } 86 notifyControlsOffsetChanged()87 private void notifyControlsOffsetChanged() { 88 mOffsetInitialized = true; 89 RewindableIterator<TabObserver> observers = mTab.getTabObservers(); 90 while (observers.hasNext()) { 91 observers.next().onBrowserControlsOffsetChanged(mTab, mTopControlsOffset, 92 mBottomControlsOffset, mContentOffset, mTopControlsMinHeightOffset, 93 mBottomControlsMinHeightOffset); 94 } 95 } 96 97 @Override onCrash(Tab tab)98 public void onCrash(Tab tab) { 99 super.onCrash(tab); 100 mTopControlsOffset = 0; 101 mBottomControlsOffset = 0; 102 mContentOffset = 0; 103 mOffsetInitialized = false; 104 } 105 106 /** @return Top control offset */ topControlsOffset()107 public int topControlsOffset() { 108 return mTopControlsOffset; 109 } 110 111 /** @return Bottom control offset */ bottomControlsOffset()112 public int bottomControlsOffset() { 113 return mBottomControlsOffset; 114 } 115 116 /** @return Content offset */ contentOffset()117 public int contentOffset() { 118 return mContentOffset; 119 } 120 121 /** @return Top controls min-height offset */ topControlsMinHeightOffset()122 public int topControlsMinHeightOffset() { 123 return mTopControlsMinHeightOffset; 124 } 125 126 /** @return Bottom controls min-height offset */ bottomControlsMinHeightOffset()127 public int bottomControlsMinHeightOffset() { 128 return mBottomControlsMinHeightOffset; 129 } 130 131 /** @return Whether the control offset is initialized by compositor. */ offsetInitialized()132 public boolean offsetInitialized() { 133 return mOffsetInitialized; 134 } 135 } 136