1 // Copyright 2015 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.compositor.layouts; 6 7 import android.content.Context; 8 import android.graphics.PointF; 9 import android.graphics.RectF; 10 import android.view.MotionEvent; 11 import android.view.ViewGroup; 12 13 import androidx.annotation.IntDef; 14 import androidx.annotation.VisibleForTesting; 15 16 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; 17 import org.chromium.chrome.browser.compositor.LayerTitleCache; 18 import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab; 19 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; 20 import org.chromium.chrome.browser.layouts.EventFilter; 21 import org.chromium.chrome.browser.layouts.LayoutType; 22 import org.chromium.chrome.browser.layouts.animation.CompositorAnimationHandler; 23 import org.chromium.chrome.browser.layouts.scene_layer.SceneLayer; 24 import org.chromium.chrome.browser.tab.Tab; 25 import org.chromium.chrome.browser.tabmodel.TabModel; 26 import org.chromium.chrome.browser.tabmodel.TabModelSelector; 27 import org.chromium.chrome.browser.tabmodel.TabModelUtils; 28 import org.chromium.ui.modelutil.PropertyModel; 29 import org.chromium.ui.resources.ResourceManager; 30 31 import java.lang.annotation.Retention; 32 import java.lang.annotation.RetentionPolicy; 33 import java.util.List; 34 35 /** 36 * Abstract representation of an OpenGL layout tailored to draw tabs. It is a framework used as an 37 * alternative to the Android UI for lower level hardware accelerated rendering. 38 * This layout also pass through all the events that may happen. 39 */ 40 41 public abstract class Layout implements TabContentManager.ThumbnailChangeListener { 42 43 /** 44 * The orientation of the device. 45 */ 46 @IntDef({Orientation.UNSET, Orientation.PORTRAIT, Orientation.LANDSCAPE}) 47 @Retention(RetentionPolicy.SOURCE) 48 public @interface Orientation { 49 int UNSET = 0; 50 int PORTRAIT = 1; 51 int LANDSCAPE = 2; 52 } 53 54 /** The possible variations of the visible viewport that different layouts may need. */ 55 @IntDef({ViewportMode.ALWAYS_FULLSCREEN, ViewportMode.ALWAYS_SHOWING_BROWSER_CONTROLS, 56 ViewportMode.DYNAMIC_BROWSER_CONTROLS, 57 ViewportMode.USE_PREVIOUS_BROWSER_CONTROLS_STATE}) 58 @Retention(RetentionPolicy.SOURCE) 59 public @interface ViewportMode { 60 /** The viewport is assumed to be always fullscreen. */ 61 int ALWAYS_FULLSCREEN = 0; 62 /** The viewport is assuming that browser controls are permanently shown. */ 63 int ALWAYS_SHOWING_BROWSER_CONTROLS = 1; 64 /** The viewport will account for animating browser controls (both shown and hidden). */ 65 int DYNAMIC_BROWSER_CONTROLS = 2; 66 /** Use a viewport that accounts for the browser controls state in the previous layout. */ 67 int USE_PREVIOUS_BROWSER_CONTROLS_STATE = 3; 68 } 69 70 // Defines to make the code easier to read. 71 public static final boolean NEED_TITLE = true; 72 public static final boolean NO_TITLE = false; 73 public static final boolean SHOW_CLOSE_BUTTON = true; 74 public static final boolean NO_CLOSE_BUTTON = false; 75 76 /** Length of the unstalling animation. **/ 77 public static final long UNSTALLED_ANIMATION_DURATION_MS = 500; 78 79 private static final float SNAP_SPEED = 1.0f; // dp per second 80 81 // Drawing area properties. 82 private float mWidthDp; 83 private float mHeightDp; 84 private float mTopBrowserControlsHeightDp; 85 private float mBottomBrowserControlsHeightDp; 86 87 /** A {@link Context} instance. */ 88 private Context mContext; 89 90 /** The current {@link Orientation} of the layout. */ 91 private @Orientation int mCurrentOrientation; 92 93 // Tabs 94 protected TabModelSelector mTabModelSelector; 95 protected TabContentManager mTabContentManager; 96 97 // Helpers 98 private final LayoutUpdateHost mUpdateHost; 99 protected final LayoutRenderHost mRenderHost; 100 101 /** The tabs currently being rendered as part of this layout. The tabs are 102 * drawn using the same ordering as this array. */ 103 protected LayoutTab[] mLayoutTabs; 104 105 // True means that the layout is going to hide as soon as the animation finishes. 106 private boolean mIsStartingToHide; 107 108 // True means that the layout is going to show as soon as the animation finishes. 109 private boolean mIsStartingToShow; 110 111 // The next id to show when the layout is hidden, or TabBase#INVALID_TAB_ID if no change. 112 protected int mNextTabId = Tab.INVALID_TAB_ID; 113 114 // The ratio of dp to px. 115 protected final float mDpToPx; 116 protected final float mPxToDp; 117 118 /** 119 * The {@link Layout} is not usable until sizeChanged is called. 120 * This is convenient this way so we can pre-create the layout before the host is fully defined. 121 * @param context The current Android's context. 122 * @param updateHost The parent {@link LayoutUpdateHost}. 123 * @param renderHost The parent {@link LayoutRenderHost}. 124 */ Layout(Context context, LayoutUpdateHost updateHost, LayoutRenderHost renderHost)125 public Layout(Context context, LayoutUpdateHost updateHost, LayoutRenderHost renderHost) { 126 mContext = context; 127 mUpdateHost = updateHost; 128 mRenderHost = renderHost; 129 130 // Invalid sizes 131 mWidthDp = -1; 132 mHeightDp = -1; 133 mTopBrowserControlsHeightDp = -1; 134 mBottomBrowserControlsHeightDp = -1; 135 136 mCurrentOrientation = Orientation.UNSET; 137 mDpToPx = context.getResources().getDisplayMetrics().density; 138 mPxToDp = 1 / mDpToPx; 139 } 140 141 /** 142 * @return The handler responsible for running compositor animations. 143 */ getAnimationHandler()144 public CompositorAnimationHandler getAnimationHandler() { 145 return mUpdateHost.getAnimationHandler(); 146 } 147 148 /** 149 * Called when native initialization is completed. 150 */ onFinishNativeInitialization()151 public void onFinishNativeInitialization() {} 152 153 /** 154 * Cleans up any internal state. This object should not be used after this call. 155 */ destroy()156 public void destroy() { 157 } 158 159 /** 160 * @return The current {@link Context} instance associated with this {@link Layout}. 161 */ getContext()162 public Context getContext() { 163 return mContext; 164 } 165 166 /** 167 * @return Whether the {@link Layout} is currently active. 168 */ isActive()169 public boolean isActive() { 170 return mUpdateHost.isActiveLayout(this); 171 } 172 173 /** 174 * Creates a {@link LayoutTab}. 175 * @param id The id of the reference {@link Tab} in the {@link TabModel}. 176 * @param isIncognito Whether the new tab is incognito. 177 * @param showCloseButton True to show and activate a close button on the border. 178 * @param isTitleNeeded Whether a title will be shown. 179 * @return The newly created {@link LayoutTab}. 180 */ createLayoutTab( int id, boolean isIncognito, boolean showCloseButton, boolean isTitleNeeded)181 public LayoutTab createLayoutTab( 182 int id, boolean isIncognito, boolean showCloseButton, boolean isTitleNeeded) { 183 return createLayoutTab(id, isIncognito, showCloseButton, isTitleNeeded, -1.f, -1.f); 184 } 185 186 /** 187 * Creates a {@link LayoutTab}. 188 * @param id The id of the reference {@link Tab} in the {@link TabModel}. 189 * @param isIncognito Whether the new tab is incognito. 190 * @param showCloseButton True to show and activate a close button on the border. 191 * @param isTitleNeeded Whether a title will be shown. 192 * @param maxContentWidth The max content width of the tab. Negative numbers will use the 193 * original content width. 194 * @param maxContentHeight The max content height of the tab. Negative numbers will use the 195 * original content height. 196 * @return The newly created {@link LayoutTab}. 197 */ createLayoutTab(int id, boolean isIncognito, boolean showCloseButton, boolean isTitleNeeded, float maxContentWidth, float maxContentHeight)198 public LayoutTab createLayoutTab(int id, boolean isIncognito, boolean showCloseButton, 199 boolean isTitleNeeded, float maxContentWidth, float maxContentHeight) { 200 LayoutTab layoutTab = mUpdateHost.createLayoutTab( 201 id, isIncognito, showCloseButton, isTitleNeeded, maxContentWidth, maxContentHeight); 202 initLayoutTabFromHost(layoutTab); 203 return layoutTab; 204 } 205 206 /** 207 * Releases the data we keep for that {@link LayoutTab}. 208 * @param layoutTab The {@link LayoutTab} to release. 209 */ releaseTabLayout(LayoutTab layoutTab)210 public void releaseTabLayout(LayoutTab layoutTab) { 211 mUpdateHost.releaseTabLayout(layoutTab.getId()); 212 } 213 214 /** 215 * Releases cached title texture resources for the {@link LayoutTab}. 216 * @param layoutTab The {@link LayoutTab} to release resources for. 217 */ releaseResourcesForTab(LayoutTab layoutTab)218 public void releaseResourcesForTab(LayoutTab layoutTab) { 219 mUpdateHost.releaseResourcesForTab(layoutTab.getId()); 220 } 221 222 /** 223 * Update the animation and give chance to cascade the changes. 224 * @param time The current time of the app in ms. 225 * @param dt The delta time between update frames in ms. 226 * @return Whether the layout is done updating. 227 */ onUpdate(long time, long dt)228 public final boolean onUpdate(long time, long dt) { 229 final boolean doneAnimating = onUpdateAnimation(time, false); 230 231 // Don't update the layout if onUpdateAnimation ended up making a new layout active. 232 if (mUpdateHost.isActiveLayout(this)) updateLayout(time, dt); 233 234 return doneAnimating; 235 } 236 237 /** 238 * Layout-specific updates. Cascades the values updated by the animations. 239 * @param time The current time of the app in ms. 240 * @param dt The delta time between update frames in ms. 241 */ updateLayout(long time, long dt)242 protected void updateLayout(long time, long dt) {} 243 244 /** 245 * Update snapping to pixel. To be called once every frame. 246 * 247 * TODO(crbug.com/1070281): Temporary placement. This is some Mediator logic and should move to 248 * the appropriate location when doing MVC. Maybe move to {@link LayoutMediator}. 249 * 250 * @param dt The delta time between update frames in ms. 251 * @param layoutTab The {@link LayoutTab} that needs to be updating. 252 * @return True if the snapping requests to render at least one more frame. 253 */ updateSnap(long dt, PropertyModel layoutTab)254 protected boolean updateSnap(long dt, PropertyModel layoutTab) { 255 final float step = dt * SNAP_SPEED / 1000.0f; 256 final float renderX = layoutTab.get(LayoutTab.RENDER_X); 257 final float renderY = layoutTab.get(LayoutTab.RENDER_Y); 258 final float x = updateSnap(step, renderX, layoutTab.get(LayoutTab.X)); 259 final float y = updateSnap(step, renderY, layoutTab.get(LayoutTab.Y)); 260 final boolean change = x != renderX || y != renderY; 261 layoutTab.set(LayoutTab.RENDER_X, x); 262 layoutTab.set(LayoutTab.RENDER_Y, y); 263 return change; 264 } 265 updateSnap(float step, float current, float ref)266 private float updateSnap(float step, float current, float ref) { 267 if (Math.abs(current - ref) > mPxToDp) return ref; 268 final float refRounded = Math.round(ref * mDpToPx) * mPxToDp; 269 if (refRounded < ref) { 270 current -= step; 271 current = Math.max(refRounded, current); 272 } else { 273 current += step; 274 current = Math.min(refRounded, current); 275 } 276 return current; 277 } 278 279 /** 280 * Request that the renderer render a frame (after the current frame). This 281 * should be called whenever a new frame should be rendered. 282 */ requestRender()283 public void requestRender() { 284 mRenderHost.requestRender(); 285 } 286 287 /** 288 * Requests one more frame of refresh for the transforms and changing properties. Primarily, 289 * this is so animations can continue to animate. 290 */ requestUpdate()291 public void requestUpdate() { 292 mUpdateHost.requestUpdate(); 293 } 294 295 /** 296 * Called when the context and size of the view has changed. 297 * 298 * @param context The current Android's context. 299 */ contextChanged(Context context)300 public void contextChanged(Context context) { 301 mContext = context; 302 LayoutTab.resetDimensionConstants(context); 303 } 304 305 /** 306 * Called when the size of the viewport has changed. 307 * @param visibleViewportPx The visible viewport that represents the area on the 308 * screen this {@link Layout} gets to draw to in px 309 * (potentially takes into account browser controls). 310 * @param screenViewportPx The viewport of the screen in px. 311 * @param topBrowserControlsHeightPx The top browser controls height in px. 312 * @param bottomBrowserControlsHeightPx The bottom browser controls height in px. 313 * @param orientation The new orientation. Valid values are defined by 314 * {@link Orientation}. 315 */ sizeChanged(RectF visibleViewportPx, RectF screenViewportPx, int topBrowserControlsHeightPx, int bottomBrowserControlsHeightPx, @Orientation int orientation)316 final void sizeChanged(RectF visibleViewportPx, RectF screenViewportPx, 317 int topBrowserControlsHeightPx, int bottomBrowserControlsHeightPx, 318 @Orientation int orientation) { 319 // 1. Pull out this Layout's width and height properties based on the viewport. 320 float width = screenViewportPx.width() / mDpToPx; 321 float height = screenViewportPx.height() / mDpToPx; 322 float topBrowserControlsHeightDp = topBrowserControlsHeightPx / mDpToPx; 323 float bottomBrowserControlsHeightDp = bottomBrowserControlsHeightPx / mDpToPx; 324 325 // 2. Check if any Layout-specific properties have changed. 326 boolean layoutPropertiesChanged = Float.compare(mWidthDp, width) != 0 327 || Float.compare(mHeightDp, height) != 0 328 || Float.compare(mTopBrowserControlsHeightDp, topBrowserControlsHeightDp) != 0 329 || Float.compare(mBottomBrowserControlsHeightDp, bottomBrowserControlsHeightDp) != 0 330 || mCurrentOrientation != orientation; 331 332 // 3. Update the internal sizing properties. 333 mWidthDp = width; 334 mHeightDp = height; 335 mTopBrowserControlsHeightDp = topBrowserControlsHeightDp; 336 mBottomBrowserControlsHeightDp = bottomBrowserControlsHeightDp; 337 mCurrentOrientation = orientation; 338 339 // 4. Notify the actual Layout if necessary. 340 if (layoutPropertiesChanged) { 341 notifySizeChanged(width, height, orientation); 342 } 343 } 344 345 /** 346 * Notifies when the size or the orientation of the view has actually changed. 347 * 348 * @param width The new width in dp. 349 * @param height The new height in dp. 350 * @param orientation The new orientation. 351 */ notifySizeChanged(float width, float height, @Orientation int orientation)352 protected void notifySizeChanged(float width, float height, @Orientation int orientation) {} 353 354 /** 355 * Sets the managers needed to for the layout to get information from outside. The managers 356 * are tailored to be called from the GL thread. 357 * 358 * @param modelSelector The {@link TabModelSelector} to be set on the layout. 359 * @param manager The {@link TabContentManager} to get tab display content. 360 */ setTabModelSelector(TabModelSelector modelSelector, TabContentManager manager)361 public void setTabModelSelector(TabModelSelector modelSelector, TabContentManager manager) { 362 mTabModelSelector = modelSelector; 363 setTabContentManager(manager); 364 } 365 366 /** 367 * Sets the manager needed for the layout to get thumbnails. 368 * 369 * @param manager The {@link TabContentManager} to get tab display content. 370 */ setTabContentManager(TabContentManager manager)371 protected void setTabContentManager(TabContentManager manager) { 372 if (manager == null) return; 373 374 if (mTabContentManager != null) mTabContentManager.removeThumbnailChangeListener(this); 375 mTabContentManager = manager; 376 mTabContentManager.addThumbnailChangeListener(this); 377 } 378 379 /** 380 * @return The sizing mode for the layout. 381 */ getViewportMode()382 public @ViewportMode int getViewportMode() { 383 return ViewportMode.ALWAYS_SHOWING_BROWSER_CONTROLS; 384 } 385 386 /** 387 * Informs this cache of the visible {@link Tab} {@code id}s, as well as the 388 * primary screen-filling tab. 389 */ updateCacheVisibleIdsAndPrimary(List<Integer> visible, int primaryTabId)390 protected void updateCacheVisibleIdsAndPrimary(List<Integer> visible, int primaryTabId) { 391 if (mTabContentManager != null) mTabContentManager.updateVisibleIds(visible, primaryTabId); 392 } 393 394 /** 395 * Informs this cache of the visible {@link Tab} {@code id}s, in cases where there 396 * is no primary screen-filling tab. 397 */ updateCacheVisibleIds(List<Integer> visible)398 protected void updateCacheVisibleIds(List<Integer> visible) { 399 if (mTabContentManager != null) mTabContentManager.updateVisibleIds(visible, -1); 400 } 401 402 /** 403 * To be called when the layout is starting a transition out of the view mode. 404 * @param nextTabId The id of the next tab. 405 * @param hintAtTabSelection Whether or not the new tab selection should be broadcast as a hint 406 * potentially before this {@link Layout} is done hiding and the 407 * selection occurs. 408 */ startHiding(int nextTabId, boolean hintAtTabSelection)409 public void startHiding(int nextTabId, boolean hintAtTabSelection) { 410 mUpdateHost.startHiding(nextTabId, hintAtTabSelection); 411 mIsStartingToHide = true; 412 mNextTabId = nextTabId; 413 } 414 415 /** 416 * @return True is the layout is in the process of hiding itself. 417 */ isStartingToHide()418 public boolean isStartingToHide() { 419 return mIsStartingToHide; 420 } 421 422 /** 423 * @return True is the layout is in the process of showing itself. 424 */ isStartingToShow()425 public boolean isStartingToShow() { 426 return mIsStartingToShow; 427 } 428 429 /** 430 * @return The incognito state of the layout. 431 */ isIncognito()432 public boolean isIncognito() { 433 return mTabModelSelector.isIncognitoSelected(); 434 } 435 436 /** 437 * To be called when the transition into the layout is done. 438 */ doneShowing()439 public void doneShowing() { 440 if (!mIsStartingToShow) return; 441 442 mIsStartingToShow = false; 443 mUpdateHost.doneShowing(); 444 } 445 446 /** 447 * To be called when the transition out of the view mode is done. 448 * This is currently called by the renderer when all the animation are done while hiding. 449 */ doneHiding()450 public void doneHiding() { 451 if (!mIsStartingToHide) return; 452 453 mIsStartingToHide = false; 454 if (mNextTabId != Tab.INVALID_TAB_ID) { 455 TabModel model = mTabModelSelector.getModelForTabId(mNextTabId); 456 if (model != null) { 457 TabModelUtils.setIndex(model, TabModelUtils.getTabIndexById(model, mNextTabId)); 458 } 459 mNextTabId = Tab.INVALID_TAB_ID; 460 } 461 mUpdateHost.doneHiding(); 462 if (mRenderHost != null && mRenderHost.getResourceManager() != null) { 463 mRenderHost.getResourceManager().clearTintedResourceCache(); 464 } 465 466 if (getSceneLayer() != null) getSceneLayer().removeFromParent(); 467 } 468 469 /** 470 * Called when a tab is getting selected. Typically when exiting the overview mode. 471 * @param time The current time of the app in ms. 472 * @param tabId The id of the selected tab. 473 */ onTabSelecting(long time, int tabId)474 public void onTabSelecting(long time, int tabId) { 475 startHiding(tabId, true); 476 } 477 478 /** 479 * Initialize the layout to be shown. 480 * @param time The current time of the app in ms. 481 * @param animate Whether to play an entry animation. 482 */ show(long time, boolean animate)483 public void show(long time, boolean animate) { 484 // TODO(crbug.com/1108496): Remove after LayoutManager explicitly hide the old layout. 485 mIsStartingToHide = false; 486 mIsStartingToShow = true; 487 mNextTabId = Tab.INVALID_TAB_ID; 488 } 489 490 /** 491 * Hands the layout an Android view to attach it's views to. 492 * @param container The Android View to attach the layout's views to. 493 */ attachViews(ViewGroup container)494 public void attachViews(ViewGroup container) { } 495 496 /** 497 * Signal to the Layout to detach it's views from the container. 498 */ detachViews()499 public void detachViews() { } 500 501 /** 502 * Forces the current animation to finish and broadcasts the proper event. 503 */ forceAnimationToFinish()504 protected void forceAnimationToFinish() {} 505 506 /** 507 * @return The width of the drawing area in dp. 508 */ getWidth()509 public float getWidth() { 510 return mWidthDp; 511 } 512 513 /** 514 * @return The height of the drawing area in dp. 515 */ getHeight()516 public float getHeight() { 517 return mHeightDp; 518 } 519 520 /** 521 * @return The height of the bottom browser controls in dp. 522 */ getBottomBrowserControlsHeight()523 public float getBottomBrowserControlsHeight() { 524 return mBottomBrowserControlsHeightDp; 525 } 526 527 /** 528 * @see Orientation 529 * @return The orientation of the screen (portrait or landscape). Values are defined by 530 * {@link Orientation}. 531 */ getOrientation()532 public @Orientation int getOrientation() { 533 return mCurrentOrientation; 534 } 535 536 /** 537 * Initializes a {@link LayoutTab} with data from the {@link LayoutUpdateHost}. This function 538 * eventually needs to be called but may be overridden to manage the posting traffic. 539 * 540 * @param layoutTab The {@link LayoutTab} To initialize from a 541 * {@link Tab} on the UI thread. 542 * @return Whether the asynchronous initialization of the {@link LayoutTab} has really 543 * been posted. 544 */ initLayoutTabFromHost(LayoutTab layoutTab)545 protected boolean initLayoutTabFromHost(LayoutTab layoutTab) { 546 if (layoutTab.isInitFromHostNeeded()) { 547 mUpdateHost.initLayoutTabFromHost(layoutTab.getId()); 548 return true; 549 } 550 return false; 551 } 552 553 /** 554 * Called by the LayoutManager when an animation should be killed. 555 */ unstallImmediately()556 public void unstallImmediately() { } 557 558 /** 559 * Called by the LayoutManager when an animation should be killed. 560 * @param tabId The tab that the kill signal is associated with 561 */ unstallImmediately(int tabId)562 public void unstallImmediately(int tabId) { } 563 564 /** 565 * Called by the LayoutManager when they system back button is pressed. 566 * @return Whether or not the layout consumed the event. 567 */ onBackPressed()568 public boolean onBackPressed() { 569 return false; 570 } 571 572 /** 573 * Called when a tab get selected. Typically when a tab get closed and the new current tab get 574 * selected. 575 * @param time The current time of the app in ms. 576 * @param tabId The id of the selected tab. 577 * @param prevId The id of the previously selected tab. 578 * @param incognito Whether or not the affected model was incognito. 579 */ onTabSelected(long time, int tabId, int prevId, boolean incognito)580 public void onTabSelected(long time, int tabId, int prevId, boolean incognito) { 581 } 582 583 /** 584 * Called when a tab is about to be closed. When called, the closing tab will still 585 * be part of the model. 586 * @param time The current time of the app in ms. 587 * @param tabId The id of the tab being closed 588 */ onTabClosing(long time, int tabId)589 public void onTabClosing(long time, int tabId) { 590 } 591 592 /** 593 * Called when a tab is being closed. When called, the closing tab will not 594 * be part of the model. 595 * @param time The current time of the app in ms. 596 * @param tabId The id of the tab being closed. 597 * @param nextTabId The id if the tab that is being switched to. 598 * @param incognito Whether or not the affected model was incognito. 599 */ onTabClosed(long time, int tabId, int nextTabId, boolean incognito)600 public void onTabClosed(long time, int tabId, int nextTabId, boolean incognito) { 601 } 602 603 /** 604 * Called when all the tabs in the current stack need to be closed. 605 * When called, the tabs will still be part of the model. 606 * @param time The current time of the app in ms. 607 * @param incognito True if this the incognito tab model should close all tabs, false otherwise. 608 */ onTabsAllClosing(long time, boolean incognito)609 public void onTabsAllClosing(long time, boolean incognito) { 610 } 611 612 /** 613 * Called before a tab is created from the top left button. 614 * 615 * @param sourceTabId The id of the source tab. 616 */ onTabCreating(int sourceTabId)617 public void onTabCreating(int sourceTabId) { } 618 619 /** 620 * Called when a tab is created from the top left button. 621 * @param time The current time of the app in ms. 622 * @param tabId The id of the newly created tab. 623 * @param tabIndex The index of the newly created tab. 624 * @param sourceTabId The id of the source tab. 625 * @param newIsIncognito Whether the new tab is incognito. 626 * @param background Whether the tab is created in the background. 627 * @param originX The X screen coordinate in dp of the last touch down event that spawned 628 * this tab. 629 * @param originY The Y screen coordinate in dp of the last touch down event that spawned 630 * this tab. 631 */ onTabCreated(long time, int tabId, int tabIndex, int sourceTabId, boolean newIsIncognito, boolean background, float originX, float originY)632 public void onTabCreated(long time, int tabId, int tabIndex, int sourceTabId, 633 boolean newIsIncognito, boolean background, float originX, float originY) { 634 } 635 636 /** 637 * Called when a tab is restored (created FROM_RESTORE). 638 * @param time The current time of the app in ms. 639 * @param tabId The id of the restored tab. 640 */ onTabRestored(long time, int tabId)641 public void onTabRestored(long time, int tabId) { } 642 643 /** 644 * Called when the current tabModel switched (e.g. standard -> incognito). 645 * 646 * @param incognito True if the new model is incognito. 647 */ onTabModelSwitched(boolean incognito)648 public void onTabModelSwitched(boolean incognito) { 649 } 650 651 /** 652 * Called when a tab is finally closed if the action was previously undoable. 653 * @param time The current time of the app in ms. 654 * @param id The id of the Tab. 655 * @param incognito True if the tab is incognito 656 */ onTabClosureCommitted(long time, int id, boolean incognito)657 public void onTabClosureCommitted(long time, int id, boolean incognito) { } 658 659 @Override onThumbnailChange(int id)660 public void onThumbnailChange(int id) { 661 requestUpdate(); 662 } 663 664 /** 665 * Steps the animation forward and updates all the animated values. 666 * @param time The current time of the app in ms. 667 * @param jumpToEnd Whether to finish the animation. 668 * @return Whether the animation was finished. 669 */ onUpdateAnimation(long time, boolean jumpToEnd)670 protected boolean onUpdateAnimation(long time, boolean jumpToEnd) { 671 return true; 672 } 673 674 /** 675 * @return Whether or not there is an animation currently being driven by this {@link Layout}. 676 */ 677 @VisibleForTesting isLayoutAnimating()678 public boolean isLayoutAnimating() { 679 return false; 680 } 681 682 /** 683 * @return The {@link LayoutTab}s to be drawn. 684 */ getLayoutTabsToRender()685 public LayoutTab[] getLayoutTabsToRender() { 686 return mLayoutTabs; 687 } 688 689 /** 690 * @param id The id of the {@link LayoutTab} to search for. 691 * @return A {@link LayoutTab} represented by a {@link Tab} with an id of {@code id}. 692 */ getLayoutTab(int id)693 public LayoutTab getLayoutTab(int id) { 694 if (mLayoutTabs != null) { 695 for (int i = 0; i < mLayoutTabs.length; i++) { 696 if (mLayoutTabs[i].getId() == id) return mLayoutTabs[i]; 697 } 698 } 699 return null; 700 } 701 702 /** 703 * @return Whether the layout is handling the model updates when a tab is closing. 704 */ handlesTabClosing()705 public boolean handlesTabClosing() { 706 return false; 707 } 708 709 /** 710 * @return Whether the layout is handling the model updates when a tab is creating. 711 */ handlesTabCreating()712 public boolean handlesTabCreating() { 713 if (mLayoutTabs == null || mLayoutTabs.length != 1) return false; 714 return false; 715 } 716 717 /** 718 * @return Whether the layout is handling the model updates when closing all the tabs. 719 */ handlesCloseAll()720 public boolean handlesCloseAll() { 721 return false; 722 } 723 724 /** 725 * Whether or not the toolbar IncognitoToggleButton (if present) should be enabled. E.g., it can 726 * be disabled while animating a tab selection to avoid odd behavior. 727 */ shouldAllowIncognitoSwitching()728 public boolean shouldAllowIncognitoSwitching() { 729 return true; 730 } 731 732 /** 733 * @return True if the content decoration layer should be shown. 734 */ shouldDisplayContentOverlay()735 public boolean shouldDisplayContentOverlay() { 736 return false; 737 } 738 739 /** 740 * @return True if the host container can set itself as focusable e.g. for accessibility. 741 * Subclasses can override e.g. to provide a different default focused view. 742 */ canHostBeFocusable()743 public boolean canHostBeFocusable() { 744 return true; 745 } 746 747 /** 748 * @param e The {@link MotionEvent} to consider. 749 * @param offsets The current touch offsets that should be applied to the 750 * {@link EventFilter}s. 751 * @param isKeyboardShowing Whether or not the keyboard is showing. 752 * @return The {@link EventFilter} the {@link Layout} is listening to. 753 */ findInterceptingEventFilter( MotionEvent e, PointF offsets, boolean isKeyboardShowing)754 public EventFilter findInterceptingEventFilter( 755 MotionEvent e, PointF offsets, boolean isKeyboardShowing) { 756 EventFilter layoutEventFilter = getEventFilter(); 757 if (layoutEventFilter != null) { 758 if (offsets != null) { 759 layoutEventFilter.setCurrentMotionEventOffsets(offsets.x, offsets.y); 760 } 761 if (layoutEventFilter.onInterceptTouchEvent(e, isKeyboardShowing)) { 762 return layoutEventFilter; 763 } 764 } 765 return null; 766 } 767 768 /** 769 * Build a {@link SceneLayer} if it hasn't already been built, and update it and return it. 770 * 771 * @param viewport A viewport in which to display content in px. 772 * @param visibleViewport The visible section of the viewport in px. 773 * @param layerTitleCache A layer title cache. 774 * @param tabContentManager A tab content manager. 775 * @param resourceManager A resource manager. 776 * @param browserControls A browser controls state provider. 777 * @return A {@link SceneLayer} that represents the content for this 778 * {@link Layout}. 779 */ getUpdatedSceneLayer(RectF viewport, RectF visibleViewport, LayerTitleCache layerTitleCache, TabContentManager tabContentManager, ResourceManager resourceManager, BrowserControlsStateProvider browserControls)780 public final SceneLayer getUpdatedSceneLayer(RectF viewport, RectF visibleViewport, 781 LayerTitleCache layerTitleCache, TabContentManager tabContentManager, 782 ResourceManager resourceManager, BrowserControlsStateProvider browserControls) { 783 updateSceneLayer(viewport, visibleViewport, layerTitleCache, tabContentManager, 784 resourceManager, browserControls); 785 return getSceneLayer(); 786 } 787 788 /** 789 * @return Whether or not to force the browser controls Android view to hide. 790 */ forceHideBrowserControlsAndroidView()791 public boolean forceHideBrowserControlsAndroidView() { 792 return false; 793 } 794 795 /** 796 * @return Whether or not the layout should permanently show the browser controls. 797 */ forceShowBrowserControlsAndroidView()798 public boolean forceShowBrowserControlsAndroidView() { 799 return false; 800 } 801 802 /** 803 * @return The EventFilter to use for processing events for this Layout. 804 */ getEventFilter()805 protected abstract EventFilter getEventFilter(); 806 807 /** 808 * Get an instance of {@link SceneLayer}. Any class inheriting {@link Layout} 809 * should override this function in order for other functions to work. 810 * 811 * @return The scene layer for this {@link Layout}. 812 */ getSceneLayer()813 protected abstract SceneLayer getSceneLayer(); 814 815 /** 816 * Update {@link SceneLayer} instance this layout holds. Any class inheriting {@link Layout} 817 * should override this function in order for other functions to work. 818 */ updateSceneLayer(RectF viewport, RectF contentViewport, LayerTitleCache layerTitleCache, TabContentManager tabContentManager, ResourceManager resourceManager, BrowserControlsStateProvider browserControls)819 protected void updateSceneLayer(RectF viewport, RectF contentViewport, 820 LayerTitleCache layerTitleCache, TabContentManager tabContentManager, 821 ResourceManager resourceManager, BrowserControlsStateProvider browserControls) {} 822 823 /** 824 * @return The {@link LayoutType}. 825 */ 826 @LayoutType getLayoutType()827 public abstract int getLayoutType(); 828 } 829