Index: chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java |
index 4ebb19b2cec8fbeb2b56dcde994d586e5dcde005..609f8ea871e811e3df06efcf91b20d53ec50dacf 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java |
@@ -14,13 +14,18 @@ import org.chromium.base.ApplicationStatus; |
import org.chromium.base.ApplicationStatus.ActivityStateListener; |
import org.chromium.base.VisibleForTesting; |
import org.chromium.chrome.browser.ChromeActivity; |
+import org.chromium.chrome.browser.compositor.LayerTitleCache; |
import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager.PanelPriority; |
import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost; |
+import org.chromium.chrome.browser.compositor.layouts.components.VirtualView; |
import org.chromium.chrome.browser.compositor.layouts.eventfilter.EdgeSwipeEventFilter.ScrollDirection; |
import org.chromium.chrome.browser.compositor.layouts.eventfilter.EdgeSwipeHandler; |
import org.chromium.chrome.browser.compositor.layouts.eventfilter.EventFilter; |
+import org.chromium.chrome.browser.compositor.layouts.eventfilter.EventFilterHost; |
import org.chromium.chrome.browser.compositor.layouts.eventfilter.GestureHandler; |
-import org.chromium.chrome.browser.compositor.scene_layer.SceneLayer; |
+import org.chromium.chrome.browser.compositor.layouts.eventfilter.OverlayPanelEventFilter; |
+import org.chromium.chrome.browser.compositor.overlays.SceneOverlay; |
+import org.chromium.chrome.browser.compositor.scene_layer.SceneOverlayLayer; |
import org.chromium.chrome.browser.multiwindow.MultiWindowUtils; |
import org.chromium.chrome.browser.tab.Tab; |
import org.chromium.content.browser.ContentVideoViewEmbedder; |
@@ -30,21 +35,19 @@ import org.chromium.content_public.common.TopControlsState; |
import org.chromium.ui.base.LocalizationUtils; |
import org.chromium.ui.resources.ResourceManager; |
+import java.util.List; |
+ |
/** |
* Controls the Overlay Panel. |
*/ |
public class OverlayPanel extends OverlayPanelAnimation implements ActivityStateListener, |
- EdgeSwipeHandler, GestureHandler, OverlayPanelContentFactory { |
+ EdgeSwipeHandler, GestureHandler, OverlayPanelContentFactory, SceneOverlay { |
- /** |
- * The extra dp added around the close button touch target. |
- */ |
+ /** The extra dp added around the close button touch target. */ |
private static final int CLOSE_BUTTON_TOUCH_SLOP_DP = 5; |
- /** |
- * State of the Overlay Panel. |
- */ |
- public enum PanelState { |
+ /** State of the Overlay Panel. */ |
+ public static enum PanelState { |
// TODO(pedrosimonetti): consider removing the UNDEFINED state |
UNDEFINED, |
CLOSED, |
@@ -109,12 +112,15 @@ public class OverlayPanel extends OverlayPanelAnimation implements ActivityState |
/** Container for content the panel will show. */ |
private OverlayPanelContent mContent; |
- /** The {@link OverlayPanelHost} used to communicate with the supported layout. */ |
- private OverlayPanelHost mOverlayPanelHost; |
- |
/** OverlayPanel manager handle for notifications of opening and closing. */ |
protected OverlayPanelManager mPanelManager; |
+ /** If the base page focus has been cleared. */ |
+ private boolean mDidClearBasePageFocus; |
pedro (no code reviews)
2016/05/05 19:12:16
As I said in my previous comment, we don't control
mdjones
2016/05/05 20:46:02
That name doesn't suit what it is actually doing.
|
+ |
+ /** If the panel should be ignoring swipe events (for compatibility mode). */ |
+ private boolean mIgnoreSwipeEvents; |
+ |
// ============================================================================================ |
// Constructor |
// ============================================================================================ |
@@ -122,15 +128,17 @@ public class OverlayPanel extends OverlayPanelAnimation implements ActivityState |
/** |
* @param context The current Android {@link Context}. |
* @param updateHost The {@link LayoutUpdateHost} used to request updates in the Layout. |
+ * @param eventHost The {@link EventFilterHost} used to propagate events. |
* @param panelManager The {@link OverlayPanelManager} responsible for showing panels. |
*/ |
- public OverlayPanel(Context context, LayoutUpdateHost updateHost, |
+ public OverlayPanel(Context context, LayoutUpdateHost updateHost, EventFilterHost eventHost, |
OverlayPanelManager panelManager) { |
super(context, updateHost); |
mContentFactory = this; |
mPanelManager = panelManager; |
mPanelManager.registerPanel(this); |
+ mEventFilter = new OverlayPanelEventFilter(mContext, eventHost, this); |
} |
/** |
@@ -151,6 +159,7 @@ public class OverlayPanel extends OverlayPanelAnimation implements ActivityState |
@Override |
protected void onClosed(StateChangeReason reason) { |
+ focusBasePage(); |
destroyComponents(); |
mPanelManager.notifyPanelClosed(this, reason); |
} |
@@ -178,13 +187,6 @@ public class OverlayPanel extends OverlayPanelAnimation implements ActivityState |
if (!isShowing()) return; |
super.closePanel(reason, animate); |
- |
- // If the close action is animated, the Layout will be hidden when |
- // the animation is finished, so we should only hide the Layout |
- // here when not animating. |
- if (!animate && mOverlayPanelHost != null) { |
- mOverlayPanelHost.hideLayout(true); |
- } |
} |
/** |
@@ -285,6 +287,42 @@ public class OverlayPanel extends OverlayPanelAnimation implements ActivityState |
return -mActivity.getFullscreenManager().getControlOffset() * mPxToDp; |
} |
+ /** |
+ * Remove focus to the base page. |
+ */ |
+ protected void focusBasePage() { |
+ if (mActivity == null) return; |
+ ContentViewCore baseContentView = mActivity.getActivityTab().getContentViewCore(); |
+ |
+ // If the panel does not have focus or isn't open, return. |
+ if (!mDidClearBasePageFocus || isPanelOpened() || baseContentView == null) return; |
+ |
+ // Return focus to base page. |
+ mDidClearBasePageFocus = false; |
+ baseContentView.getContainerView().requestFocus(); |
+ baseContentView.updateTextSelectionUI(true); |
+ } |
+ |
+ /** |
+ * Clear focus from the base page. |
+ */ |
+ protected void clearBasePageFocus() { |
+ if (mActivity == null) return; |
+ ContentViewCore baseContentView = mActivity.getActivityTab().getContentViewCore(); |
+ ContentViewCore panelContentView = getContentViewCore(); |
+ |
+ // If content already has focus, return. |
+ if (mDidClearBasePageFocus || !isPanelOpened()) return; |
+ |
+ // Remove focus from the base page. |
+ baseContentView.preserveSelectionOnNextLossOfFocus(); |
+ baseContentView.updateTextSelectionUI(false); |
+ if (panelContentView != null) { |
+ mDidClearBasePageFocus = true; |
+ panelContentView.updateTextSelectionUI(true); |
+ } |
+ } |
+ |
// ============================================================================================ |
// ActivityStateListener |
// ============================================================================================ |
@@ -469,35 +507,20 @@ public class OverlayPanel extends OverlayPanelAnimation implements ActivityState |
} |
// ============================================================================================ |
- // Animation Handling |
+ // OverlayPanelBase methods. |
// ============================================================================================ |
@Override |
protected void onAnimationFinished() { |
super.onAnimationFinished(); |
- if (shouldHideOverlayPanelLayout()) { |
- if (mOverlayPanelHost != null) { |
- mOverlayPanelHost.hideLayout(false); |
- } |
+ if (getPanelState() == PanelState.PEEKED || getPanelState() == PanelState.CLOSED) { |
+ focusBasePage(); |
+ } else { |
+ clearBasePageFocus(); |
} |
} |
- /** |
- * Whether the Overlay Panel Layout should be hidden. |
- * |
- * @return Whether the Overlay Panel Layout should be hidden. |
- */ |
- private boolean shouldHideOverlayPanelLayout() { |
- final PanelState state = getPanelState(); |
- return (state == PanelState.PEEKED || state == PanelState.CLOSED) |
- && getHeight() == getPanelHeightFromState(state); |
- } |
- |
- // ============================================================================================ |
- // ContextualSearchPanelBase methods. |
- // ============================================================================================ |
- |
@Override |
protected int getControlContainerHeightResource() { |
// TODO(mdjones): Investigate passing this in to the constructor instead. |
@@ -510,35 +533,10 @@ public class OverlayPanel extends OverlayPanelAnimation implements ActivityState |
// ============================================================================================ |
/** |
- * Sets the {@link OverlayPanelHost} used to communicate with the supported layout. |
- * @param host The {@link OverlayPanelHost}. |
- */ |
- public void setHost(OverlayPanelHost host) { |
- mOverlayPanelHost = host; |
- } |
- |
- /** |
- * @return The scene layer used to draw this panel. |
- */ |
- public SceneLayer getSceneLayer() { |
- return null; |
- } |
- |
- /** |
- * Update this panel's scene layer. This should be implemented by each panel type. |
- * @param resourceManager Used to access static resources. |
+ * Updates the Panel so it preserves its state when the orientation changes. |
*/ |
- public void updateSceneLayer(ResourceManager resourceManager) { |
- } |
- |
- /** |
- * Determine if using a second layout for showing the overlay panel is possible. This should |
- * be overridden by each panel and returns true by default. |
- * @return True if the layout is supported. |
- * TODO(mdjones): Rename to supportsOverlayPanelLayout once the corresponding class is renamed. |
- */ |
- public boolean supportsContextualSearchLayout() { |
- return true; |
+ protected void updatePanelForOrientationChange() { |
+ resizePanelToState(getPanelState(), StateChangeReason.UNKNOWN); |
} |
// ============================================================================================ |
@@ -760,21 +758,31 @@ public class OverlayPanel extends OverlayPanelAnimation implements ActivityState |
@Override |
public void swipeStarted(ScrollDirection direction, float x, float y) { |
+ if (onInterceptBarSwipe()) { |
+ mIgnoreSwipeEvents = true; |
+ return; |
+ } |
handleSwipeStart(); |
} |
@Override |
public void swipeUpdated(float x, float y, float dx, float dy, float tx, float ty) { |
+ if (mIgnoreSwipeEvents) return; |
handleSwipeMove(ty); |
} |
@Override |
public void swipeFinished() { |
+ if (mIgnoreSwipeEvents) { |
+ mIgnoreSwipeEvents = false; |
+ return; |
+ } |
handleSwipeEnd(); |
} |
@Override |
public void swipeFlingOccurred(float x, float y, float tx, float ty, float vx, float vy) { |
+ if (mIgnoreSwipeEvents) return; |
handleFling(vy); |
} |
@@ -782,4 +790,103 @@ public class OverlayPanel extends OverlayPanelAnimation implements ActivityState |
public boolean isSwipeEnabled(ScrollDirection direction) { |
return direction == ScrollDirection.UP && isShowing(); |
} |
+ |
+ // ============================================================================================ |
+ // SceneOverlay implementation. |
+ // ============================================================================================ |
+ |
+ @Override |
+ public SceneOverlayLayer getUpdatedSceneOverlayTree(LayerTitleCache layerTitleCache, |
+ ResourceManager resourceManager, float yOffset) { |
+ return null; |
+ } |
+ |
+ @Override |
+ public EventFilter getEventFilter() { |
+ return mEventFilter; |
+ } |
+ |
+ @Override |
+ public void onSizeChanged(float width, float height, float visibleViewportOffsetY, |
+ int orientation) { |
+ onSizeChanged(width, height); |
+ } |
+ |
+ @Override |
+ public void getVirtualViews(List<VirtualView> views) { |
+ // TODO(mdjones): Add views for accessibility. |
+ } |
+ |
+ @Override |
+ public boolean handlesTabCreating() { |
+ // If the panel is not opened, do not handle tab creating. |
+ if (!isPanelOpened()) return false; |
+ // Updates TopControls' State so the Toolbar becomes visible. |
+ // TODO(pedrosimonetti): The transition when promoting to a new tab is only smooth |
+ // if the SearchContentView's vertical scroll position is zero. Otherwise the |
+ // ContentView will appear to jump in the screen. Coordinate with @dtrainor to solve |
+ // this problem. |
+ updateTopControlsState(TopControlsState.BOTH, false); |
+ return true; |
+ } |
+ |
+ @Override |
+ public boolean shouldHideAndroidTopControls() { |
+ return isPanelOpened(); |
+ } |
+ |
+ @Override |
+ public boolean updateOverlay(long time, long dt) { |
+ if (isPanelOpened()) clearBasePageFocus(); |
+ return super.onUpdateAnimation(time, false); |
+ } |
+ |
+ @Override |
+ public void onHideLayout() { |
+ if (!isShowing()) return; |
+ closePanel(StateChangeReason.UNKNOWN, false); |
+ } |
+ |
+ @Override |
+ public boolean onBackPressed() { |
+ if (!isPanelOpened()) return false; |
+ closePanel(StateChangeReason.BACK_PRESS, true); |
+ return true; |
+ } |
+ |
+ @Override |
+ public void tabTitleChanged(int tabId, String title) {} |
+ |
+ @Override |
+ public void tabStateInitialized() {} |
+ |
+ @Override |
+ public void tabModelSwitched(boolean incognito) {} |
+ |
+ @Override |
+ public void tabSelected(long time, boolean incognito, int id, int prevId) {} |
+ |
+ @Override |
+ public void tabMoved(long time, boolean incognito, int id, int oldIndex, int newIndex) {} |
+ |
+ @Override |
+ public void tabClosed(long time, boolean incognito, int id) {} |
+ |
+ @Override |
+ public void tabClosureCancelled(long time, boolean incognito, int id) {} |
+ |
+ @Override |
+ public void tabCreated(long time, boolean incognito, int id, int prevId, boolean selected) {} |
+ |
+ @Override |
+ public void tabPageLoadStarted(int id, boolean incognito) {} |
+ |
+ @Override |
+ public void tabPageLoadFinished(int id, boolean incognito) {} |
+ |
+ @Override |
+ public void tabLoadStarted(int id, boolean incognito) {} |
+ |
+ @Override |
+ public void tabLoadFinished(int id, boolean incognito) {} |
} |