Move DecorView out of PhoneWindow into its own class file.
Bug: 24810450
Change-Id: Ifa4e01517c80cec6d9a5b1051e5ccb7bab94a470
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
new file mode 100644
index 0000000..4f38ff3
--- /dev/null
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -0,0 +1,1632 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.policy;
+
+import com.android.internal.R;
+import com.android.internal.view.FloatingActionMode;
+import com.android.internal.view.RootViewSurfaceTaker;
+import com.android.internal.view.StandaloneActionMode;
+import com.android.internal.view.menu.ContextMenuBuilder;
+import com.android.internal.view.menu.MenuDialogHelper;
+import com.android.internal.view.menu.MenuPopupHelper;
+import com.android.internal.widget.ActionBarContextView;
+import com.android.internal.widget.BackgroundFallback;
+import com.android.internal.widget.FloatingToolbar;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.ActionMode;
+import android.view.ContextThemeWrapper;
+import android.view.Gravity;
+import android.view.InputQueue;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewStub;
+import android.view.ViewTreeObserver;
+import android.view.Window;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+import android.widget.FrameLayout;
+import android.widget.PopupWindow;
+
+import static android.view.View.MeasureSpec.AT_MOST;
+import static android.view.View.MeasureSpec.EXACTLY;
+import static android.view.View.MeasureSpec.getMode;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
+import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
+import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
+
+class DecorView extends FrameLayout implements RootViewSurfaceTaker {
+ private static final String TAG = "DecorView";
+
+ private static final boolean SWEEP_OPEN_MENU = false;
+
+ int mDefaultOpacity = PixelFormat.OPAQUE;
+
+ /** The feature ID of the panel, or -1 if this is the application's DecorView */
+ private final int mFeatureId;
+
+ private final Rect mDrawingBounds = new Rect();
+
+ private final Rect mBackgroundPadding = new Rect();
+
+ private final Rect mFramePadding = new Rect();
+
+ private final Rect mFrameOffsets = new Rect();
+
+ // True if a non client area decor exists.
+ private boolean mHasNonClientDecor = false;
+
+ private boolean mChanging;
+
+ private Drawable mMenuBackground;
+ private boolean mWatchingForMenu;
+ private int mDownY;
+
+ ActionMode mPrimaryActionMode;
+ private ActionMode mFloatingActionMode;
+ private ActionBarContextView mPrimaryActionModeView;
+ private PopupWindow mPrimaryActionModePopup;
+ private Runnable mShowPrimaryActionModePopup;
+ private ViewTreeObserver.OnPreDrawListener mFloatingToolbarPreDrawListener;
+ private View mFloatingActionModeOriginatingView;
+ private FloatingToolbar mFloatingToolbar;
+ private ObjectAnimator mFadeAnim;
+
+ // View added at runtime to draw under the status bar area
+ private View mStatusGuard;
+ // View added at runtime to draw under the navigation bar area
+ private View mNavigationGuard;
+
+ private final ColorViewState mStatusColorViewState = new ColorViewState(
+ SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS,
+ Gravity.TOP, Gravity.LEFT,
+ Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME,
+ com.android.internal.R.id.statusBarBackground,
+ FLAG_FULLSCREEN);
+ private final ColorViewState mNavigationColorViewState = new ColorViewState(
+ SYSTEM_UI_FLAG_HIDE_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION,
+ Gravity.BOTTOM, Gravity.RIGHT,
+ Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,
+ com.android.internal.R.id.navigationBarBackground,
+ 0 /* hideWindowFlag */);
+
+ private final Interpolator mShowInterpolator;
+ private final Interpolator mHideInterpolator;
+ private final int mBarEnterExitDuration;
+
+ private final BackgroundFallback mBackgroundFallback = new BackgroundFallback();
+
+ private int mLastTopInset = 0;
+ private int mLastBottomInset = 0;
+ private int mLastRightInset = 0;
+ private boolean mLastHasTopStableInset = false;
+ private boolean mLastHasBottomStableInset = false;
+ private boolean mLastHasRightStableInset = false;
+ private int mLastWindowFlags = 0;
+
+ private int mRootScrollY = 0;
+
+ private PhoneWindow mWindow;
+
+ ViewGroup mContentRoot;
+
+ private Rect mTempRect;
+ private Rect mOutsets = new Rect();
+
+ DecorView(Context context, int featureId, PhoneWindow window) {
+ super(context);
+ mFeatureId = featureId;
+
+ mShowInterpolator = AnimationUtils.loadInterpolator(context,
+ android.R.interpolator.linear_out_slow_in);
+ mHideInterpolator = AnimationUtils.loadInterpolator(context,
+ android.R.interpolator.fast_out_linear_in);
+
+ mBarEnterExitDuration = context.getResources().getInteger(
+ R.integer.dock_enter_exit_duration);
+
+ setWindow(window);
+ }
+
+ public void setBackgroundFallback(int resId) {
+ mBackgroundFallback.setDrawable(resId != 0 ? getContext().getDrawable(resId) : null);
+ setWillNotDraw(getBackground() == null && !mBackgroundFallback.hasFallback());
+ }
+
+ @Override
+ public void onDraw(Canvas c) {
+ super.onDraw(c);
+ mBackgroundFallback.draw(mContentRoot, c, mWindow.mContentParent);
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ final int keyCode = event.getKeyCode();
+ final int action = event.getAction();
+ final boolean isDown = action == KeyEvent.ACTION_DOWN;
+
+ if (isDown && (event.getRepeatCount() == 0)) {
+ // First handle chording of panel key: if a panel key is held
+ // but not released, try to execute a shortcut in it.
+ if ((mWindow.mPanelChordingKey > 0) && (mWindow.mPanelChordingKey != keyCode)) {
+ boolean handled = dispatchKeyShortcutEvent(event);
+ if (handled) {
+ return true;
+ }
+ }
+
+ // If a panel is open, perform a shortcut on it without the
+ // chorded panel key
+ if ((mWindow.mPreparedPanel != null) && mWindow.mPreparedPanel.isOpen) {
+ if (mWindow.performPanelShortcut(mWindow.mPreparedPanel, keyCode, event, 0)) {
+ return true;
+ }
+ }
+ }
+
+ if (!mWindow.isDestroyed()) {
+ final Window.Callback cb = mWindow.getCallback();
+ final boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event)
+ : super.dispatchKeyEvent(event);
+ if (handled) {
+ return true;
+ }
+ }
+
+ return isDown ? mWindow.onKeyDown(mFeatureId, event.getKeyCode(), event)
+ : mWindow.onKeyUp(mFeatureId, event.getKeyCode(), event);
+ }
+
+ @Override
+ public boolean dispatchKeyShortcutEvent(KeyEvent ev) {
+ // If the panel is already prepared, then perform the shortcut using it.
+ boolean handled;
+ if (mWindow.mPreparedPanel != null) {
+ handled = mWindow.performPanelShortcut(mWindow.mPreparedPanel, ev.getKeyCode(), ev,
+ Menu.FLAG_PERFORM_NO_CLOSE);
+ if (handled) {
+ if (mWindow.mPreparedPanel != null) {
+ mWindow.mPreparedPanel.isHandled = true;
+ }
+ return true;
+ }
+ }
+
+ // Shortcut not handled by the panel. Dispatch to the view hierarchy.
+ final Window.Callback cb = mWindow.getCallback();
+ handled = cb != null && !mWindow.isDestroyed() && mFeatureId < 0
+ ? cb.dispatchKeyShortcutEvent(ev) : super.dispatchKeyShortcutEvent(ev);
+ if (handled) {
+ return true;
+ }
+
+ // If the panel is not prepared, then we may be trying to handle a shortcut key
+ // combination such as Control+C. Temporarily prepare the panel then mark it
+ // unprepared again when finished to ensure that the panel will again be prepared
+ // the next time it is shown for real.
+ PhoneWindow.PanelFeatureState st =
+ mWindow.getPanelState(Window.FEATURE_OPTIONS_PANEL, false);
+ if (st != null && mWindow.mPreparedPanel == null) {
+ mWindow.preparePanel(st, ev);
+ handled = mWindow.performPanelShortcut(st, ev.getKeyCode(), ev,
+ Menu.FLAG_PERFORM_NO_CLOSE);
+ st.isPrepared = false;
+ if (handled) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ final Window.Callback cb = mWindow.getCallback();
+ return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
+ ? cb.dispatchTouchEvent(ev) : super.dispatchTouchEvent(ev);
+ }
+
+ @Override
+ public boolean dispatchTrackballEvent(MotionEvent ev) {
+ final Window.Callback cb = mWindow.getCallback();
+ return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
+ ? cb.dispatchTrackballEvent(ev) : super.dispatchTrackballEvent(ev);
+ }
+
+ @Override
+ public boolean dispatchGenericMotionEvent(MotionEvent ev) {
+ final Window.Callback cb = mWindow.getCallback();
+ return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
+ ? cb.dispatchGenericMotionEvent(ev) : super.dispatchGenericMotionEvent(ev);
+ }
+
+ public boolean superDispatchKeyEvent(KeyEvent event) {
+ // Give priority to closing action modes if applicable.
+ if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
+ final int action = event.getAction();
+ // Back cancels action modes first.
+ if (mPrimaryActionMode != null) {
+ if (action == KeyEvent.ACTION_UP) {
+ mPrimaryActionMode.finish();
+ }
+ return true;
+ }
+ }
+
+ return super.dispatchKeyEvent(event);
+ }
+
+ public boolean superDispatchKeyShortcutEvent(KeyEvent event) {
+ return super.dispatchKeyShortcutEvent(event);
+ }
+
+ public boolean superDispatchTouchEvent(MotionEvent event) {
+ return super.dispatchTouchEvent(event);
+ }
+
+ public boolean superDispatchTrackballEvent(MotionEvent event) {
+ return super.dispatchTrackballEvent(event);
+ }
+
+ public boolean superDispatchGenericMotionEvent(MotionEvent event) {
+ return super.dispatchGenericMotionEvent(event);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ return onInterceptTouchEvent(event);
+ }
+
+ private boolean isOutOfInnerBounds(int x, int y) {
+ return x < 0 || y < 0 || x > getWidth() || y > getHeight();
+ }
+
+ private boolean isOutOfBounds(int x, int y) {
+ return x < -5 || y < -5 || x > (getWidth() + 5)
+ || y > (getHeight() + 5);
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent event) {
+ int action = event.getAction();
+ if (mHasNonClientDecor && mWindow.mNonClientDecorView.mVisible) {
+ // Don't dispatch ACTION_DOWN to the non client decor if the window is
+ // resizable and the event was (starting) outside the window.
+ // Window resizing events should be handled by WindowManager.
+ // TODO: Investigate how to handle the outside touch in window manager
+ // without generating these events.
+ // Currently we receive these because we need to enlarge the window's
+ // touch region so that the monitor channel receives the events
+ // in the outside touch area.
+ if (action == MotionEvent.ACTION_DOWN) {
+ final int x = (int) event.getX();
+ final int y = (int) event.getY();
+ if (isOutOfInnerBounds(x, y)) {
+ return true;
+ }
+ }
+ }
+
+ if (mFeatureId >= 0) {
+ if (action == MotionEvent.ACTION_DOWN) {
+ int x = (int)event.getX();
+ int y = (int)event.getY();
+ if (isOutOfBounds(x, y)) {
+ mWindow.closePanel(mFeatureId);
+ return true;
+ }
+ }
+ }
+
+ if (!SWEEP_OPEN_MENU) {
+ return false;
+ }
+
+ if (mFeatureId >= 0) {
+ if (action == MotionEvent.ACTION_DOWN) {
+ Log.i(TAG, "Watchiing!");
+ mWatchingForMenu = true;
+ mDownY = (int) event.getY();
+ return false;
+ }
+
+ if (!mWatchingForMenu) {
+ return false;
+ }
+
+ int y = (int)event.getY();
+ if (action == MotionEvent.ACTION_MOVE) {
+ if (y > (mDownY+30)) {
+ Log.i(TAG, "Closing!");
+ mWindow.closePanel(mFeatureId);
+ mWatchingForMenu = false;
+ return true;
+ }
+ } else if (action == MotionEvent.ACTION_UP) {
+ mWatchingForMenu = false;
+ }
+
+ return false;
+ }
+
+ //Log.i(TAG, "Intercept: action=" + action + " y=" + event.getY()
+ // + " (in " + getHeight() + ")");
+
+ if (action == MotionEvent.ACTION_DOWN) {
+ int y = (int)event.getY();
+ if (y >= (getHeight()-5) && !mWindow.hasChildren()) {
+ Log.i(TAG, "Watching!");
+ mWatchingForMenu = true;
+ }
+ return false;
+ }
+
+ if (!mWatchingForMenu) {
+ return false;
+ }
+
+ int y = (int)event.getY();
+ if (action == MotionEvent.ACTION_MOVE) {
+ if (y < (getHeight()-30)) {
+ Log.i(TAG, "Opening!");
+ mWindow.openPanel(Window.FEATURE_OPTIONS_PANEL, new KeyEvent(
+ KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU));
+ mWatchingForMenu = false;
+ return true;
+ }
+ } else if (action == MotionEvent.ACTION_UP) {
+ mWatchingForMenu = false;
+ }
+
+ return false;
+ }
+
+ @Override
+ public void sendAccessibilityEvent(int eventType) {
+ if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
+ return;
+ }
+
+ // if we are showing a feature that should be announced and one child
+ // make this child the event source since this is the feature itself
+ // otherwise the callback will take over and announce its client
+ if ((mFeatureId == Window.FEATURE_OPTIONS_PANEL ||
+ mFeatureId == Window.FEATURE_CONTEXT_MENU ||
+ mFeatureId == Window.FEATURE_PROGRESS ||
+ mFeatureId == Window.FEATURE_INDETERMINATE_PROGRESS)
+ && getChildCount() == 1) {
+ getChildAt(0).sendAccessibilityEvent(eventType);
+ } else {
+ super.sendAccessibilityEvent(eventType);
+ }
+ }
+
+ @Override
+ public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
+ final Window.Callback cb = mWindow.getCallback();
+ if (cb != null && !mWindow.isDestroyed()) {
+ if (cb.dispatchPopulateAccessibilityEvent(event)) {
+ return true;
+ }
+ }
+ return super.dispatchPopulateAccessibilityEventInternal(event);
+ }
+
+ @Override
+ protected boolean setFrame(int l, int t, int r, int b) {
+ boolean changed = super.setFrame(l, t, r, b);
+ if (changed) {
+ final Rect drawingBounds = mDrawingBounds;
+ getDrawingRect(drawingBounds);
+
+ Drawable fg = getForeground();
+ if (fg != null) {
+ final Rect frameOffsets = mFrameOffsets;
+ drawingBounds.left += frameOffsets.left;
+ drawingBounds.top += frameOffsets.top;
+ drawingBounds.right -= frameOffsets.right;
+ drawingBounds.bottom -= frameOffsets.bottom;
+ fg.setBounds(drawingBounds);
+ final Rect framePadding = mFramePadding;
+ drawingBounds.left += framePadding.left - frameOffsets.left;
+ drawingBounds.top += framePadding.top - frameOffsets.top;
+ drawingBounds.right -= framePadding.right - frameOffsets.right;
+ drawingBounds.bottom -= framePadding.bottom - frameOffsets.bottom;
+ }
+
+ Drawable bg = getBackground();
+ if (bg != null) {
+ bg.setBounds(drawingBounds);
+ }
+
+ if (SWEEP_OPEN_MENU) {
+ if (mMenuBackground == null && mFeatureId < 0
+ && mWindow.getAttributes().height
+ == WindowManager.LayoutParams.MATCH_PARENT) {
+ mMenuBackground = getContext().getDrawable(
+ R.drawable.menu_background);
+ }
+ if (mMenuBackground != null) {
+ mMenuBackground.setBounds(drawingBounds.left,
+ drawingBounds.bottom-6, drawingBounds.right,
+ drawingBounds.bottom+20);
+ }
+ }
+ }
+ return changed;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
+ final boolean isPortrait = metrics.widthPixels < metrics.heightPixels;
+
+ final int widthMode = getMode(widthMeasureSpec);
+ final int heightMode = getMode(heightMeasureSpec);
+
+ boolean fixedWidth = false;
+ if (widthMode == AT_MOST) {
+ final TypedValue tvw = isPortrait ? mWindow.mFixedWidthMinor
+ : mWindow.mFixedWidthMajor;
+ if (tvw != null && tvw.type != TypedValue.TYPE_NULL) {
+ final int w;
+ if (tvw.type == TypedValue.TYPE_DIMENSION) {
+ w = (int) tvw.getDimension(metrics);
+ } else if (tvw.type == TypedValue.TYPE_FRACTION) {
+ w = (int) tvw.getFraction(metrics.widthPixels, metrics.widthPixels);
+ } else {
+ w = 0;
+ }
+
+ if (w > 0) {
+ final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+ widthMeasureSpec = MeasureSpec.makeMeasureSpec(
+ Math.min(w, widthSize), EXACTLY);
+ fixedWidth = true;
+ }
+ }
+ }
+
+ if (heightMode == AT_MOST) {
+ final TypedValue tvh = isPortrait ? mWindow.mFixedHeightMajor
+ : mWindow.mFixedHeightMinor;
+ if (tvh != null && tvh.type != TypedValue.TYPE_NULL) {
+ final int h;
+ if (tvh.type == TypedValue.TYPE_DIMENSION) {
+ h = (int) tvh.getDimension(metrics);
+ } else if (tvh.type == TypedValue.TYPE_FRACTION) {
+ h = (int) tvh.getFraction(metrics.heightPixels, metrics.heightPixels);
+ } else {
+ h = 0;
+ }
+ if (h > 0) {
+ final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+ heightMeasureSpec = MeasureSpec.makeMeasureSpec(
+ Math.min(h, heightSize), EXACTLY);
+ }
+ }
+ }
+
+ getOutsets(mOutsets);
+ if (mOutsets.top > 0 || mOutsets.bottom > 0) {
+ int mode = MeasureSpec.getMode(heightMeasureSpec);
+ if (mode != MeasureSpec.UNSPECIFIED) {
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+ heightMeasureSpec = MeasureSpec.makeMeasureSpec(
+ height + mOutsets.top + mOutsets.bottom, mode);
+ }
+ }
+ if (mOutsets.left > 0 || mOutsets.right > 0) {
+ int mode = MeasureSpec.getMode(widthMeasureSpec);
+ if (mode != MeasureSpec.UNSPECIFIED) {
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ widthMeasureSpec = MeasureSpec.makeMeasureSpec(
+ width + mOutsets.left + mOutsets.right, mode);
+ }
+ }
+
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ int width = getMeasuredWidth();
+ boolean measure = false;
+
+ widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, EXACTLY);
+
+ if (!fixedWidth && widthMode == AT_MOST) {
+ final TypedValue tv = isPortrait ? mWindow.mMinWidthMinor : mWindow.mMinWidthMajor;
+ if (tv.type != TypedValue.TYPE_NULL) {
+ final int min;
+ if (tv.type == TypedValue.TYPE_DIMENSION) {
+ min = (int)tv.getDimension(metrics);
+ } else if (tv.type == TypedValue.TYPE_FRACTION) {
+ min = (int)tv.getFraction(metrics.widthPixels, metrics.widthPixels);
+ } else {
+ min = 0;
+ }
+
+ if (width < min) {
+ widthMeasureSpec = MeasureSpec.makeMeasureSpec(min, EXACTLY);
+ measure = true;
+ }
+ }
+ }
+
+ // TODO: Support height?
+
+ if (measure) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ getOutsets(mOutsets);
+ if (mOutsets.left > 0) {
+ offsetLeftAndRight(-mOutsets.left);
+ }
+ if (mOutsets.top > 0) {
+ offsetTopAndBottom(-mOutsets.top);
+ }
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ super.draw(canvas);
+
+ if (mMenuBackground != null) {
+ mMenuBackground.draw(canvas);
+ }
+ }
+
+ @Override
+ public boolean showContextMenuForChild(View originalView) {
+ // Reuse the context menu builder
+ if (mWindow.mContextMenu == null) {
+ mWindow.mContextMenu = new ContextMenuBuilder(getContext());
+ mWindow.mContextMenu.setCallback(mWindow.mContextMenuCallback);
+ } else {
+ mWindow.mContextMenu.clearAll();
+ }
+
+ final MenuDialogHelper helper = mWindow.mContextMenu.show(originalView,
+ originalView.getWindowToken());
+ if (helper != null) {
+ helper.setPresenterCallback(mWindow.mContextMenuCallback);
+ } else if (mWindow.mContextMenuHelper != null) {
+ // No menu to show, but if we have a menu currently showing it just became blank.
+ // Close it.
+ mWindow.mContextMenuHelper.dismiss();
+ }
+ mWindow.mContextMenuHelper = helper;
+ return helper != null;
+ }
+
+ @Override
+ public boolean showContextMenuForChild(View originalView, float x, float y) {
+ // Reuse the context menu builder
+ if (mWindow.mContextMenu == null) {
+ mWindow.mContextMenu = new ContextMenuBuilder(getContext());
+ mWindow.mContextMenu.setCallback(mWindow.mContextMenuCallback);
+ } else {
+ mWindow.mContextMenu.clearAll();
+ }
+
+ final MenuPopupHelper helper = mWindow.mContextMenu.showPopup(
+ getContext(), originalView, x, y);
+ if (helper != null) {
+ helper.setCallback(mWindow.mContextMenuCallback);
+ } else if (mWindow.mContextMenuPopupHelper != null) {
+ // No menu to show, but if we have a menu currently showing it just became blank.
+ // Close it.
+ mWindow.mContextMenuPopupHelper.dismiss();
+ }
+ mWindow.mContextMenuPopupHelper = helper;
+ return helper != null;
+ }
+
+ @Override
+ public ActionMode startActionModeForChild(View originalView,
+ ActionMode.Callback callback) {
+ return startActionModeForChild(originalView, callback, ActionMode.TYPE_PRIMARY);
+ }
+
+ @Override
+ public ActionMode startActionModeForChild(
+ View child, ActionMode.Callback callback, int type) {
+ return startActionMode(child, callback, type);
+ }
+
+ @Override
+ public ActionMode startActionMode(ActionMode.Callback callback) {
+ return startActionMode(callback, ActionMode.TYPE_PRIMARY);
+ }
+
+ @Override
+ public ActionMode startActionMode(ActionMode.Callback callback, int type) {
+ return startActionMode(this, callback, type);
+ }
+
+ private ActionMode startActionMode(
+ View originatingView, ActionMode.Callback callback, int type) {
+ ActionMode.Callback2 wrappedCallback = new ActionModeCallback2Wrapper(callback);
+ ActionMode mode = null;
+ if (mWindow.getCallback() != null && !mWindow.isDestroyed()) {
+ try {
+ mode = mWindow.getCallback().onWindowStartingActionMode(wrappedCallback, type);
+ } catch (AbstractMethodError ame) {
+ // Older apps might not implement the typed version of this method.
+ if (type == ActionMode.TYPE_PRIMARY) {
+ try {
+ mode = mWindow.getCallback().onWindowStartingActionMode(
+ wrappedCallback);
+ } catch (AbstractMethodError ame2) {
+ // Older apps might not implement this callback method at all.
+ }
+ }
+ }
+ }
+ if (mode != null) {
+ if (mode.getType() == ActionMode.TYPE_PRIMARY) {
+ cleanupPrimaryActionMode();
+ mPrimaryActionMode = mode;
+ } else if (mode.getType() == ActionMode.TYPE_FLOATING) {
+ if (mFloatingActionMode != null) {
+ mFloatingActionMode.finish();
+ }
+ mFloatingActionMode = mode;
+ }
+ } else {
+ mode = createActionMode(type, wrappedCallback, originatingView);
+ if (mode != null && wrappedCallback.onCreateActionMode(mode, mode.getMenu())) {
+ setHandledActionMode(mode);
+ } else {
+ mode = null;
+ }
+ }
+ if (mode != null && mWindow.getCallback() != null && !mWindow.isDestroyed()) {
+ try {
+ mWindow.getCallback().onActionModeStarted(mode);
+ } catch (AbstractMethodError ame) {
+ // Older apps might not implement this callback method.
+ }
+ }
+ return mode;
+ }
+
+ private void cleanupPrimaryActionMode() {
+ if (mPrimaryActionMode != null) {
+ mPrimaryActionMode.finish();
+ mPrimaryActionMode = null;
+ }
+ if (mPrimaryActionModeView != null) {
+ mPrimaryActionModeView.killMode();
+ }
+ }
+
+ private void cleanupFloatingActionModeViews() {
+ if (mFloatingToolbar != null) {
+ mFloatingToolbar.dismiss();
+ mFloatingToolbar = null;
+ }
+ if (mFloatingActionModeOriginatingView != null) {
+ if (mFloatingToolbarPreDrawListener != null) {
+ mFloatingActionModeOriginatingView.getViewTreeObserver()
+ .removeOnPreDrawListener(mFloatingToolbarPreDrawListener);
+ mFloatingToolbarPreDrawListener = null;
+ }
+ mFloatingActionModeOriginatingView = null;
+ }
+ }
+
+ public void startChanging() {
+ mChanging = true;
+ }
+
+ public void finishChanging() {
+ mChanging = false;
+ drawableChanged();
+ }
+
+ public void setWindowBackground(Drawable drawable) {
+ if (getBackground() != drawable) {
+ setBackgroundDrawable(drawable);
+ if (drawable != null) {
+ drawable.getPadding(mBackgroundPadding);
+ } else {
+ mBackgroundPadding.setEmpty();
+ }
+ drawableChanged();
+ }
+ }
+
+ public void setWindowFrame(Drawable drawable) {
+ if (getForeground() != drawable) {
+ setForeground(drawable);
+ if (drawable != null) {
+ drawable.getPadding(mFramePadding);
+ } else {
+ mFramePadding.setEmpty();
+ }
+ drawableChanged();
+ }
+ }
+
+ @Override
+ public void onWindowSystemUiVisibilityChanged(int visible) {
+ updateColorViews(null /* insets */, true /* animate */);
+ }
+
+ @Override
+ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ mFrameOffsets.set(insets.getSystemWindowInsets());
+ insets = updateColorViews(insets, true /* animate */);
+ insets = updateStatusGuard(insets);
+ updateNavigationGuard(insets);
+ if (getForeground() != null) {
+ drawableChanged();
+ }
+ return insets;
+ }
+
+ @Override
+ public boolean isTransitionGroup() {
+ return false;
+ }
+
+ WindowInsets updateColorViews(WindowInsets insets, boolean animate) {
+ WindowManager.LayoutParams attrs = mWindow.getAttributes();
+ int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility();
+
+ if (!mWindow.mIsFloating && ActivityManager.isHighEndGfx()) {
+ boolean disallowAnimate = !isLaidOut();
+ disallowAnimate |= ((mLastWindowFlags ^ attrs.flags)
+ & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
+ mLastWindowFlags = attrs.flags;
+
+ if (insets != null) {
+ mLastTopInset = Math.min(insets.getStableInsetTop(),
+ insets.getSystemWindowInsetTop());
+ mLastBottomInset = Math.min(insets.getStableInsetBottom(),
+ insets.getSystemWindowInsetBottom());
+ mLastRightInset = Math.min(insets.getStableInsetRight(),
+ insets.getSystemWindowInsetRight());
+
+ // Don't animate if the presence of stable insets has changed, because that
+ // indicates that the window was either just added and received them for the
+ // first time, or the window size or position has changed.
+ boolean hasTopStableInset = insets.getStableInsetTop() != 0;
+ disallowAnimate |= (hasTopStableInset != mLastHasTopStableInset);
+ mLastHasTopStableInset = hasTopStableInset;
+
+ boolean hasBottomStableInset = insets.getStableInsetBottom() != 0;
+ disallowAnimate |= (hasBottomStableInset != mLastHasBottomStableInset);
+ mLastHasBottomStableInset = hasBottomStableInset;
+
+ boolean hasRightStableInset = insets.getStableInsetRight() != 0;
+ disallowAnimate |= (hasRightStableInset != mLastHasRightStableInset);
+ mLastHasRightStableInset = hasRightStableInset;
+ }
+
+ boolean navBarToRightEdge = mLastBottomInset == 0 && mLastRightInset > 0;
+ int navBarSize = navBarToRightEdge ? mLastRightInset : mLastBottomInset;
+ updateColorViewInt(mNavigationColorViewState, sysUiVisibility,
+ mWindow.mNavigationBarColor, navBarSize, navBarToRightEdge,
+ 0 /* rightInset */, animate && !disallowAnimate);
+
+ boolean statusBarNeedsRightInset = navBarToRightEdge
+ && mNavigationColorViewState.present;
+ int statusBarRightInset = statusBarNeedsRightInset ? mLastRightInset : 0;
+ updateColorViewInt(mStatusColorViewState, sysUiVisibility, mWindow.mStatusBarColor,
+ mLastTopInset, false /* matchVertical */, statusBarRightInset,
+ animate && !disallowAnimate);
+ }
+
+ // When we expand the window with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, we still need
+ // to ensure that the rest of the view hierarchy doesn't notice it, unless they've
+ // explicitly asked for it.
+
+ boolean consumingNavBar =
+ (attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
+ && (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0
+ && (sysUiVisibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
+
+ int consumedRight = consumingNavBar ? mLastRightInset : 0;
+ int consumedBottom = consumingNavBar ? mLastBottomInset : 0;
+
+ if (mContentRoot != null
+ && mContentRoot.getLayoutParams() instanceof MarginLayoutParams) {
+ MarginLayoutParams lp = (MarginLayoutParams) mContentRoot.getLayoutParams();
+ if (lp.rightMargin != consumedRight || lp.bottomMargin != consumedBottom) {
+ lp.rightMargin = consumedRight;
+ lp.bottomMargin = consumedBottom;
+ mContentRoot.setLayoutParams(lp);
+
+ if (insets == null) {
+ // The insets have changed, but we're not currently in the process
+ // of dispatching them.
+ requestApplyInsets();
+ }
+ }
+ if (insets != null) {
+ insets = insets.replaceSystemWindowInsets(
+ insets.getSystemWindowInsetLeft(),
+ insets.getSystemWindowInsetTop(),
+ insets.getSystemWindowInsetRight() - consumedRight,
+ insets.getSystemWindowInsetBottom() - consumedBottom);
+ }
+ }
+
+ if (insets != null) {
+ insets = insets.consumeStableInsets();
+ }
+ return insets;
+ }
+
+ /**
+ * Update a color view
+ *
+ * @param state the color view to update.
+ * @param sysUiVis the current systemUiVisibility to apply.
+ * @param color the current color to apply.
+ * @param size the current size in the non-parent-matching dimension.
+ * @param verticalBar if true the view is attached to a vertical edge, otherwise to a
+ * horizontal edge,
+ * @param rightMargin rightMargin for the color view.
+ * @param animate if true, the change will be animated.
+ */
+ private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color,
+ int size, boolean verticalBar, int rightMargin, boolean animate) {
+ state.present = size > 0 && (sysUiVis & state.systemUiHideFlag) == 0
+ && (mWindow.getAttributes().flags & state.hideWindowFlag) == 0
+ && (mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
+ boolean show = state.present
+ && (color & Color.BLACK) != 0
+ && (mWindow.getAttributes().flags & state.translucentFlag) == 0;
+
+ boolean visibilityChanged = false;
+ View view = state.view;
+
+ int resolvedHeight = verticalBar ? LayoutParams.MATCH_PARENT : size;
+ int resolvedWidth = verticalBar ? size : LayoutParams.MATCH_PARENT;
+ int resolvedGravity = verticalBar ? state.horizontalGravity : state.verticalGravity;
+
+ if (view == null) {
+ if (show) {
+ state.view = view = new View(mContext);
+ view.setBackgroundColor(color);
+ view.setTransitionName(state.transitionName);
+ view.setId(state.id);
+ visibilityChanged = true;
+ view.setVisibility(INVISIBLE);
+ state.targetVisibility = VISIBLE;
+
+ LayoutParams lp = new LayoutParams(resolvedWidth, resolvedHeight,
+ resolvedGravity);
+ lp.rightMargin = rightMargin;
+ addView(view, lp);
+ updateColorViewTranslations();
+ }
+ } else {
+ int vis = show ? VISIBLE : INVISIBLE;
+ visibilityChanged = state.targetVisibility != vis;
+ state.targetVisibility = vis;
+ LayoutParams lp = (LayoutParams) view.getLayoutParams();
+ if (lp.height != resolvedHeight || lp.width != resolvedWidth
+ || lp.gravity != resolvedGravity || lp.rightMargin != rightMargin) {
+ lp.height = resolvedHeight;
+ lp.width = resolvedWidth;
+ lp.gravity = resolvedGravity;
+ lp.rightMargin = rightMargin;
+ view.setLayoutParams(lp);
+ }
+ if (show) {
+ view.setBackgroundColor(color);
+ }
+ }
+ if (visibilityChanged) {
+ view.animate().cancel();
+ if (animate) {
+ if (show) {
+ if (view.getVisibility() != VISIBLE) {
+ view.setVisibility(VISIBLE);
+ view.setAlpha(0.0f);
+ }
+ view.animate().alpha(1.0f).setInterpolator(mShowInterpolator).
+ setDuration(mBarEnterExitDuration);
+ } else {
+ view.animate().alpha(0.0f).setInterpolator(mHideInterpolator)
+ .setDuration(mBarEnterExitDuration)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ state.view.setAlpha(1.0f);
+ state.view.setVisibility(INVISIBLE);
+ }
+ });
+ }
+ } else {
+ view.setAlpha(1.0f);
+ view.setVisibility(show ? VISIBLE : INVISIBLE);
+ }
+ }
+ }
+
+ private void updateColorViewTranslations() {
+ // Put the color views back in place when they get moved off the screen
+ // due to the the ViewRootImpl panning.
+ int rootScrollY = mRootScrollY;
+ if (mStatusColorViewState.view != null) {
+ mStatusColorViewState.view.setTranslationY(rootScrollY > 0 ? rootScrollY : 0);
+ }
+ if (mNavigationColorViewState.view != null) {
+ mNavigationColorViewState.view.setTranslationY(rootScrollY < 0 ? rootScrollY : 0);
+ }
+ }
+
+ private WindowInsets updateStatusGuard(WindowInsets insets) {
+ boolean showStatusGuard = false;
+ // Show the status guard when the non-overlay contextual action bar is showing
+ if (mPrimaryActionModeView != null) {
+ if (mPrimaryActionModeView.getLayoutParams() instanceof MarginLayoutParams) {
+ // Insets are magic!
+ final MarginLayoutParams mlp = (MarginLayoutParams)
+ mPrimaryActionModeView.getLayoutParams();
+ boolean mlpChanged = false;
+ if (mPrimaryActionModeView.isShown()) {
+ if (mTempRect == null) {
+ mTempRect = new Rect();
+ }
+ final Rect rect = mTempRect;
+
+ // If the parent doesn't consume the insets, manually
+ // apply the default system window insets.
+ mWindow.mContentParent.computeSystemWindowInsets(insets, rect);
+ final int newMargin = rect.top == 0 ? insets.getSystemWindowInsetTop() : 0;
+ if (mlp.topMargin != newMargin) {
+ mlpChanged = true;
+ mlp.topMargin = insets.getSystemWindowInsetTop();
+
+ if (mStatusGuard == null) {
+ mStatusGuard = new View(mContext);
+ mStatusGuard.setBackgroundColor(mContext.getColor(
+ R.color.input_method_navigation_guard));
+ addView(mStatusGuard, indexOfChild(mStatusColorViewState.view),
+ new LayoutParams(LayoutParams.MATCH_PARENT,
+ mlp.topMargin, Gravity.START | Gravity.TOP));
+ } else {
+ final LayoutParams lp = (LayoutParams)
+ mStatusGuard.getLayoutParams();
+ if (lp.height != mlp.topMargin) {
+ lp.height = mlp.topMargin;
+ mStatusGuard.setLayoutParams(lp);
+ }
+ }
+ }
+
+ // The action mode's theme may differ from the app, so
+ // always show the status guard above it if we have one.
+ showStatusGuard = mStatusGuard != null;
+
+ // We only need to consume the insets if the action
+ // mode is overlaid on the app content (e.g. it's
+ // sitting in a FrameLayout, see
+ // screen_simple_overlay_action_mode.xml).
+ final boolean nonOverlay = (mWindow.getLocalFeaturesPrivate()
+ & (1 << Window.FEATURE_ACTION_MODE_OVERLAY)) == 0;
+ insets = insets.consumeSystemWindowInsets(
+ false, nonOverlay && showStatusGuard /* top */, false, false);
+ } else {
+ // reset top margin
+ if (mlp.topMargin != 0) {
+ mlpChanged = true;
+ mlp.topMargin = 0;
+ }
+ }
+ if (mlpChanged) {
+ mPrimaryActionModeView.setLayoutParams(mlp);
+ }
+ }
+ }
+ if (mStatusGuard != null) {
+ mStatusGuard.setVisibility(showStatusGuard ? View.VISIBLE : View.GONE);
+ }
+ return insets;
+ }
+
+ private void updateNavigationGuard(WindowInsets insets) {
+ // IMEs lay out below the nav bar, but the content view must not (for back compat)
+ if (mWindow.getAttributes().type == WindowManager.LayoutParams.TYPE_INPUT_METHOD) {
+ // prevent the content view from including the nav bar height
+ if (mWindow.mContentParent != null) {
+ if (mWindow.mContentParent.getLayoutParams() instanceof MarginLayoutParams) {
+ MarginLayoutParams mlp =
+ (MarginLayoutParams) mWindow.mContentParent.getLayoutParams();
+ mlp.bottomMargin = insets.getSystemWindowInsetBottom();
+ mWindow.mContentParent.setLayoutParams(mlp);
+ }
+ }
+ // position the navigation guard view, creating it if necessary
+ if (mNavigationGuard == null) {
+ mNavigationGuard = new View(mContext);
+ mNavigationGuard.setBackgroundColor(mContext.getColor(
+ R.color.input_method_navigation_guard));
+ addView(mNavigationGuard, indexOfChild(mNavigationColorViewState.view),
+ new LayoutParams(LayoutParams.MATCH_PARENT,
+ insets.getSystemWindowInsetBottom(),
+ Gravity.START | Gravity.BOTTOM));
+ } else {
+ LayoutParams lp = (LayoutParams) mNavigationGuard.getLayoutParams();
+ lp.height = insets.getSystemWindowInsetBottom();
+ mNavigationGuard.setLayoutParams(lp);
+ }
+ }
+ }
+
+ private void drawableChanged() {
+ if (mChanging) {
+ return;
+ }
+
+ setPadding(mFramePadding.left + mBackgroundPadding.left,
+ mFramePadding.top + mBackgroundPadding.top,
+ mFramePadding.right + mBackgroundPadding.right,
+ mFramePadding.bottom + mBackgroundPadding.bottom);
+ requestLayout();
+ invalidate();
+
+ int opacity = PixelFormat.OPAQUE;
+ if (windowHasShadow()) {
+ // If the window has a shadow, it must be translucent.
+ opacity = PixelFormat.TRANSLUCENT;
+ } else{
+ // Note: If there is no background, we will assume opaque. The
+ // common case seems to be that an application sets there to be
+ // no background so it can draw everything itself. For that,
+ // we would like to assume OPAQUE and let the app force it to
+ // the slower TRANSLUCENT mode if that is really what it wants.
+ Drawable bg = getBackground();
+ Drawable fg = getForeground();
+ if (bg != null) {
+ if (fg == null) {
+ opacity = bg.getOpacity();
+ } else if (mFramePadding.left <= 0 && mFramePadding.top <= 0
+ && mFramePadding.right <= 0 && mFramePadding.bottom <= 0) {
+ // If the frame padding is zero, then we can be opaque
+ // if either the frame -or- the background is opaque.
+ int fop = fg.getOpacity();
+ int bop = bg.getOpacity();
+ if (false)
+ Log.v(TAG, "Background opacity: " + bop + ", Frame opacity: " + fop);
+ if (fop == PixelFormat.OPAQUE || bop == PixelFormat.OPAQUE) {
+ opacity = PixelFormat.OPAQUE;
+ } else if (fop == PixelFormat.UNKNOWN) {
+ opacity = bop;
+ } else if (bop == PixelFormat.UNKNOWN) {
+ opacity = fop;
+ } else {
+ opacity = Drawable.resolveOpacity(fop, bop);
+ }
+ } else {
+ // For now we have to assume translucent if there is a
+ // frame with padding... there is no way to tell if the
+ // frame and background together will draw all pixels.
+ if (false)
+ Log.v(TAG, "Padding: " + mFramePadding);
+ opacity = PixelFormat.TRANSLUCENT;
+ }
+ }
+ if (false)
+ Log.v(TAG, "Background: " + bg + ", Frame: " + fg);
+ }
+
+ if (false)
+ Log.v(TAG, "Selected default opacity: " + opacity);
+
+ mDefaultOpacity = opacity;
+ if (mFeatureId < 0) {
+ mWindow.setDefaultWindowFormat(opacity);
+ }
+ }
+
+ @Override
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ super.onWindowFocusChanged(hasWindowFocus);
+
+ // If the user is chording a menu shortcut, release the chord since
+ // this window lost focus
+ if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL) && !hasWindowFocus
+ && mWindow.mPanelChordingKey != 0) {
+ mWindow.closePanel(Window.FEATURE_OPTIONS_PANEL);
+ }
+
+ final Window.Callback cb = mWindow.getCallback();
+ if (cb != null && !mWindow.isDestroyed() && mFeatureId < 0) {
+ cb.onWindowFocusChanged(hasWindowFocus);
+ }
+
+ if (mPrimaryActionMode != null) {
+ mPrimaryActionMode.onWindowFocusChanged(hasWindowFocus);
+ }
+ if (mFloatingActionMode != null) {
+ mFloatingActionMode.onWindowFocusChanged(hasWindowFocus);
+ }
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ final Window.Callback cb = mWindow.getCallback();
+ if (cb != null && !mWindow.isDestroyed() && mFeatureId < 0) {
+ cb.onAttachedToWindow();
+ }
+
+ if (mFeatureId == -1) {
+ /*
+ * The main window has been attached, try to restore any panels
+ * that may have been open before. This is called in cases where
+ * an activity is being killed for configuration change and the
+ * menu was open. When the activity is recreated, the menu
+ * should be shown again.
+ */
+ mWindow.openPanelsAfterRestore();
+ }
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+
+ final Window.Callback cb = mWindow.getCallback();
+ if (cb != null && mFeatureId < 0) {
+ cb.onDetachedFromWindow();
+ }
+
+ if (mWindow.mDecorContentParent != null) {
+ mWindow.mDecorContentParent.dismissPopups();
+ }
+
+ if (mPrimaryActionModePopup != null) {
+ removeCallbacks(mShowPrimaryActionModePopup);
+ if (mPrimaryActionModePopup.isShowing()) {
+ mPrimaryActionModePopup.dismiss();
+ }
+ mPrimaryActionModePopup = null;
+ }
+ if (mFloatingToolbar != null) {
+ mFloatingToolbar.dismiss();
+ mFloatingToolbar = null;
+ }
+
+ PhoneWindow.PanelFeatureState st = mWindow.getPanelState(Window.FEATURE_OPTIONS_PANEL, false);
+ if (st != null && st.menu != null && mFeatureId < 0) {
+ st.menu.close();
+ }
+ }
+
+ @Override
+ public void onCloseSystemDialogs(String reason) {
+ if (mFeatureId >= 0) {
+ mWindow.closeAllPanels();
+ }
+ }
+
+ public android.view.SurfaceHolder.Callback2 willYouTakeTheSurface() {
+ return mFeatureId < 0 ? mWindow.mTakeSurfaceCallback : null;
+ }
+
+ public InputQueue.Callback willYouTakeTheInputQueue() {
+ return mFeatureId < 0 ? mWindow.mTakeInputQueueCallback : null;
+ }
+
+ public void setSurfaceType(int type) {
+ mWindow.setType(type);
+ }
+
+ public void setSurfaceFormat(int format) {
+ mWindow.setFormat(format);
+ }
+
+ public void setSurfaceKeepScreenOn(boolean keepOn) {
+ if (keepOn) mWindow.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ else mWindow.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ }
+
+ @Override
+ public void onRootViewScrollYChanged(int rootScrollY) {
+ mRootScrollY = rootScrollY;
+ updateColorViewTranslations();
+ }
+
+ private ActionMode createActionMode(
+ int type, ActionMode.Callback2 callback, View originatingView) {
+ switch (type) {
+ case ActionMode.TYPE_PRIMARY:
+ default:
+ return createStandaloneActionMode(callback);
+ case ActionMode.TYPE_FLOATING:
+ return createFloatingActionMode(originatingView, callback);
+ }
+ }
+
+ private void setHandledActionMode(ActionMode mode) {
+ if (mode.getType() == ActionMode.TYPE_PRIMARY) {
+ setHandledPrimaryActionMode(mode);
+ } else if (mode.getType() == ActionMode.TYPE_FLOATING) {
+ setHandledFloatingActionMode(mode);
+ }
+ }
+
+ private ActionMode createStandaloneActionMode(ActionMode.Callback callback) {
+ endOnGoingFadeAnimation();
+ cleanupPrimaryActionMode();
+ if (mPrimaryActionModeView == null) {
+ if (mWindow.isFloating()) {
+ // Use the action bar theme.
+ final TypedValue outValue = new TypedValue();
+ final Resources.Theme baseTheme = mContext.getTheme();
+ baseTheme.resolveAttribute(R.attr.actionBarTheme, outValue, true);
+
+ final Context actionBarContext;
+ if (outValue.resourceId != 0) {
+ final Resources.Theme actionBarTheme = mContext.getResources().newTheme();
+ actionBarTheme.setTo(baseTheme);
+ actionBarTheme.applyStyle(outValue.resourceId, true);
+
+ actionBarContext = new ContextThemeWrapper(mContext, 0);
+ actionBarContext.getTheme().setTo(actionBarTheme);
+ } else {
+ actionBarContext = mContext;
+ }
+
+ mPrimaryActionModeView = new ActionBarContextView(actionBarContext);
+ mPrimaryActionModePopup = new PopupWindow(actionBarContext, null,
+ R.attr.actionModePopupWindowStyle);
+ mPrimaryActionModePopup.setWindowLayoutType(
+ WindowManager.LayoutParams.TYPE_APPLICATION);
+ mPrimaryActionModePopup.setContentView(mPrimaryActionModeView);
+ mPrimaryActionModePopup.setWidth(MATCH_PARENT);
+
+ actionBarContext.getTheme().resolveAttribute(
+ R.attr.actionBarSize, outValue, true);
+ final int height = TypedValue.complexToDimensionPixelSize(outValue.data,
+ actionBarContext.getResources().getDisplayMetrics());
+ mPrimaryActionModeView.setContentHeight(height);
+ mPrimaryActionModePopup.setHeight(WRAP_CONTENT);
+ mShowPrimaryActionModePopup = new Runnable() {
+ public void run() {
+ mPrimaryActionModePopup.showAtLocation(
+ mPrimaryActionModeView.getApplicationWindowToken(),
+ Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0);
+ endOnGoingFadeAnimation();
+ mFadeAnim = ObjectAnimator.ofFloat(mPrimaryActionModeView, View.ALPHA,
+ 0f, 1f);
+ mFadeAnim.addListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mPrimaryActionModeView.setVisibility(VISIBLE);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mPrimaryActionModeView.setAlpha(1f);
+ mFadeAnim = null;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+
+ }
+ });
+ mFadeAnim.start();
+ }
+ };
+ } else {
+ ViewStub stub = (ViewStub) findViewById(R.id.action_mode_bar_stub);
+ if (stub != null) {
+ mPrimaryActionModeView = (ActionBarContextView) stub.inflate();
+ }
+ }
+ }
+ if (mPrimaryActionModeView != null) {
+ mPrimaryActionModeView.killMode();
+ ActionMode mode = new StandaloneActionMode(
+ mPrimaryActionModeView.getContext(), mPrimaryActionModeView,
+ callback, mPrimaryActionModePopup == null);
+ return mode;
+ }
+ return null;
+ }
+
+ private void endOnGoingFadeAnimation() {
+ if (mFadeAnim != null) {
+ mFadeAnim.end();
+ }
+ }
+
+ private void setHandledPrimaryActionMode(ActionMode mode) {
+ endOnGoingFadeAnimation();
+ mPrimaryActionMode = mode;
+ mPrimaryActionMode.invalidate();
+ mPrimaryActionModeView.initForMode(mPrimaryActionMode);
+ if (mPrimaryActionModePopup != null) {
+ post(mShowPrimaryActionModePopup);
+ } else {
+ mFadeAnim = ObjectAnimator.ofFloat(mPrimaryActionModeView, View.ALPHA, 0f, 1f);
+ mFadeAnim.addListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mPrimaryActionModeView.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mPrimaryActionModeView.setAlpha(1f);
+ mFadeAnim = null;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+
+ }
+ });
+ mFadeAnim.start();
+ }
+ mPrimaryActionModeView.sendAccessibilityEvent(
+ AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ }
+
+ private ActionMode createFloatingActionMode(
+ View originatingView, ActionMode.Callback2 callback) {
+ if (mFloatingActionMode != null) {
+ mFloatingActionMode.finish();
+ }
+ cleanupFloatingActionModeViews();
+ final FloatingActionMode mode =
+ new FloatingActionMode(mContext, callback, originatingView);
+ mFloatingActionModeOriginatingView = originatingView;
+ mFloatingToolbarPreDrawListener =
+ new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ mode.updateViewLocationInWindow();
+ return true;
+ }
+ };
+ return mode;
+ }
+
+ private void setHandledFloatingActionMode(ActionMode mode) {
+ mFloatingActionMode = mode;
+ mFloatingToolbar = new FloatingToolbar(mContext, mWindow);
+ ((FloatingActionMode) mFloatingActionMode).setFloatingToolbar(mFloatingToolbar);
+ mFloatingActionMode.invalidate(); // Will show the floating toolbar if necessary.
+ mFloatingActionModeOriginatingView.getViewTreeObserver()
+ .addOnPreDrawListener(mFloatingToolbarPreDrawListener);
+ }
+
+ /**
+ * Informs the decor if a non client decor is attached and visible.
+ * @param attachedAndVisible true when the decor is visible.
+ * Note that this will even be called if there is no non client decor.
+ **/
+ void enableNonClientDecor(boolean attachedAndVisible) {
+ if (mHasNonClientDecor != attachedAndVisible) {
+ mHasNonClientDecor = attachedAndVisible;
+ if (getForeground() != null) {
+ drawableChanged();
+ }
+ }
+ }
+
+ /**
+ * Returns true if the window has a non client decor.
+ * @return If there is a non client decor - even if it is not visible.
+ **/
+ private boolean windowHasNonClientDecor() {
+ return mHasNonClientDecor;
+ }
+
+ /**
+ * Returns true if the Window is free floating and has a shadow (although at some times
+ * it might not be displaying it, e.g. during a resize). Note that non overlapping windows
+ * do not have a shadow since it could not be seen anyways (a small screen / tablet
+ * "tiles" the windows side by side but does not overlap them).
+ * @return Returns true when the window has a shadow created by the non client decor.
+ **/
+ private boolean windowHasShadow() {
+ return windowHasNonClientDecor() && ActivityManager.StackId
+ .hasWindowShadow(mWindow.mWorkspaceId);
+ }
+
+ void setWindow(PhoneWindow phoneWindow) {
+ mWindow = phoneWindow;
+ Context context = getContext();
+ if (context instanceof DecorContext) {
+ DecorContext decorContex = (DecorContext) context;
+ decorContex.setPhoneWindow(mWindow);
+ }
+ }
+
+ private static class ColorViewState {
+ View view = null;
+ int targetVisibility = View.INVISIBLE;
+ boolean present = false;
+
+ final int id;
+ final int systemUiHideFlag;
+ final int translucentFlag;
+ final int verticalGravity;
+ final int horizontalGravity;
+ final String transitionName;
+ final int hideWindowFlag;
+
+ ColorViewState(int systemUiHideFlag,
+ int translucentFlag, int verticalGravity, int horizontalGravity,
+ String transitionName, int id, int hideWindowFlag) {
+ this.id = id;
+ this.systemUiHideFlag = systemUiHideFlag;
+ this.translucentFlag = translucentFlag;
+ this.verticalGravity = verticalGravity;
+ this.horizontalGravity = horizontalGravity;
+ this.transitionName = transitionName;
+ this.hideWindowFlag = hideWindowFlag;
+ }
+ }
+
+ /**
+ * Clears out internal references when the action mode is destroyed.
+ */
+ private class ActionModeCallback2Wrapper extends ActionMode.Callback2 {
+ private final ActionMode.Callback mWrapped;
+
+ public ActionModeCallback2Wrapper(ActionMode.Callback wrapped) {
+ mWrapped = wrapped;
+ }
+
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ return mWrapped.onCreateActionMode(mode, menu);
+ }
+
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ requestFitSystemWindows();
+ return mWrapped.onPrepareActionMode(mode, menu);
+ }
+
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ return mWrapped.onActionItemClicked(mode, item);
+ }
+
+ public void onDestroyActionMode(ActionMode mode) {
+ mWrapped.onDestroyActionMode(mode);
+ final boolean isMncApp = mContext.getApplicationInfo().targetSdkVersion
+ >= Build.VERSION_CODES.M;
+ final boolean isPrimary;
+ final boolean isFloating;
+ if (isMncApp) {
+ isPrimary = mode == mPrimaryActionMode;
+ isFloating = mode == mFloatingActionMode;
+ if (!isPrimary && mode.getType() == ActionMode.TYPE_PRIMARY) {
+ Log.e(TAG, "Destroying unexpected ActionMode instance of TYPE_PRIMARY; "
+ + mode + " was not the current primary action mode! Expected "
+ + mPrimaryActionMode);
+ }
+ if (!isFloating && mode.getType() == ActionMode.TYPE_FLOATING) {
+ Log.e(TAG, "Destroying unexpected ActionMode instance of TYPE_FLOATING; "
+ + mode + " was not the current floating action mode! Expected "
+ + mFloatingActionMode);
+ }
+ } else {
+ isPrimary = mode.getType() == ActionMode.TYPE_PRIMARY;
+ isFloating = mode.getType() == ActionMode.TYPE_FLOATING;
+ }
+ if (isPrimary) {
+ if (mPrimaryActionModePopup != null) {
+ removeCallbacks(mShowPrimaryActionModePopup);
+ }
+ if (mPrimaryActionModeView != null) {
+ endOnGoingFadeAnimation();
+ mFadeAnim = ObjectAnimator.ofFloat(mPrimaryActionModeView, View.ALPHA,
+ 1f, 0f);
+ mFadeAnim.addListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mPrimaryActionModeView.setVisibility(GONE);
+ if (mPrimaryActionModePopup != null) {
+ mPrimaryActionModePopup.dismiss();
+ }
+ mPrimaryActionModeView.removeAllViews();
+ mFadeAnim = null;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+
+ }
+ });
+ mFadeAnim.start();
+ }
+
+ mPrimaryActionMode = null;
+ } else if (isFloating) {
+ cleanupFloatingActionModeViews();
+ mFloatingActionMode = null;
+ }
+ if (mWindow.getCallback() != null && !mWindow.isDestroyed()) {
+ try {
+ mWindow.getCallback().onActionModeFinished(mode);
+ } catch (AbstractMethodError ame) {
+ // Older apps might not implement this callback method.
+ }
+ }
+ requestFitSystemWindows();
+ }
+
+ @Override
+ public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
+ if (mWrapped instanceof ActionMode.Callback2) {
+ ((ActionMode.Callback2) mWrapped).onGetContentRect(mode, view, outRect);
+ } else {
+ super.onGetContentRect(mode, view, outRect);
+ }
+ }
+ }
+}
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 83f810f..c427149 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -18,22 +18,15 @@
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.view.View.MeasureSpec.AT_MOST;
-import static android.view.View.MeasureSpec.EXACTLY;
-import static android.view.View.MeasureSpec.getMode;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static android.view.WindowManager.LayoutParams.*;
-import android.animation.Animator;
-import android.animation.ObjectAnimator;
import android.app.ActivityManager.StackId;
import android.app.ActivityManagerNative;
import android.app.SearchManager;
-import android.os.Build;
import android.os.UserHandle;
-import android.view.ActionMode;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.IRotationWatcher.Stub;
@@ -55,15 +48,9 @@
import android.view.ViewManager;
import android.view.ViewParent;
import android.view.ViewRootImpl;
-import android.view.ViewStub;
-import android.view.ViewTreeObserver.OnPreDrawListener;
import android.view.Window;
-import android.view.WindowInsets;
import android.view.WindowManager;
import com.android.internal.R;
-import com.android.internal.view.FloatingActionMode;
-import com.android.internal.view.RootViewSurfaceTaker;
-import com.android.internal.view.StandaloneActionMode;
import com.android.internal.view.menu.ContextMenuBuilder;
import com.android.internal.view.menu.IconMenuPresenter;
import com.android.internal.view.menu.ListMenuPresenter;
@@ -72,10 +59,7 @@
import com.android.internal.view.menu.MenuPopupHelper;
import com.android.internal.view.menu.MenuPresenter;
import com.android.internal.view.menu.MenuView;
-import com.android.internal.widget.ActionBarContextView;
-import com.android.internal.widget.BackgroundFallback;
import com.android.internal.widget.DecorContentParent;
-import com.android.internal.widget.FloatingToolbar;
import com.android.internal.widget.NonClientDecorView;
import com.android.internal.widget.SwipeDismissLayout;
@@ -87,9 +71,7 @@
import android.content.res.Configuration;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
-import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
@@ -108,22 +90,17 @@
import android.transition.TransitionManager;
import android.transition.TransitionSet;
import android.util.AndroidRuntimeException;
-import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
import android.util.SparseArray;
import android.util.TypedValue;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeProvider;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
-import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ImageView;
-import android.widget.PopupWindow;
import android.widget.ProgressBar;
import android.widget.TextView;
@@ -142,8 +119,6 @@
private final static String TAG = "PhoneWindow";
- private final static boolean SWEEP_OPEN_MENU = false;
-
private final static int DEFAULT_BACKGROUND_FADE_DURATION_MS = 300;
private static final int CUSTOM_TITLE_COMPATIBLE_FEATURES = DEFAULT_FEATURES |
@@ -185,21 +160,19 @@
// This is the view in which the window contents are placed. It is either
// mDecor itself, or a child of mDecor where the contents go.
- private ViewGroup mContentParent;
-
- private ViewGroup mContentRoot;
+ ViewGroup mContentParent;
Callback2 mTakeSurfaceCallback;
InputQueue.Callback mTakeInputQueueCallback;
- private boolean mIsFloating;
+ boolean mIsFloating;
private LayoutInflater mLayoutInflater;
private TextView mTitleView;
- private DecorContentParent mDecorContentParent;
+ DecorContentParent mDecorContentParent;
private ActionMenuPresenterCallback mActionMenuPresenterCallback;
private PanelMenuPresenterCallback mPanelMenuPresenterCallback;
@@ -231,13 +204,13 @@
* multiple panels). Shortcuts will go to this panel. It gets set in
* {@link #preparePanel} and cleared in {@link #closePanel}.
*/
- private PanelFeatureState mPreparedPanel;
+ PanelFeatureState mPreparedPanel;
/**
* The keycode that is currently held down (as a modifier) for chording. If
* this is 0, there is no key held down.
*/
- private int mPanelChordingKey;
+ int mPanelChordingKey;
private ImageView mLeftIconView;
@@ -261,8 +234,8 @@
private int mFrameResource = 0;
private int mTextColor = 0;
- private int mStatusBarColor = 0;
- private int mNavigationBarColor = 0;
+ int mStatusBarColor = 0;
+ int mNavigationBarColor = 0;
private boolean mForcedStatusBarColor = false;
private boolean mForcedNavigationBarColor = false;
@@ -272,9 +245,9 @@
private boolean mAlwaysReadCloseOnTouchAttr = false;
- private ContextMenuBuilder mContextMenu;
- private MenuDialogHelper mContextMenuHelper;
- private MenuPopupHelper mContextMenuPopupHelper;
+ ContextMenuBuilder mContextMenu;
+ MenuDialogHelper mContextMenuHelper;
+ MenuPopupHelper mContextMenuPopupHelper;
private boolean mClosingActionMenu;
private int mVolumeControlStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE;
@@ -312,9 +285,6 @@
private long mBackgroundFadeDurationMillis = -1;
private Boolean mSharedElementsUseOverlay;
- private Rect mTempRect;
- private Rect mOutsets = new Rect();
-
private boolean mIsStartingWindow;
private int mTheme = -1;
@@ -1170,7 +1140,7 @@
return performPanelShortcut(getPanelState(featureId, false), keyCode, event, flags);
}
- private boolean performPanelShortcut(PanelFeatureState st, int keyCode, KeyEvent event,
+ boolean performPanelShortcut(PanelFeatureState st, int keyCode, KeyEvent event,
int flags) {
if (event.isSystem() || (st == null)) {
return false;
@@ -2261,7 +2231,7 @@
* called sometime after {@link #restorePanelState} when it is safe to add
* to the window manager.
*/
- private void openPanelsAfterRestore() {
+ void openPanelsAfterRestore() {
PanelFeatureState[] panels = mPanels;
if (panels == null) {
@@ -2332,1530 +2302,6 @@
}
}
- private static final class DecorView extends FrameLayout implements RootViewSurfaceTaker {
-
- /* package */int mDefaultOpacity = PixelFormat.OPAQUE;
-
- /** The feature ID of the panel, or -1 if this is the application's DecorView */
- private final int mFeatureId;
-
- private final Rect mDrawingBounds = new Rect();
-
- private final Rect mBackgroundPadding = new Rect();
-
- private final Rect mFramePadding = new Rect();
-
- private final Rect mFrameOffsets = new Rect();
-
- // True if a non client area decor exists.
- private boolean mHasNonClientDecor = false;
-
- private boolean mChanging;
-
- private Drawable mMenuBackground;
- private boolean mWatchingForMenu;
- private int mDownY;
-
- private ActionMode mPrimaryActionMode;
- private ActionMode mFloatingActionMode;
- private ActionBarContextView mPrimaryActionModeView;
- private PopupWindow mPrimaryActionModePopup;
- private Runnable mShowPrimaryActionModePopup;
- private OnPreDrawListener mFloatingToolbarPreDrawListener;
- private View mFloatingActionModeOriginatingView;
- private FloatingToolbar mFloatingToolbar;
- private ObjectAnimator mFadeAnim;
-
- // View added at runtime to draw under the status bar area
- private View mStatusGuard;
- // View added at runtime to draw under the navigation bar area
- private View mNavigationGuard;
-
- private final ColorViewState mStatusColorViewState = new ColorViewState(
- SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS,
- Gravity.TOP,
- Gravity.LEFT,
- STATUS_BAR_BACKGROUND_TRANSITION_NAME,
- com.android.internal.R.id.statusBarBackground,
- FLAG_FULLSCREEN);
- private final ColorViewState mNavigationColorViewState = new ColorViewState(
- SYSTEM_UI_FLAG_HIDE_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION,
- Gravity.BOTTOM,
- Gravity.RIGHT,
- NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,
- com.android.internal.R.id.navigationBarBackground,
- 0 /* hideWindowFlag */);
-
- private final Interpolator mShowInterpolator;
- private final Interpolator mHideInterpolator;
- private final int mBarEnterExitDuration;
-
- private final BackgroundFallback mBackgroundFallback = new BackgroundFallback();
-
- private int mLastTopInset = 0;
- private int mLastBottomInset = 0;
- private int mLastRightInset = 0;
- private boolean mLastHasTopStableInset = false;
- private boolean mLastHasBottomStableInset = false;
- private boolean mLastHasRightStableInset = false;
- private int mLastWindowFlags = 0;
-
- private int mRootScrollY = 0;
-
- private PhoneWindow mWindow;
-
- private DecorView(Context context, int featureId, PhoneWindow window) {
- super(context);
- mFeatureId = featureId;
-
- mShowInterpolator = AnimationUtils.loadInterpolator(context,
- android.R.interpolator.linear_out_slow_in);
- mHideInterpolator = AnimationUtils.loadInterpolator(context,
- android.R.interpolator.fast_out_linear_in);
-
- mBarEnterExitDuration = context.getResources().getInteger(
- R.integer.dock_enter_exit_duration);
-
- setWindow(window);
- }
-
- public void setBackgroundFallback(int resId) {
- mBackgroundFallback.setDrawable(resId != 0 ? getContext().getDrawable(resId) : null);
- setWillNotDraw(getBackground() == null && !mBackgroundFallback.hasFallback());
- }
-
- @Override
- public void onDraw(Canvas c) {
- super.onDraw(c);
- mBackgroundFallback.draw(mWindow.mContentRoot, c, mWindow.mContentParent);
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- final int keyCode = event.getKeyCode();
- final int action = event.getAction();
- final boolean isDown = action == KeyEvent.ACTION_DOWN;
-
- if (isDown && (event.getRepeatCount() == 0)) {
- // First handle chording of panel key: if a panel key is held
- // but not released, try to execute a shortcut in it.
- if ((mWindow.mPanelChordingKey > 0) && (mWindow.mPanelChordingKey != keyCode)) {
- boolean handled = dispatchKeyShortcutEvent(event);
- if (handled) {
- return true;
- }
- }
-
- // If a panel is open, perform a shortcut on it without the
- // chorded panel key
- if ((mWindow.mPreparedPanel != null) && mWindow.mPreparedPanel.isOpen) {
- if (mWindow.performPanelShortcut(mWindow.mPreparedPanel, keyCode, event, 0)) {
- return true;
- }
- }
- }
-
- if (!mWindow.isDestroyed()) {
- final Callback cb = mWindow.getCallback();
- final boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event)
- : super.dispatchKeyEvent(event);
- if (handled) {
- return true;
- }
- }
-
- return isDown ? mWindow.onKeyDown(mFeatureId, event.getKeyCode(), event)
- : mWindow.onKeyUp(mFeatureId, event.getKeyCode(), event);
- }
-
- @Override
- public boolean dispatchKeyShortcutEvent(KeyEvent ev) {
- // If the panel is already prepared, then perform the shortcut using it.
- boolean handled;
- if (mWindow.mPreparedPanel != null) {
- handled = mWindow.performPanelShortcut(mWindow.mPreparedPanel, ev.getKeyCode(), ev,
- Menu.FLAG_PERFORM_NO_CLOSE);
- if (handled) {
- if (mWindow.mPreparedPanel != null) {
- mWindow.mPreparedPanel.isHandled = true;
- }
- return true;
- }
- }
-
- // Shortcut not handled by the panel. Dispatch to the view hierarchy.
- final Callback cb = mWindow.getCallback();
- handled = cb != null && !mWindow.isDestroyed() && mFeatureId < 0
- ? cb.dispatchKeyShortcutEvent(ev) : super.dispatchKeyShortcutEvent(ev);
- if (handled) {
- return true;
- }
-
- // If the panel is not prepared, then we may be trying to handle a shortcut key
- // combination such as Control+C. Temporarily prepare the panel then mark it
- // unprepared again when finished to ensure that the panel will again be prepared
- // the next time it is shown for real.
- PanelFeatureState st = mWindow.getPanelState(FEATURE_OPTIONS_PANEL, false);
- if (st != null && mWindow.mPreparedPanel == null) {
- mWindow.preparePanel(st, ev);
- handled = mWindow.performPanelShortcut(st, ev.getKeyCode(), ev,
- Menu.FLAG_PERFORM_NO_CLOSE);
- st.isPrepared = false;
- if (handled) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- final Callback cb = mWindow.getCallback();
- return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
- ? cb.dispatchTouchEvent(ev) : super.dispatchTouchEvent(ev);
- }
-
- @Override
- public boolean dispatchTrackballEvent(MotionEvent ev) {
- final Callback cb = mWindow.getCallback();
- return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
- ? cb.dispatchTrackballEvent(ev) : super.dispatchTrackballEvent(ev);
- }
-
- @Override
- public boolean dispatchGenericMotionEvent(MotionEvent ev) {
- final Callback cb = mWindow.getCallback();
- return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
- ? cb.dispatchGenericMotionEvent(ev) : super.dispatchGenericMotionEvent(ev);
- }
-
- public boolean superDispatchKeyEvent(KeyEvent event) {
- // Give priority to closing action modes if applicable.
- if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
- final int action = event.getAction();
- // Back cancels action modes first.
- if (mPrimaryActionMode != null) {
- if (action == KeyEvent.ACTION_UP) {
- mPrimaryActionMode.finish();
- }
- return true;
- }
- }
-
- return super.dispatchKeyEvent(event);
- }
-
- public boolean superDispatchKeyShortcutEvent(KeyEvent event) {
- return super.dispatchKeyShortcutEvent(event);
- }
-
- public boolean superDispatchTouchEvent(MotionEvent event) {
- return super.dispatchTouchEvent(event);
- }
-
- public boolean superDispatchTrackballEvent(MotionEvent event) {
- return super.dispatchTrackballEvent(event);
- }
-
- public boolean superDispatchGenericMotionEvent(MotionEvent event) {
- return super.dispatchGenericMotionEvent(event);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- return onInterceptTouchEvent(event);
- }
-
- private boolean isOutOfInnerBounds(int x, int y) {
- return x < 0 || y < 0 || x > getWidth() || y > getHeight();
- }
-
- private boolean isOutOfBounds(int x, int y) {
- return x < -5 || y < -5 || x > (getWidth() + 5)
- || y > (getHeight() + 5);
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent event) {
- int action = event.getAction();
- if (mHasNonClientDecor && mWindow.mNonClientDecorView.mVisible) {
- // Don't dispatch ACTION_DOWN to the non client decor if the window is
- // resizable and the event was (starting) outside the window.
- // Window resizing events should be handled by WindowManager.
- // TODO: Investigate how to handle the outside touch in window manager
- // without generating these events.
- // Currently we receive these because we need to enlarge the window's
- // touch region so that the monitor channel receives the events
- // in the outside touch area.
- if (action == MotionEvent.ACTION_DOWN) {
- final int x = (int) event.getX();
- final int y = (int) event.getY();
- if (isOutOfInnerBounds(x, y)) {
- return true;
- }
- }
- }
-
- if (mFeatureId >= 0) {
- if (action == MotionEvent.ACTION_DOWN) {
- int x = (int)event.getX();
- int y = (int)event.getY();
- if (isOutOfBounds(x, y)) {
- mWindow.closePanel(mFeatureId);
- return true;
- }
- }
- }
-
- if (!SWEEP_OPEN_MENU) {
- return false;
- }
-
- if (mFeatureId >= 0) {
- if (action == MotionEvent.ACTION_DOWN) {
- Log.i(TAG, "Watchiing!");
- mWatchingForMenu = true;
- mDownY = (int) event.getY();
- return false;
- }
-
- if (!mWatchingForMenu) {
- return false;
- }
-
- int y = (int)event.getY();
- if (action == MotionEvent.ACTION_MOVE) {
- if (y > (mDownY+30)) {
- Log.i(TAG, "Closing!");
- mWindow.closePanel(mFeatureId);
- mWatchingForMenu = false;
- return true;
- }
- } else if (action == MotionEvent.ACTION_UP) {
- mWatchingForMenu = false;
- }
-
- return false;
- }
-
- //Log.i(TAG, "Intercept: action=" + action + " y=" + event.getY()
- // + " (in " + getHeight() + ")");
-
- if (action == MotionEvent.ACTION_DOWN) {
- int y = (int)event.getY();
- if (y >= (getHeight()-5) && !mWindow.hasChildren()) {
- Log.i(TAG, "Watching!");
- mWatchingForMenu = true;
- }
- return false;
- }
-
- if (!mWatchingForMenu) {
- return false;
- }
-
- int y = (int)event.getY();
- if (action == MotionEvent.ACTION_MOVE) {
- if (y < (getHeight()-30)) {
- Log.i(TAG, "Opening!");
- mWindow.openPanel(FEATURE_OPTIONS_PANEL, new KeyEvent(
- KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU));
- mWatchingForMenu = false;
- return true;
- }
- } else if (action == MotionEvent.ACTION_UP) {
- mWatchingForMenu = false;
- }
-
- return false;
- }
-
- @Override
- public void sendAccessibilityEvent(int eventType) {
- if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
- return;
- }
-
- // if we are showing a feature that should be announced and one child
- // make this child the event source since this is the feature itself
- // otherwise the callback will take over and announce its client
- if ((mFeatureId == FEATURE_OPTIONS_PANEL ||
- mFeatureId == FEATURE_CONTEXT_MENU ||
- mFeatureId == FEATURE_PROGRESS ||
- mFeatureId == FEATURE_INDETERMINATE_PROGRESS)
- && getChildCount() == 1) {
- getChildAt(0).sendAccessibilityEvent(eventType);
- } else {
- super.sendAccessibilityEvent(eventType);
- }
- }
-
- @Override
- public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
- final Callback cb = mWindow.getCallback();
- if (cb != null && !mWindow.isDestroyed()) {
- if (cb.dispatchPopulateAccessibilityEvent(event)) {
- return true;
- }
- }
- return super.dispatchPopulateAccessibilityEventInternal(event);
- }
-
- @Override
- protected boolean setFrame(int l, int t, int r, int b) {
- boolean changed = super.setFrame(l, t, r, b);
- if (changed) {
- final Rect drawingBounds = mDrawingBounds;
- getDrawingRect(drawingBounds);
-
- Drawable fg = getForeground();
- if (fg != null) {
- final Rect frameOffsets = mFrameOffsets;
- drawingBounds.left += frameOffsets.left;
- drawingBounds.top += frameOffsets.top;
- drawingBounds.right -= frameOffsets.right;
- drawingBounds.bottom -= frameOffsets.bottom;
- fg.setBounds(drawingBounds);
- final Rect framePadding = mFramePadding;
- drawingBounds.left += framePadding.left - frameOffsets.left;
- drawingBounds.top += framePadding.top - frameOffsets.top;
- drawingBounds.right -= framePadding.right - frameOffsets.right;
- drawingBounds.bottom -= framePadding.bottom - frameOffsets.bottom;
- }
-
- Drawable bg = getBackground();
- if (bg != null) {
- bg.setBounds(drawingBounds);
- }
-
- if (SWEEP_OPEN_MENU) {
- if (mMenuBackground == null && mFeatureId < 0
- && mWindow.getAttributes().height
- == WindowManager.LayoutParams.MATCH_PARENT) {
- mMenuBackground = getContext().getDrawable(
- R.drawable.menu_background);
- }
- if (mMenuBackground != null) {
- mMenuBackground.setBounds(drawingBounds.left,
- drawingBounds.bottom-6, drawingBounds.right,
- drawingBounds.bottom+20);
- }
- }
- }
- return changed;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
- final boolean isPortrait = metrics.widthPixels < metrics.heightPixels;
-
- final int widthMode = getMode(widthMeasureSpec);
- final int heightMode = getMode(heightMeasureSpec);
-
- boolean fixedWidth = false;
- if (widthMode == AT_MOST) {
- final TypedValue tvw = isPortrait ? mWindow.mFixedWidthMinor
- : mWindow.mFixedWidthMajor;
- if (tvw != null && tvw.type != TypedValue.TYPE_NULL) {
- final int w;
- if (tvw.type == TypedValue.TYPE_DIMENSION) {
- w = (int) tvw.getDimension(metrics);
- } else if (tvw.type == TypedValue.TYPE_FRACTION) {
- w = (int) tvw.getFraction(metrics.widthPixels, metrics.widthPixels);
- } else {
- w = 0;
- }
-
- if (w > 0) {
- final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- widthMeasureSpec = MeasureSpec.makeMeasureSpec(
- Math.min(w, widthSize), EXACTLY);
- fixedWidth = true;
- }
- }
- }
-
- if (heightMode == AT_MOST) {
- final TypedValue tvh = isPortrait ? mWindow.mFixedHeightMajor
- : mWindow.mFixedHeightMinor;
- if (tvh != null && tvh.type != TypedValue.TYPE_NULL) {
- final int h;
- if (tvh.type == TypedValue.TYPE_DIMENSION) {
- h = (int) tvh.getDimension(metrics);
- } else if (tvh.type == TypedValue.TYPE_FRACTION) {
- h = (int) tvh.getFraction(metrics.heightPixels, metrics.heightPixels);
- } else {
- h = 0;
- }
- if (h > 0) {
- final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
- heightMeasureSpec = MeasureSpec.makeMeasureSpec(
- Math.min(h, heightSize), EXACTLY);
- }
- }
- }
-
- getOutsets(mWindow.mOutsets);
- if (mWindow.mOutsets.top > 0 || mWindow.mOutsets.bottom > 0) {
- int mode = MeasureSpec.getMode(heightMeasureSpec);
- if (mode != MeasureSpec.UNSPECIFIED) {
- int height = MeasureSpec.getSize(heightMeasureSpec);
- heightMeasureSpec = MeasureSpec.makeMeasureSpec(
- height + mWindow.mOutsets.top + mWindow.mOutsets.bottom, mode);
- }
- }
- if (mWindow.mOutsets.left > 0 || mWindow.mOutsets.right > 0) {
- int mode = MeasureSpec.getMode(widthMeasureSpec);
- if (mode != MeasureSpec.UNSPECIFIED) {
- int width = MeasureSpec.getSize(widthMeasureSpec);
- widthMeasureSpec = MeasureSpec.makeMeasureSpec(
- width + mWindow.mOutsets.left + mWindow.mOutsets.right, mode);
- }
- }
-
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
- int width = getMeasuredWidth();
- boolean measure = false;
-
- widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, EXACTLY);
-
- if (!fixedWidth && widthMode == AT_MOST) {
- final TypedValue tv = isPortrait ? mWindow.mMinWidthMinor : mWindow.mMinWidthMajor;
- if (tv.type != TypedValue.TYPE_NULL) {
- final int min;
- if (tv.type == TypedValue.TYPE_DIMENSION) {
- min = (int)tv.getDimension(metrics);
- } else if (tv.type == TypedValue.TYPE_FRACTION) {
- min = (int)tv.getFraction(metrics.widthPixels, metrics.widthPixels);
- } else {
- min = 0;
- }
-
- if (width < min) {
- widthMeasureSpec = MeasureSpec.makeMeasureSpec(min, EXACTLY);
- measure = true;
- }
- }
- }
-
- // TODO: Support height?
-
- if (measure) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- getOutsets(mWindow.mOutsets);
- if (mWindow.mOutsets.left > 0) {
- offsetLeftAndRight(-mWindow.mOutsets.left);
- }
- if (mWindow.mOutsets.top > 0) {
- offsetTopAndBottom(-mWindow.mOutsets.top);
- }
- }
-
- @Override
- public void draw(Canvas canvas) {
- super.draw(canvas);
-
- if (mMenuBackground != null) {
- mMenuBackground.draw(canvas);
- }
- }
-
- @Override
- public boolean showContextMenuForChild(View originalView) {
- // Reuse the context menu builder
- if (mWindow.mContextMenu == null) {
- mWindow.mContextMenu = new ContextMenuBuilder(getContext());
- mWindow.mContextMenu.setCallback(mWindow.mContextMenuCallback);
- } else {
- mWindow.mContextMenu.clearAll();
- }
-
- final MenuDialogHelper helper = mWindow.mContextMenu.show(originalView,
- originalView.getWindowToken());
- if (helper != null) {
- helper.setPresenterCallback(mWindow.mContextMenuCallback);
- } else if (mWindow.mContextMenuHelper != null) {
- // No menu to show, but if we have a menu currently showing it just became blank.
- // Close it.
- mWindow.mContextMenuHelper.dismiss();
- }
- mWindow.mContextMenuHelper = helper;
- return helper != null;
- }
-
- @Override
- public boolean showContextMenuForChild(View originalView, float x, float y) {
- // Reuse the context menu builder
- if (mWindow.mContextMenu == null) {
- mWindow.mContextMenu = new ContextMenuBuilder(getContext());
- mWindow.mContextMenu.setCallback(mWindow.mContextMenuCallback);
- } else {
- mWindow.mContextMenu.clearAll();
- }
-
- final MenuPopupHelper helper = mWindow.mContextMenu.showPopup(
- getContext(), originalView, x, y);
- if (helper != null) {
- helper.setCallback(mWindow.mContextMenuCallback);
- } else if (mWindow.mContextMenuPopupHelper != null) {
- // No menu to show, but if we have a menu currently showing it just became blank.
- // Close it.
- mWindow.mContextMenuPopupHelper.dismiss();
- }
- mWindow.mContextMenuPopupHelper = helper;
- return helper != null;
- }
-
- @Override
- public ActionMode startActionModeForChild(View originalView,
- ActionMode.Callback callback) {
- return startActionModeForChild(originalView, callback, ActionMode.TYPE_PRIMARY);
- }
-
- @Override
- public ActionMode startActionModeForChild(
- View child, ActionMode.Callback callback, int type) {
- return startActionMode(child, callback, type);
- }
-
- @Override
- public ActionMode startActionMode(ActionMode.Callback callback) {
- return startActionMode(callback, ActionMode.TYPE_PRIMARY);
- }
-
- @Override
- public ActionMode startActionMode(ActionMode.Callback callback, int type) {
- return startActionMode(this, callback, type);
- }
-
- private ActionMode startActionMode(
- View originatingView, ActionMode.Callback callback, int type) {
- ActionMode.Callback2 wrappedCallback = new ActionModeCallback2Wrapper(callback);
- ActionMode mode = null;
- if (mWindow.getCallback() != null && !mWindow.isDestroyed()) {
- try {
- mode = mWindow.getCallback().onWindowStartingActionMode(wrappedCallback, type);
- } catch (AbstractMethodError ame) {
- // Older apps might not implement the typed version of this method.
- if (type == ActionMode.TYPE_PRIMARY) {
- try {
- mode = mWindow.getCallback().onWindowStartingActionMode(
- wrappedCallback);
- } catch (AbstractMethodError ame2) {
- // Older apps might not implement this callback method at all.
- }
- }
- }
- }
- if (mode != null) {
- if (mode.getType() == ActionMode.TYPE_PRIMARY) {
- cleanupPrimaryActionMode();
- mPrimaryActionMode = mode;
- } else if (mode.getType() == ActionMode.TYPE_FLOATING) {
- if (mFloatingActionMode != null) {
- mFloatingActionMode.finish();
- }
- mFloatingActionMode = mode;
- }
- } else {
- mode = createActionMode(type, wrappedCallback, originatingView);
- if (mode != null && wrappedCallback.onCreateActionMode(mode, mode.getMenu())) {
- setHandledActionMode(mode);
- } else {
- mode = null;
- }
- }
- if (mode != null && mWindow.getCallback() != null && !mWindow.isDestroyed()) {
- try {
- mWindow.getCallback().onActionModeStarted(mode);
- } catch (AbstractMethodError ame) {
- // Older apps might not implement this callback method.
- }
- }
- return mode;
- }
-
- private void cleanupPrimaryActionMode() {
- if (mPrimaryActionMode != null) {
- mPrimaryActionMode.finish();
- mPrimaryActionMode = null;
- }
- if (mPrimaryActionModeView != null) {
- mPrimaryActionModeView.killMode();
- }
- }
-
- private void cleanupFloatingActionModeViews() {
- if (mFloatingToolbar != null) {
- mFloatingToolbar.dismiss();
- mFloatingToolbar = null;
- }
- if (mFloatingActionModeOriginatingView != null) {
- if (mFloatingToolbarPreDrawListener != null) {
- mFloatingActionModeOriginatingView.getViewTreeObserver()
- .removeOnPreDrawListener(mFloatingToolbarPreDrawListener);
- mFloatingToolbarPreDrawListener = null;
- }
- mFloatingActionModeOriginatingView = null;
- }
- }
-
- public void startChanging() {
- mChanging = true;
- }
-
- public void finishChanging() {
- mChanging = false;
- drawableChanged();
- }
-
- public void setWindowBackground(Drawable drawable) {
- if (getBackground() != drawable) {
- setBackgroundDrawable(drawable);
- if (drawable != null) {
- drawable.getPadding(mBackgroundPadding);
- } else {
- mBackgroundPadding.setEmpty();
- }
- drawableChanged();
- }
- }
-
- public void setWindowFrame(Drawable drawable) {
- if (getForeground() != drawable) {
- setForeground(drawable);
- if (drawable != null) {
- drawable.getPadding(mFramePadding);
- } else {
- mFramePadding.setEmpty();
- }
- drawableChanged();
- }
- }
-
- @Override
- public void onWindowSystemUiVisibilityChanged(int visible) {
- updateColorViews(null /* insets */, true /* animate */);
- }
-
- @Override
- public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- mFrameOffsets.set(insets.getSystemWindowInsets());
- insets = updateColorViews(insets, true /* animate */);
- insets = updateStatusGuard(insets);
- updateNavigationGuard(insets);
- if (getForeground() != null) {
- drawableChanged();
- }
- return insets;
- }
-
- @Override
- public boolean isTransitionGroup() {
- return false;
- }
-
- private WindowInsets updateColorViews(WindowInsets insets, boolean animate) {
- WindowManager.LayoutParams attrs = mWindow.getAttributes();
- int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility();
-
- if (!mWindow.mIsFloating && ActivityManager.isHighEndGfx()) {
- boolean disallowAnimate = !isLaidOut();
- disallowAnimate |= ((mLastWindowFlags ^ attrs.flags)
- & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
- mLastWindowFlags = attrs.flags;
-
- if (insets != null) {
- mLastTopInset = Math.min(insets.getStableInsetTop(),
- insets.getSystemWindowInsetTop());
- mLastBottomInset = Math.min(insets.getStableInsetBottom(),
- insets.getSystemWindowInsetBottom());
- mLastRightInset = Math.min(insets.getStableInsetRight(),
- insets.getSystemWindowInsetRight());
-
- // Don't animate if the presence of stable insets has changed, because that
- // indicates that the window was either just added and received them for the
- // first time, or the window size or position has changed.
- boolean hasTopStableInset = insets.getStableInsetTop() != 0;
- disallowAnimate |= (hasTopStableInset != mLastHasTopStableInset);
- mLastHasTopStableInset = hasTopStableInset;
-
- boolean hasBottomStableInset = insets.getStableInsetBottom() != 0;
- disallowAnimate |= (hasBottomStableInset != mLastHasBottomStableInset);
- mLastHasBottomStableInset = hasBottomStableInset;
-
- boolean hasRightStableInset = insets.getStableInsetRight() != 0;
- disallowAnimate |= (hasRightStableInset != mLastHasRightStableInset);
- mLastHasRightStableInset = hasRightStableInset;
- }
-
- boolean navBarToRightEdge = mLastBottomInset == 0 && mLastRightInset > 0;
- int navBarSize = navBarToRightEdge ? mLastRightInset : mLastBottomInset;
- updateColorViewInt(mNavigationColorViewState, sysUiVisibility,
- mWindow.mNavigationBarColor, navBarSize, navBarToRightEdge,
- 0 /* rightInset */, animate && !disallowAnimate);
-
- boolean statusBarNeedsRightInset = navBarToRightEdge
- && mNavigationColorViewState.present;
- int statusBarRightInset = statusBarNeedsRightInset ? mLastRightInset : 0;
- updateColorViewInt(mStatusColorViewState, sysUiVisibility, mWindow.mStatusBarColor,
- mLastTopInset, false /* matchVertical */, statusBarRightInset,
- animate && !disallowAnimate);
- }
-
- // When we expand the window with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, we still need
- // to ensure that the rest of the view hierarchy doesn't notice it, unless they've
- // explicitly asked for it.
-
- boolean consumingNavBar =
- (attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
- && (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0
- && (sysUiVisibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
-
- int consumedRight = consumingNavBar ? mLastRightInset : 0;
- int consumedBottom = consumingNavBar ? mLastBottomInset : 0;
-
- if (mWindow.mContentRoot != null
- && mWindow.mContentRoot.getLayoutParams() instanceof MarginLayoutParams) {
- MarginLayoutParams lp = (MarginLayoutParams) mWindow.mContentRoot.getLayoutParams();
- if (lp.rightMargin != consumedRight || lp.bottomMargin != consumedBottom) {
- lp.rightMargin = consumedRight;
- lp.bottomMargin = consumedBottom;
- mWindow.mContentRoot.setLayoutParams(lp);
-
- if (insets == null) {
- // The insets have changed, but we're not currently in the process
- // of dispatching them.
- requestApplyInsets();
- }
- }
- if (insets != null) {
- insets = insets.replaceSystemWindowInsets(
- insets.getSystemWindowInsetLeft(),
- insets.getSystemWindowInsetTop(),
- insets.getSystemWindowInsetRight() - consumedRight,
- insets.getSystemWindowInsetBottom() - consumedBottom);
- }
- }
-
- if (insets != null) {
- insets = insets.consumeStableInsets();
- }
- return insets;
- }
-
- /**
- * Update a color view
- *
- * @param state the color view to update.
- * @param sysUiVis the current systemUiVisibility to apply.
- * @param color the current color to apply.
- * @param size the current size in the non-parent-matching dimension.
- * @param verticalBar if true the view is attached to a vertical edge, otherwise to a
- * horizontal edge,
- * @param rightMargin rightMargin for the color view.
- * @param animate if true, the change will be animated.
- */
- private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color,
- int size, boolean verticalBar, int rightMargin, boolean animate) {
- state.present = size > 0 && (sysUiVis & state.systemUiHideFlag) == 0
- && (mWindow.getAttributes().flags & state.hideWindowFlag) == 0
- && (mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
- boolean show = state.present
- && (color & Color.BLACK) != 0
- && (mWindow.getAttributes().flags & state.translucentFlag) == 0;
-
- boolean visibilityChanged = false;
- View view = state.view;
-
- int resolvedHeight = verticalBar ? LayoutParams.MATCH_PARENT : size;
- int resolvedWidth = verticalBar ? size : LayoutParams.MATCH_PARENT;
- int resolvedGravity = verticalBar ? state.horizontalGravity : state.verticalGravity;
-
- if (view == null) {
- if (show) {
- state.view = view = new View(mContext);
- view.setBackgroundColor(color);
- view.setTransitionName(state.transitionName);
- view.setId(state.id);
- visibilityChanged = true;
- view.setVisibility(INVISIBLE);
- state.targetVisibility = VISIBLE;
-
- LayoutParams lp = new LayoutParams(resolvedWidth, resolvedHeight,
- resolvedGravity);
- lp.rightMargin = rightMargin;
- addView(view, lp);
- updateColorViewTranslations();
- }
- } else {
- int vis = show ? VISIBLE : INVISIBLE;
- visibilityChanged = state.targetVisibility != vis;
- state.targetVisibility = vis;
- LayoutParams lp = (LayoutParams) view.getLayoutParams();
- if (lp.height != resolvedHeight || lp.width != resolvedWidth
- || lp.gravity != resolvedGravity || lp.rightMargin != rightMargin) {
- lp.height = resolvedHeight;
- lp.width = resolvedWidth;
- lp.gravity = resolvedGravity;
- lp.rightMargin = rightMargin;
- view.setLayoutParams(lp);
- }
- if (show) {
- view.setBackgroundColor(color);
- }
- }
- if (visibilityChanged) {
- view.animate().cancel();
- if (animate) {
- if (show) {
- if (view.getVisibility() != VISIBLE) {
- view.setVisibility(VISIBLE);
- view.setAlpha(0.0f);
- }
- view.animate().alpha(1.0f).setInterpolator(mShowInterpolator).
- setDuration(mBarEnterExitDuration);
- } else {
- view.animate().alpha(0.0f).setInterpolator(mHideInterpolator)
- .setDuration(mBarEnterExitDuration)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- state.view.setAlpha(1.0f);
- state.view.setVisibility(INVISIBLE);
- }
- });
- }
- } else {
- view.setAlpha(1.0f);
- view.setVisibility(show ? VISIBLE : INVISIBLE);
- }
- }
- }
-
- private void updateColorViewTranslations() {
- // Put the color views back in place when they get moved off the screen
- // due to the the ViewRootImpl panning.
- int rootScrollY = mRootScrollY;
- if (mStatusColorViewState.view != null) {
- mStatusColorViewState.view.setTranslationY(rootScrollY > 0 ? rootScrollY : 0);
- }
- if (mNavigationColorViewState.view != null) {
- mNavigationColorViewState.view.setTranslationY(rootScrollY < 0 ? rootScrollY : 0);
- }
- }
-
- private WindowInsets updateStatusGuard(WindowInsets insets) {
- boolean showStatusGuard = false;
- // Show the status guard when the non-overlay contextual action bar is showing
- if (mPrimaryActionModeView != null) {
- if (mPrimaryActionModeView.getLayoutParams() instanceof MarginLayoutParams) {
- // Insets are magic!
- final MarginLayoutParams mlp = (MarginLayoutParams)
- mPrimaryActionModeView.getLayoutParams();
- boolean mlpChanged = false;
- if (mPrimaryActionModeView.isShown()) {
- if (mWindow.mTempRect == null) {
- mWindow.mTempRect = new Rect();
- }
- final Rect rect = mWindow.mTempRect;
-
- // If the parent doesn't consume the insets, manually
- // apply the default system window insets.
- mWindow.mContentParent.computeSystemWindowInsets(insets, rect);
- final int newMargin = rect.top == 0 ? insets.getSystemWindowInsetTop() : 0;
- if (mlp.topMargin != newMargin) {
- mlpChanged = true;
- mlp.topMargin = insets.getSystemWindowInsetTop();
-
- if (mStatusGuard == null) {
- mStatusGuard = new View(mContext);
- mStatusGuard.setBackgroundColor(mContext.getColor(
- R.color.input_method_navigation_guard));
- addView(mStatusGuard, indexOfChild(mStatusColorViewState.view),
- new LayoutParams(LayoutParams.MATCH_PARENT,
- mlp.topMargin, Gravity.START | Gravity.TOP));
- } else {
- final LayoutParams lp = (LayoutParams)
- mStatusGuard.getLayoutParams();
- if (lp.height != mlp.topMargin) {
- lp.height = mlp.topMargin;
- mStatusGuard.setLayoutParams(lp);
- }
- }
- }
-
- // The action mode's theme may differ from the app, so
- // always show the status guard above it if we have one.
- showStatusGuard = mStatusGuard != null;
-
- // We only need to consume the insets if the action
- // mode is overlaid on the app content (e.g. it's
- // sitting in a FrameLayout, see
- // screen_simple_overlay_action_mode.xml).
- final boolean nonOverlay = (mWindow.getLocalFeatures()
- & (1 << FEATURE_ACTION_MODE_OVERLAY)) == 0;
- insets = insets.consumeSystemWindowInsets(
- false, nonOverlay && showStatusGuard /* top */, false, false);
- } else {
- // reset top margin
- if (mlp.topMargin != 0) {
- mlpChanged = true;
- mlp.topMargin = 0;
- }
- }
- if (mlpChanged) {
- mPrimaryActionModeView.setLayoutParams(mlp);
- }
- }
- }
- if (mStatusGuard != null) {
- mStatusGuard.setVisibility(showStatusGuard ? View.VISIBLE : View.GONE);
- }
- return insets;
- }
-
- private void updateNavigationGuard(WindowInsets insets) {
- // IMEs lay out below the nav bar, but the content view must not (for back compat)
- if (mWindow.getAttributes().type == WindowManager.LayoutParams.TYPE_INPUT_METHOD) {
- // prevent the content view from including the nav bar height
- if (mWindow.mContentParent != null) {
- if (mWindow.mContentParent.getLayoutParams() instanceof MarginLayoutParams) {
- MarginLayoutParams mlp =
- (MarginLayoutParams) mWindow.mContentParent.getLayoutParams();
- mlp.bottomMargin = insets.getSystemWindowInsetBottom();
- mWindow.mContentParent.setLayoutParams(mlp);
- }
- }
- // position the navigation guard view, creating it if necessary
- if (mNavigationGuard == null) {
- mNavigationGuard = new View(mContext);
- mNavigationGuard.setBackgroundColor(mContext.getColor(
- R.color.input_method_navigation_guard));
- addView(mNavigationGuard, indexOfChild(mNavigationColorViewState.view),
- new LayoutParams(LayoutParams.MATCH_PARENT,
- insets.getSystemWindowInsetBottom(),
- Gravity.START | Gravity.BOTTOM));
- } else {
- LayoutParams lp = (LayoutParams) mNavigationGuard.getLayoutParams();
- lp.height = insets.getSystemWindowInsetBottom();
- mNavigationGuard.setLayoutParams(lp);
- }
- }
- }
-
- private void drawableChanged() {
- if (mChanging) {
- return;
- }
-
- setPadding(mFramePadding.left + mBackgroundPadding.left,
- mFramePadding.top + mBackgroundPadding.top,
- mFramePadding.right + mBackgroundPadding.right,
- mFramePadding.bottom + mBackgroundPadding.bottom);
- requestLayout();
- invalidate();
-
- int opacity = PixelFormat.OPAQUE;
- if (windowHasShadow()) {
- // If the window has a shadow, it must be translucent.
- opacity = PixelFormat.TRANSLUCENT;
- } else{
- // Note: If there is no background, we will assume opaque. The
- // common case seems to be that an application sets there to be
- // no background so it can draw everything itself. For that,
- // we would like to assume OPAQUE and let the app force it to
- // the slower TRANSLUCENT mode if that is really what it wants.
- Drawable bg = getBackground();
- Drawable fg = getForeground();
- if (bg != null) {
- if (fg == null) {
- opacity = bg.getOpacity();
- } else if (mFramePadding.left <= 0 && mFramePadding.top <= 0
- && mFramePadding.right <= 0 && mFramePadding.bottom <= 0) {
- // If the frame padding is zero, then we can be opaque
- // if either the frame -or- the background is opaque.
- int fop = fg.getOpacity();
- int bop = bg.getOpacity();
- if (false)
- Log.v(TAG, "Background opacity: " + bop + ", Frame opacity: " + fop);
- if (fop == PixelFormat.OPAQUE || bop == PixelFormat.OPAQUE) {
- opacity = PixelFormat.OPAQUE;
- } else if (fop == PixelFormat.UNKNOWN) {
- opacity = bop;
- } else if (bop == PixelFormat.UNKNOWN) {
- opacity = fop;
- } else {
- opacity = Drawable.resolveOpacity(fop, bop);
- }
- } else {
- // For now we have to assume translucent if there is a
- // frame with padding... there is no way to tell if the
- // frame and background together will draw all pixels.
- if (false)
- Log.v(TAG, "Padding: " + mFramePadding);
- opacity = PixelFormat.TRANSLUCENT;
- }
- }
- if (false)
- Log.v(TAG, "Background: " + bg + ", Frame: " + fg);
- }
-
- if (false)
- Log.v(TAG, "Selected default opacity: " + opacity);
-
- mDefaultOpacity = opacity;
- if (mFeatureId < 0) {
- mWindow.setDefaultWindowFormat(opacity);
- }
- }
-
- @Override
- public void onWindowFocusChanged(boolean hasWindowFocus) {
- super.onWindowFocusChanged(hasWindowFocus);
-
- // If the user is chording a menu shortcut, release the chord since
- // this window lost focus
- if (mWindow.hasFeature(FEATURE_OPTIONS_PANEL) && !hasWindowFocus
- && mWindow.mPanelChordingKey != 0) {
- mWindow.closePanel(FEATURE_OPTIONS_PANEL);
- }
-
- final Callback cb = mWindow.getCallback();
- if (cb != null && !mWindow.isDestroyed() && mFeatureId < 0) {
- cb.onWindowFocusChanged(hasWindowFocus);
- }
-
- if (mPrimaryActionMode != null) {
- mPrimaryActionMode.onWindowFocusChanged(hasWindowFocus);
- }
- if (mFloatingActionMode != null) {
- mFloatingActionMode.onWindowFocusChanged(hasWindowFocus);
- }
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
-
- final Callback cb = mWindow.getCallback();
- if (cb != null && !mWindow.isDestroyed() && mFeatureId < 0) {
- cb.onAttachedToWindow();
- }
-
- if (mFeatureId == -1) {
- /*
- * The main window has been attached, try to restore any panels
- * that may have been open before. This is called in cases where
- * an activity is being killed for configuration change and the
- * menu was open. When the activity is recreated, the menu
- * should be shown again.
- */
- mWindow.openPanelsAfterRestore();
- }
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
-
- final Callback cb = mWindow.getCallback();
- if (cb != null && mFeatureId < 0) {
- cb.onDetachedFromWindow();
- }
-
- if (mWindow.mDecorContentParent != null) {
- mWindow.mDecorContentParent.dismissPopups();
- }
-
- if (mPrimaryActionModePopup != null) {
- removeCallbacks(mShowPrimaryActionModePopup);
- if (mPrimaryActionModePopup.isShowing()) {
- mPrimaryActionModePopup.dismiss();
- }
- mPrimaryActionModePopup = null;
- }
- if (mFloatingToolbar != null) {
- mFloatingToolbar.dismiss();
- mFloatingToolbar = null;
- }
-
- PanelFeatureState st = mWindow.getPanelState(FEATURE_OPTIONS_PANEL, false);
- if (st != null && st.menu != null && mFeatureId < 0) {
- st.menu.close();
- }
- }
-
- @Override
- public void onCloseSystemDialogs(String reason) {
- if (mFeatureId >= 0) {
- mWindow.closeAllPanels();
- }
- }
-
- public android.view.SurfaceHolder.Callback2 willYouTakeTheSurface() {
- return mFeatureId < 0 ? mWindow.mTakeSurfaceCallback : null;
- }
-
- public InputQueue.Callback willYouTakeTheInputQueue() {
- return mFeatureId < 0 ? mWindow.mTakeInputQueueCallback : null;
- }
-
- public void setSurfaceType(int type) {
- mWindow.setType(type);
- }
-
- public void setSurfaceFormat(int format) {
- mWindow.setFormat(format);
- }
-
- public void setSurfaceKeepScreenOn(boolean keepOn) {
- if (keepOn) mWindow.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- else mWindow.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- }
-
- @Override
- public void onRootViewScrollYChanged(int rootScrollY) {
- mRootScrollY = rootScrollY;
- updateColorViewTranslations();
- }
-
- private ActionMode createActionMode(
- int type, ActionMode.Callback2 callback, View originatingView) {
- switch (type) {
- case ActionMode.TYPE_PRIMARY:
- default:
- return createStandaloneActionMode(callback);
- case ActionMode.TYPE_FLOATING:
- return createFloatingActionMode(originatingView, callback);
- }
- }
-
- private void setHandledActionMode(ActionMode mode) {
- if (mode.getType() == ActionMode.TYPE_PRIMARY) {
- setHandledPrimaryActionMode(mode);
- } else if (mode.getType() == ActionMode.TYPE_FLOATING) {
- setHandledFloatingActionMode(mode);
- }
- }
-
- private ActionMode createStandaloneActionMode(ActionMode.Callback callback) {
- endOnGoingFadeAnimation();
- cleanupPrimaryActionMode();
- if (mPrimaryActionModeView == null) {
- if (mWindow.isFloating()) {
- // Use the action bar theme.
- final TypedValue outValue = new TypedValue();
- final Theme baseTheme = mContext.getTheme();
- baseTheme.resolveAttribute(R.attr.actionBarTheme, outValue, true);
-
- final Context actionBarContext;
- if (outValue.resourceId != 0) {
- final Theme actionBarTheme = mContext.getResources().newTheme();
- actionBarTheme.setTo(baseTheme);
- actionBarTheme.applyStyle(outValue.resourceId, true);
-
- actionBarContext = new ContextThemeWrapper(mContext, 0);
- actionBarContext.getTheme().setTo(actionBarTheme);
- } else {
- actionBarContext = mContext;
- }
-
- mPrimaryActionModeView = new ActionBarContextView(actionBarContext);
- mPrimaryActionModePopup = new PopupWindow(actionBarContext, null,
- R.attr.actionModePopupWindowStyle);
- mPrimaryActionModePopup.setWindowLayoutType(
- WindowManager.LayoutParams.TYPE_APPLICATION);
- mPrimaryActionModePopup.setContentView(mPrimaryActionModeView);
- mPrimaryActionModePopup.setWidth(MATCH_PARENT);
-
- actionBarContext.getTheme().resolveAttribute(
- R.attr.actionBarSize, outValue, true);
- final int height = TypedValue.complexToDimensionPixelSize(outValue.data,
- actionBarContext.getResources().getDisplayMetrics());
- mPrimaryActionModeView.setContentHeight(height);
- mPrimaryActionModePopup.setHeight(WRAP_CONTENT);
- mShowPrimaryActionModePopup = new Runnable() {
- public void run() {
- mPrimaryActionModePopup.showAtLocation(
- mPrimaryActionModeView.getApplicationWindowToken(),
- Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0);
- endOnGoingFadeAnimation();
- mFadeAnim = ObjectAnimator.ofFloat(mPrimaryActionModeView, View.ALPHA,
- 0f, 1f);
- mFadeAnim.addListener(new Animator.AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animation) {
- mPrimaryActionModeView.setVisibility(VISIBLE);
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- mPrimaryActionModeView.setAlpha(1f);
- mFadeAnim = null;
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
-
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
-
- }
- });
- mFadeAnim.start();
- }
- };
- } else {
- ViewStub stub = (ViewStub) findViewById(R.id.action_mode_bar_stub);
- if (stub != null) {
- mPrimaryActionModeView = (ActionBarContextView) stub.inflate();
- }
- }
- }
- if (mPrimaryActionModeView != null) {
- mPrimaryActionModeView.killMode();
- ActionMode mode = new StandaloneActionMode(
- mPrimaryActionModeView.getContext(), mPrimaryActionModeView,
- callback, mPrimaryActionModePopup == null);
- return mode;
- }
- return null;
- }
-
- private void endOnGoingFadeAnimation() {
- if (mFadeAnim != null) {
- mFadeAnim.end();
- }
- }
-
- private void setHandledPrimaryActionMode(ActionMode mode) {
- endOnGoingFadeAnimation();
- mPrimaryActionMode = mode;
- mPrimaryActionMode.invalidate();
- mPrimaryActionModeView.initForMode(mPrimaryActionMode);
- if (mPrimaryActionModePopup != null) {
- post(mShowPrimaryActionModePopup);
- } else {
- mFadeAnim = ObjectAnimator.ofFloat(mPrimaryActionModeView, View.ALPHA, 0f, 1f);
- mFadeAnim.addListener(new Animator.AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animation) {
- mPrimaryActionModeView.setVisibility(View.VISIBLE);
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- mPrimaryActionModeView.setAlpha(1f);
- mFadeAnim = null;
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
-
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
-
- }
- });
- mFadeAnim.start();
- }
- mPrimaryActionModeView.sendAccessibilityEvent(
- AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
- }
-
- private ActionMode createFloatingActionMode(
- View originatingView, ActionMode.Callback2 callback) {
- if (mFloatingActionMode != null) {
- mFloatingActionMode.finish();
- }
- cleanupFloatingActionModeViews();
- final FloatingActionMode mode =
- new FloatingActionMode(mContext, callback, originatingView);
- mFloatingActionModeOriginatingView = originatingView;
- mFloatingToolbarPreDrawListener =
- new OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- mode.updateViewLocationInWindow();
- return true;
- }
- };
- return mode;
- }
-
- private void setHandledFloatingActionMode(ActionMode mode) {
- mFloatingActionMode = mode;
- mFloatingToolbar = new FloatingToolbar(mContext, mWindow);
- ((FloatingActionMode) mFloatingActionMode).setFloatingToolbar(mFloatingToolbar);
- mFloatingActionMode.invalidate(); // Will show the floating toolbar if necessary.
- mFloatingActionModeOriginatingView.getViewTreeObserver()
- .addOnPreDrawListener(mFloatingToolbarPreDrawListener);
- }
-
- /**
- * Informs the decor if a non client decor is attached and visible.
- * @param attachedAndVisible true when the decor is visible.
- * Note that this will even be called if there is no non client decor.
- **/
- void enableNonClientDecor(boolean attachedAndVisible) {
- if (mHasNonClientDecor != attachedAndVisible) {
- mHasNonClientDecor = attachedAndVisible;
- if (getForeground() != null) {
- drawableChanged();
- }
- }
- }
-
- /**
- * Returns true if the window has a non client decor.
- * @return If there is a non client decor - even if it is not visible.
- **/
- private boolean windowHasNonClientDecor() {
- return mHasNonClientDecor;
- }
-
- /**
- * Returns true if the Window is free floating and has a shadow (although at some times
- * it might not be displaying it, e.g. during a resize). Note that non overlapping windows
- * do not have a shadow since it could not be seen anyways (a small screen / tablet
- * "tiles" the windows side by side but does not overlap them).
- * @return Returns true when the window has a shadow created by the non client decor.
- **/
- private boolean windowHasShadow() {
- return windowHasNonClientDecor() && StackId.hasWindowShadow(mWindow.mWorkspaceId);
- }
-
- void setWindow(PhoneWindow phoneWindow) {
- mWindow = phoneWindow;
- Context context = getContext();
- if (context instanceof DecorContext) {
- DecorContext decorContex = (DecorContext) context;
- decorContex.setPhoneWindow(mWindow);
- }
- }
-
- /**
- * Clears out internal references when the action mode is destroyed.
- */
- private class ActionModeCallback2Wrapper extends ActionMode.Callback2 {
- private final ActionMode.Callback mWrapped;
-
- public ActionModeCallback2Wrapper(ActionMode.Callback wrapped) {
- mWrapped = wrapped;
- }
-
- public boolean onCreateActionMode(ActionMode mode, Menu menu) {
- return mWrapped.onCreateActionMode(mode, menu);
- }
-
- public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
- requestFitSystemWindows();
- return mWrapped.onPrepareActionMode(mode, menu);
- }
-
- public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
- return mWrapped.onActionItemClicked(mode, item);
- }
-
- public void onDestroyActionMode(ActionMode mode) {
- mWrapped.onDestroyActionMode(mode);
- final boolean isMncApp = mContext.getApplicationInfo().targetSdkVersion
- >= Build.VERSION_CODES.M;
- final boolean isPrimary;
- final boolean isFloating;
- if (isMncApp) {
- isPrimary = mode == mPrimaryActionMode;
- isFloating = mode == mFloatingActionMode;
- if (!isPrimary && mode.getType() == ActionMode.TYPE_PRIMARY) {
- Log.e(TAG, "Destroying unexpected ActionMode instance of TYPE_PRIMARY; "
- + mode + " was not the current primary action mode! Expected "
- + mPrimaryActionMode);
- }
- if (!isFloating && mode.getType() == ActionMode.TYPE_FLOATING) {
- Log.e(TAG, "Destroying unexpected ActionMode instance of TYPE_FLOATING; "
- + mode + " was not the current floating action mode! Expected "
- + mFloatingActionMode);
- }
- } else {
- isPrimary = mode.getType() == ActionMode.TYPE_PRIMARY;
- isFloating = mode.getType() == ActionMode.TYPE_FLOATING;
- }
- if (isPrimary) {
- if (mPrimaryActionModePopup != null) {
- removeCallbacks(mShowPrimaryActionModePopup);
- }
- if (mPrimaryActionModeView != null) {
- endOnGoingFadeAnimation();
- mFadeAnim = ObjectAnimator.ofFloat(mPrimaryActionModeView, View.ALPHA,
- 1f, 0f);
- mFadeAnim.addListener(new Animator.AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animation) {
-
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- mPrimaryActionModeView.setVisibility(GONE);
- if (mPrimaryActionModePopup != null) {
- mPrimaryActionModePopup.dismiss();
- }
- mPrimaryActionModeView.removeAllViews();
- mFadeAnim = null;
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
-
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
-
- }
- });
- mFadeAnim.start();
- }
-
- mPrimaryActionMode = null;
- } else if (isFloating) {
- cleanupFloatingActionModeViews();
- mFloatingActionMode = null;
- }
- if (mWindow.getCallback() != null && !mWindow.isDestroyed()) {
- try {
- mWindow.getCallback().onActionModeFinished(mode);
- } catch (AbstractMethodError ame) {
- // Older apps might not implement this callback method.
- }
- }
- requestFitSystemWindows();
- }
-
- @Override
- public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
- if (mWrapped instanceof ActionMode.Callback2) {
- ((ActionMode.Callback2) mWrapped).onGetContentRect(mode, view, outRect);
- } else {
- super.onGetContentRect(mode, view, outRect);
- }
- }
- }
- }
-
protected DecorView generateDecor(int featureId) {
// System process doesn't have application context and in that case we need to directly use
// the context we have. Otherwise we want the application context, so we don't cling to the
@@ -4147,7 +2593,7 @@
} else {
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
}
- mContentRoot = (ViewGroup) in;
+ decor.mContentRoot = (ViewGroup) in;
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
if (contentParent == null) {
@@ -4450,7 +2896,7 @@
* isn't in our features, this throws an exception).
* @return The panel state.
*/
- private PanelFeatureState getPanelState(int featureId, boolean required) {
+ PanelFeatureState getPanelState(int featureId, boolean required) {
return getPanelState(featureId, required, null);
}
@@ -4914,7 +3360,7 @@
int curAlpha = 255;
}
- private static final class PanelFeatureState {
+ static final class PanelFeatureState {
/** Feature ID for this panel. */
int featureId;
@@ -5316,30 +3762,12 @@
}
}
- private static class ColorViewState {
- View view = null;
- int targetVisibility = View.INVISIBLE;
- boolean present = false;
+ int getLocalFeaturesPrivate() {
+ return super.getLocalFeatures();
+ }
- final int id;
- final int systemUiHideFlag;
- final int translucentFlag;
- final int verticalGravity;
- final int horizontalGravity;
- final String transitionName;
- final int hideWindowFlag;
-
- ColorViewState(int systemUiHideFlag,
- int translucentFlag, int verticalGravity, int horizontalGravity,
- String transitionName, int id, int hideWindowFlag) {
- this.id = id;
- this.systemUiHideFlag = systemUiHideFlag;
- this.translucentFlag = translucentFlag;
- this.verticalGravity = verticalGravity;
- this.horizontalGravity = horizontalGravity;
- this.transitionName = transitionName;
- this.hideWindowFlag = hideWindowFlag;
- }
+ protected void setDefaultWindowFormat(int format) {
+ super.setDefaultWindowFormat(format);
}
void sendCloseSystemWindows() {