AppCompatDelegateImplV7.java revision a9279663ecb98b85bf95a5ba1ebc145756fc13a2
16386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes/* 26386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * Copyright (C) 2013 The Android Open Source Project 36386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * 46386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * Licensed under the Apache License, Version 2.0 (the "License"); 56386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * you may not use this file except in compliance with the License. 66386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * You may obtain a copy of the License at 76386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * 86386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * http://www.apache.org/licenses/LICENSE-2.0 96386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * 106386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * Unless required by applicable law or agreed to in writing, software 116386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * distributed under the License is distributed on an "AS IS" BASIS, 126386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * See the License for the specific language governing permissions and 146386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes * limitations under the License. 156386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes */ 166386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 176386aac7ea9be44d23dcea28d9a02110c174e988Chris Banespackage android.support.v7.app; 186386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 19f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.app.Activity; 2016e8d4dd91083260223c007c797e46bc8f631055Chris Banesimport android.app.Dialog; 216386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.content.Context; 226386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.content.res.Configuration; 2361c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banesimport android.content.res.Resources; 246386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.content.res.TypedArray; 2546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banesimport android.graphics.PixelFormat; 26ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banesimport android.graphics.Rect; 2746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banesimport android.media.AudioManager; 28469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.os.Build; 298902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banesimport android.os.Bundle; 3000d183885b54de433e43118d3032340f40cac8c0Chris Banesimport android.os.Parcel; 3100d183885b54de433e43118d3032340f40cac8c0Chris Banesimport android.os.Parcelable; 32469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.support.annotation.NonNull; 3349c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v4.app.NavUtils; 34f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.support.v4.view.LayoutInflaterCompat; 35f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.support.v4.view.LayoutInflaterFactory; 36ea4f700ac38424954c56df5138ff794def50b019Chris Banesimport android.support.v4.view.OnApplyWindowInsetsListener; 3703fc11b659da1645507062bddda450136e13af35Chris Banesimport android.support.v4.view.ViewCompat; 3849c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v4.view.ViewConfigurationCompat; 39ea4f700ac38424954c56df5138ff794def50b019Chris Banesimport android.support.v4.view.WindowInsetsCompat; 406386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.support.v7.appcompat.R; 412cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banesimport android.support.v7.internal.app.AppCompatViewInflater; 4249c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.internal.app.ToolbarActionBar; 4349c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.internal.app.WindowDecorActionBar; 44878ed08a784cafb112a5d350573b0d1e81c554dbChris Banesimport android.support.v7.internal.view.ContextThemeWrapper; 454c2a95906254748cb9a843b061288265d6e185a9Chris Banesimport android.support.v7.internal.view.StandaloneActionMode; 466386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.support.v7.internal.view.menu.ListMenuPresenter; 476386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.support.v7.internal.view.menu.MenuBuilder; 486386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.support.v7.internal.view.menu.MenuPresenter; 496386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.support.v7.internal.view.menu.MenuView; 504c2a95906254748cb9a843b061288265d6e185a9Chris Banesimport android.support.v7.internal.widget.ActionBarContextView; 5119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.support.v7.internal.widget.ContentFrameLayout; 5249c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.internal.widget.DecorContentParent; 53ea4f700ac38424954c56df5138ff794def50b019Chris Banesimport android.support.v7.internal.widget.FitWindowsViewGroup; 5446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banesimport android.support.v7.internal.widget.TintManager; 554bd5cbd6ca4f1e5ed43217b808068a48f937feabChris Banesimport android.support.v7.internal.widget.ViewStubCompat; 56ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banesimport android.support.v7.internal.widget.ViewUtils; 57d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banesimport android.support.v7.view.ActionMode; 5849c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.widget.Toolbar; 5916e8d4dd91083260223c007c797e46bc8f631055Chris Banesimport android.text.TextUtils; 60cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banesimport android.util.AndroidRuntimeException; 61469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.util.AttributeSet; 6246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banesimport android.util.Log; 6356fd50144df518461398a9b3397ee4842b346708Chris Banesimport android.util.TypedValue; 644c2a95906254748cb9a843b061288265d6e185a9Chris Banesimport android.view.Gravity; 6500d183885b54de433e43118d3032340f40cac8c0Chris Banesimport android.view.KeyCharacterMap; 66dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banesimport android.view.KeyEvent; 67dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banesimport android.view.LayoutInflater; 6830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.Menu; 6930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.MenuItem; 7046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banesimport android.view.MotionEvent; 716386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.view.View; 7249c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.view.ViewConfiguration; 736386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.view.ViewGroup; 7446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banesimport android.view.ViewParent; 756386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.view.Window; 7646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banesimport android.view.WindowManager; 774c2a95906254748cb9a843b061288265d6e185a9Chris Banesimport android.view.accessibility.AccessibilityEvent; 7830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.widget.FrameLayout; 794c2a95906254748cb9a843b061288265d6e185a9Chris Banesimport android.widget.PopupWindow; 8016e8d4dd91083260223c007c797e46bc8f631055Chris Banesimport android.widget.TextView; 816386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 82469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport static android.support.v4.view.WindowCompat.FEATURE_ACTION_BAR; 83469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport static android.support.v4.view.WindowCompat.FEATURE_ACTION_BAR_OVERLAY; 84469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport static android.support.v4.view.WindowCompat.FEATURE_ACTION_MODE_OVERLAY; 8546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banesimport static android.view.ViewGroup.LayoutParams.MATCH_PARENT; 8646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banesimport static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; 8700d183885b54de433e43118d3032340f40cac8c0Chris Banesimport static android.view.Window.FEATURE_OPTIONS_PANEL; 8800d183885b54de433e43118d3032340f40cac8c0Chris Banes 89f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesclass AppCompatDelegateImplV7 extends AppCompatDelegateImplBase 90f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes implements MenuBuilder.Callback, LayoutInflaterFactory { 916386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 9249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private DecorContentParent mDecorContentParent; 9303fc11b659da1645507062bddda450136e13af35Chris Banes private ActionMenuPresenterCallback mActionMenuPresenterCallback; 9403fc11b659da1645507062bddda450136e13af35Chris Banes private PanelMenuPresenterCallback mPanelMenuPresenterCallback; 9503fc11b659da1645507062bddda450136e13af35Chris Banes 964c2a95906254748cb9a843b061288265d6e185a9Chris Banes ActionMode mActionMode; 974c2a95906254748cb9a843b061288265d6e185a9Chris Banes ActionBarContextView mActionModeView; 984c2a95906254748cb9a843b061288265d6e185a9Chris Banes PopupWindow mActionModePopup; 994c2a95906254748cb9a843b061288265d6e185a9Chris Banes Runnable mShowActionModePopup; 1005a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes 1015a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes // true if we have installed a window sub-decor layout. 1025a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes private boolean mSubDecorInstalled; 10303fc11b659da1645507062bddda450136e13af35Chris Banes private ViewGroup mWindowDecor; 104ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes private ViewGroup mSubDecor; 105ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes 10616e8d4dd91083260223c007c797e46bc8f631055Chris Banes private TextView mTitleView; 107ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes private View mStatusGuard; 108d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 109ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // Used to keep track of Progress Bar Window features 110ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private boolean mFeatureProgress, mFeatureIndeterminateProgress; 111ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 1128902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // Used for emulating PanelFeatureState 1138902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes private boolean mClosingActionMenu; 11400d183885b54de433e43118d3032340f40cac8c0Chris Banes private PanelFeatureState[] mPanels; 11500d183885b54de433e43118d3032340f40cac8c0Chris Banes private PanelFeatureState mPreparedPanel; 116556ac47ce764a4a9320b5ac914536e9da2524176Chris Banes 11703fc11b659da1645507062bddda450136e13af35Chris Banes private boolean mInvalidatePanelMenuPosted; 11800d183885b54de433e43118d3032340f40cac8c0Chris Banes private int mInvalidatePanelMenuFeatures; 11903fc11b659da1645507062bddda450136e13af35Chris Banes private final Runnable mInvalidatePanelMenuRunnable = new Runnable() { 12003fc11b659da1645507062bddda450136e13af35Chris Banes @Override 12103fc11b659da1645507062bddda450136e13af35Chris Banes public void run() { 12200d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((mInvalidatePanelMenuFeatures & 1 << FEATURE_OPTIONS_PANEL) != 0) { 12300d183885b54de433e43118d3032340f40cac8c0Chris Banes doInvalidatePanelMenu(FEATURE_OPTIONS_PANEL); 12400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 12500d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((mInvalidatePanelMenuFeatures & 1 << FEATURE_ACTION_BAR) != 0) { 12600d183885b54de433e43118d3032340f40cac8c0Chris Banes doInvalidatePanelMenu(FEATURE_ACTION_BAR); 12700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 12800d183885b54de433e43118d3032340f40cac8c0Chris Banes mInvalidatePanelMenuPosted = false; 12900d183885b54de433e43118d3032340f40cac8c0Chris Banes mInvalidatePanelMenuFeatures = 0; 13003fc11b659da1645507062bddda450136e13af35Chris Banes } 13103fc11b659da1645507062bddda450136e13af35Chris Banes }; 13203fc11b659da1645507062bddda450136e13af35Chris Banes 13349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private boolean mEnableDefaultActionBarUp; 13449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 1357efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell private Rect mTempRect1; 1367efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell private Rect mTempRect2; 1377efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell 1382cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes private AppCompatViewInflater mAppCompatViewInflater; 139fd1eb27a3700de31507de34fd1bcc51830fe876cChris Banes 14016e8d4dd91083260223c007c797e46bc8f631055Chris Banes AppCompatDelegateImplV7(Context context, Window window, AppCompatCallback callback) { 14116e8d4dd91083260223c007c797e46bc8f631055Chris Banes super(context, window, callback); 1426386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 1436386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 1446386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 145f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public void onCreate(Bundle savedInstanceState) { 14649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes super.onCreate(savedInstanceState); 14749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 14816e8d4dd91083260223c007c797e46bc8f631055Chris Banes mWindowDecor = (ViewGroup) mWindow.getDecorView(); 14903fc11b659da1645507062bddda450136e13af35Chris Banes 15016e8d4dd91083260223c007c797e46bc8f631055Chris Banes if (mOriginalWindowCallback instanceof Activity) { 15116e8d4dd91083260223c007c797e46bc8f631055Chris Banes if (NavUtils.getParentActivityName((Activity) mOriginalWindowCallback) != null) { 15216e8d4dd91083260223c007c797e46bc8f631055Chris Banes // Peek at the Action Bar and update it if it already exists 15316e8d4dd91083260223c007c797e46bc8f631055Chris Banes ActionBar ab = peekSupportActionBar(); 15416e8d4dd91083260223c007c797e46bc8f631055Chris Banes if (ab == null) { 15516e8d4dd91083260223c007c797e46bc8f631055Chris Banes mEnableDefaultActionBarUp = true; 15616e8d4dd91083260223c007c797e46bc8f631055Chris Banes } else { 15716e8d4dd91083260223c007c797e46bc8f631055Chris Banes ab.setDefaultDisplayHomeAsUpEnabled(true); 15816e8d4dd91083260223c007c797e46bc8f631055Chris Banes } 15949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 16049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 16149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 16249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 16349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 164f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public void onPostCreate(Bundle savedInstanceState) { 165c826d759805928c84b20e646e442d55483e003c8Chris Banes // Make sure that the sub decor is installed 166c826d759805928c84b20e646e442d55483e003c8Chris Banes ensureSubDecor(); 167c826d759805928c84b20e646e442d55483e003c8Chris Banes } 168c826d759805928c84b20e646e442d55483e003c8Chris Banes 169c826d759805928c84b20e646e442d55483e003c8Chris Banes @Override 1706386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public ActionBar createSupportActionBar() { 17130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell ensureSubDecor(); 17216e8d4dd91083260223c007c797e46bc8f631055Chris Banes ActionBar ab = null; 17316e8d4dd91083260223c007c797e46bc8f631055Chris Banes if (mOriginalWindowCallback instanceof Activity) { 17416e8d4dd91083260223c007c797e46bc8f631055Chris Banes ab = new WindowDecorActionBar((Activity) mOriginalWindowCallback, mOverlayActionBar); 17516e8d4dd91083260223c007c797e46bc8f631055Chris Banes } else if (mOriginalWindowCallback instanceof Dialog) { 17616e8d4dd91083260223c007c797e46bc8f631055Chris Banes ab = new WindowDecorActionBar((Dialog) mOriginalWindowCallback); 17716e8d4dd91083260223c007c797e46bc8f631055Chris Banes } 17816e8d4dd91083260223c007c797e46bc8f631055Chris Banes if (ab != null) { 17916e8d4dd91083260223c007c797e46bc8f631055Chris Banes ab.setDefaultDisplayHomeAsUpEnabled(mEnableDefaultActionBarUp); 18016e8d4dd91083260223c007c797e46bc8f631055Chris Banes } 18149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return ab; 18249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 18349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 18449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 185f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public void setSupportActionBar(Toolbar toolbar) { 18616e8d4dd91083260223c007c797e46bc8f631055Chris Banes if (!(mOriginalWindowCallback instanceof Activity)) { 18716e8d4dd91083260223c007c797e46bc8f631055Chris Banes // Only Activities support custom Action Bars 18816e8d4dd91083260223c007c797e46bc8f631055Chris Banes return; 18916e8d4dd91083260223c007c797e46bc8f631055Chris Banes } 19016e8d4dd91083260223c007c797e46bc8f631055Chris Banes 191da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes final ActionBar ab = getSupportActionBar(); 192da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes if (ab instanceof WindowDecorActionBar) { 19349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes throw new IllegalStateException("This Activity already has an action bar supplied " + 19449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes "by the window decor. Do not request Window.FEATURE_ACTION_BAR and set " + 19549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes "windowActionBar to false in your theme to use a Toolbar instead."); 19649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 197da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes 19816e8d4dd91083260223c007c797e46bc8f631055Chris Banes ToolbarActionBar tbab = new ToolbarActionBar(toolbar, ((Activity) mContext).getTitle(), 19916e8d4dd91083260223c007c797e46bc8f631055Chris Banes mWindow); 2000b216f2263135782c361e122892a12156d5d2ce1Chris Banes setSupportActionBar(tbab); 20116e8d4dd91083260223c007c797e46bc8f631055Chris Banes mWindow.setCallback(tbab.getWrappedWindowCallback()); 2020b216f2263135782c361e122892a12156d5d2ce1Chris Banes tbab.invalidateOptionsMenu(); 2036386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 2046386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 2056386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 2066386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public void onConfigurationChanged(Configuration newConfig) { 2076386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes // If this is called before sub-decor is installed, ActionBar will not 2086386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes // be properly initialized. 2095a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes if (mHasActionBar && mSubDecorInstalled) { 2106386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes // Note: The action bar will need to access 2116386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes // view changes from superclass. 21249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ActionBar ab = getSupportActionBar(); 21349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (ab != null) { 21449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ab.onConfigurationChanged(newConfig); 21549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 2166386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 2176386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 2186386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 2196386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 220a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes public void onStop() { 22149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ActionBar ab = getSupportActionBar(); 222a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes if (ab != null) { 223a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes ab.setShowHideAnimationEnabled(false); 224a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes } 225a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes } 226a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes 227a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes @Override 228a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes public void onPostResume() { 22949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ActionBar ab = getSupportActionBar(); 230a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes if (ab != null) { 231a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes ab.setShowHideAnimationEnabled(true); 232a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes } 233a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes } 234a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes 235a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes @Override 2366386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public void setContentView(View v) { 2376386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes ensureSubDecor(); 23816e8d4dd91083260223c007c797e46bc8f631055Chris Banes ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content); 23956fd50144df518461398a9b3397ee4842b346708Chris Banes contentParent.removeAllViews(); 24056fd50144df518461398a9b3397ee4842b346708Chris Banes contentParent.addView(v); 24116e8d4dd91083260223c007c797e46bc8f631055Chris Banes mOriginalWindowCallback.onContentChanged(); 2426386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 2436386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 2446386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 2456386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public void setContentView(int resId) { 2466386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes ensureSubDecor(); 24716e8d4dd91083260223c007c797e46bc8f631055Chris Banes ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content); 24856fd50144df518461398a9b3397ee4842b346708Chris Banes contentParent.removeAllViews(); 24916e8d4dd91083260223c007c797e46bc8f631055Chris Banes LayoutInflater.from(mContext).inflate(resId, contentParent); 25016e8d4dd91083260223c007c797e46bc8f631055Chris Banes mOriginalWindowCallback.onContentChanged(); 2516386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 2526386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 2536386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 2546386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public void setContentView(View v, ViewGroup.LayoutParams lp) { 2556386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes ensureSubDecor(); 25616e8d4dd91083260223c007c797e46bc8f631055Chris Banes ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content); 25756fd50144df518461398a9b3397ee4842b346708Chris Banes contentParent.removeAllViews(); 25856fd50144df518461398a9b3397ee4842b346708Chris Banes contentParent.addView(v, lp); 25916e8d4dd91083260223c007c797e46bc8f631055Chris Banes mOriginalWindowCallback.onContentChanged(); 2606386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 2616386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 2626386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 2636386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public void addContentView(View v, ViewGroup.LayoutParams lp) { 2646386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes ensureSubDecor(); 26516e8d4dd91083260223c007c797e46bc8f631055Chris Banes ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content); 26656fd50144df518461398a9b3397ee4842b346708Chris Banes contentParent.addView(v, lp); 26716e8d4dd91083260223c007c797e46bc8f631055Chris Banes mOriginalWindowCallback.onContentChanged(); 268d64322f4b9686fabfd5a03f402d50a8e3fe5adedChris Banes } 269d64322f4b9686fabfd5a03f402d50a8e3fe5adedChris Banes 270f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes private void ensureSubDecor() { 27156fd50144df518461398a9b3397ee4842b346708Chris Banes if (!mSubDecorInstalled) { 2720f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes final LayoutInflater inflater = LayoutInflater.from(mContext); 2734b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes 2740f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes if (!mWindowNoTitle) { 2750f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes if (mIsFloating) { 2760f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes // If we're floating, inflate the dialog title decor 2770f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes mSubDecor = (ViewGroup) inflater.inflate( 2780f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes R.layout.abc_dialog_title_material, null); 279a9279663ecb98b85bf95a5ba1ebc145756fc13a2Chris Banes 280a9279663ecb98b85bf95a5ba1ebc145756fc13a2Chris Banes // Floating windows can never have an action bar, reset the flags 281a9279663ecb98b85bf95a5ba1ebc145756fc13a2Chris Banes mHasActionBar = mOverlayActionBar = false; 2820f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes } else if (mHasActionBar) { 2830f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes /** 2840f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes * This needs some explanation. As we can not use the android:theme attribute 2850f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes * pre-L, we emulate it by manually creating a LayoutInflater using a 2860f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes * ContextThemeWrapper pointing to actionBarTheme. 2870f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes */ 2880f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes TypedValue outValue = new TypedValue(); 2890f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes mContext.getTheme().resolveAttribute(R.attr.actionBarTheme, outValue, true); 2900f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes 2910f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes Context themedContext; 2920f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes if (outValue.resourceId != 0) { 2930f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes themedContext = new ContextThemeWrapper(mContext, outValue.resourceId); 2940f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes } else { 2950f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes themedContext = mContext; 2960f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes } 2970f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes 2980f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes // Now inflate the view using the themed context and set it as the content view 2990f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes mSubDecor = (ViewGroup) LayoutInflater.from(themedContext) 3000f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes .inflate(R.layout.abc_screen_toolbar, null); 3010f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes 3020f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes mDecorContentParent = (DecorContentParent) mSubDecor 3030f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes .findViewById(R.id.decor_content_parent); 3040f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes mDecorContentParent.setWindowCallback(getWindowCallback()); 3050f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes 3060f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes /** 3070f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes * Propagate features to DecorContentParent 3080f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes */ 3090f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes if (mOverlayActionBar) { 3100f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes mDecorContentParent.initFeature(FEATURE_ACTION_BAR_OVERLAY); 3110f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes } 3120f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes if (mFeatureProgress) { 3130f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes mDecorContentParent.initFeature(Window.FEATURE_PROGRESS); 3140f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes } 3150f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes if (mFeatureIndeterminateProgress) { 3160f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes mDecorContentParent.initFeature(Window.FEATURE_INDETERMINATE_PROGRESS); 3170f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes } 31856fd50144df518461398a9b3397ee4842b346708Chris Banes } 31956fd50144df518461398a9b3397ee4842b346708Chris Banes } else { 3200f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes if (mOverlayActionMode) { 3210f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes mSubDecor = (ViewGroup) inflater.inflate( 3220f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes R.layout.abc_screen_simple_overlay_action_mode, null); 323ea4f700ac38424954c56df5138ff794def50b019Chris Banes } else { 3240f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes mSubDecor = (ViewGroup) inflater.inflate(R.layout.abc_screen_simple, null); 325ea4f700ac38424954c56df5138ff794def50b019Chris Banes } 326ea4f700ac38424954c56df5138ff794def50b019Chris Banes 327ea4f700ac38424954c56df5138ff794def50b019Chris Banes if (Build.VERSION.SDK_INT >= 21) { 328ea4f700ac38424954c56df5138ff794def50b019Chris Banes // If we're running on L or above, we can rely on ViewCompat's 329ea4f700ac38424954c56df5138ff794def50b019Chris Banes // setOnApplyWindowInsetsListener 330ea4f700ac38424954c56df5138ff794def50b019Chris Banes ViewCompat.setOnApplyWindowInsetsListener(mSubDecor, 331ea4f700ac38424954c56df5138ff794def50b019Chris Banes new OnApplyWindowInsetsListener() { 332ea4f700ac38424954c56df5138ff794def50b019Chris Banes @Override 333ea4f700ac38424954c56df5138ff794def50b019Chris Banes public WindowInsetsCompat onApplyWindowInsets(View v, 334ea4f700ac38424954c56df5138ff794def50b019Chris Banes WindowInsetsCompat insets) { 335ea4f700ac38424954c56df5138ff794def50b019Chris Banes final int top = insets.getSystemWindowInsetTop(); 336ea4f700ac38424954c56df5138ff794def50b019Chris Banes final int newTop = updateStatusGuard(top); 337ea4f700ac38424954c56df5138ff794def50b019Chris Banes 338ea4f700ac38424954c56df5138ff794def50b019Chris Banes if (top != newTop) { 3393040adc60c191aca58e34a01428db628604924c5Chris Banes insets = insets.replaceSystemWindowInsets( 340ea4f700ac38424954c56df5138ff794def50b019Chris Banes insets.getSystemWindowInsetLeft(), 341ea4f700ac38424954c56df5138ff794def50b019Chris Banes newTop, 342ea4f700ac38424954c56df5138ff794def50b019Chris Banes insets.getSystemWindowInsetRight(), 343ea4f700ac38424954c56df5138ff794def50b019Chris Banes insets.getSystemWindowInsetBottom()); 344ea4f700ac38424954c56df5138ff794def50b019Chris Banes } 3453040adc60c191aca58e34a01428db628604924c5Chris Banes 3463040adc60c191aca58e34a01428db628604924c5Chris Banes // Now apply the insets on our view 3473040adc60c191aca58e34a01428db628604924c5Chris Banes return ViewCompat.onApplyWindowInsets(v, insets); 348ea4f700ac38424954c56df5138ff794def50b019Chris Banes } 349ea4f700ac38424954c56df5138ff794def50b019Chris Banes }); 350ea4f700ac38424954c56df5138ff794def50b019Chris Banes } else { 351ea4f700ac38424954c56df5138ff794def50b019Chris Banes // Else, we need to use our own FitWindowsViewGroup handling 352ea4f700ac38424954c56df5138ff794def50b019Chris Banes ((FitWindowsViewGroup) mSubDecor).setOnFitSystemWindowsListener( 353ea4f700ac38424954c56df5138ff794def50b019Chris Banes new FitWindowsViewGroup.OnFitSystemWindowsListener() { 354ea4f700ac38424954c56df5138ff794def50b019Chris Banes @Override 355ea4f700ac38424954c56df5138ff794def50b019Chris Banes public void onFitSystemWindows(Rect insets) { 356ea4f700ac38424954c56df5138ff794def50b019Chris Banes insets.top = updateStatusGuard(insets.top); 357ea4f700ac38424954c56df5138ff794def50b019Chris Banes } 358ea4f700ac38424954c56df5138ff794def50b019Chris Banes }); 359ea4f700ac38424954c56df5138ff794def50b019Chris Banes } 3603954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes } 3613954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes 3620f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes if (mSubDecor == null) { 3630f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes throw new IllegalArgumentException( 3640f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes "AppCompat does not support the current theme features"); 3650f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes } 3660f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes 36716e8d4dd91083260223c007c797e46bc8f631055Chris Banes if (mDecorContentParent == null) { 36816e8d4dd91083260223c007c797e46bc8f631055Chris Banes mTitleView = (TextView) mSubDecor.findViewById(R.id.title); 36916e8d4dd91083260223c007c797e46bc8f631055Chris Banes } 37016e8d4dd91083260223c007c797e46bc8f631055Chris Banes 3711f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes // Make the decor optionally fit system windows, like the window's decor 372ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes ViewUtils.makeOptionalFitsSystemWindows(mSubDecor); 3731f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes 37416e8d4dd91083260223c007c797e46bc8f631055Chris Banes final ViewGroup decorContent = (ViewGroup) mWindow.findViewById(android.R.id.content); 37519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes final ContentFrameLayout abcContent = (ContentFrameLayout) mSubDecor.findViewById( 376c826d759805928c84b20e646e442d55483e003c8Chris Banes R.id.action_bar_activity_content); 377c826d759805928c84b20e646e442d55483e003c8Chris Banes 378c826d759805928c84b20e646e442d55483e003c8Chris Banes // There might be Views already added to the Window's content view so we need to 379c826d759805928c84b20e646e442d55483e003c8Chris Banes // migrate them to our content view 380c826d759805928c84b20e646e442d55483e003c8Chris Banes while (decorContent.getChildCount() > 0) { 381c826d759805928c84b20e646e442d55483e003c8Chris Banes final View child = decorContent.getChildAt(0); 382c826d759805928c84b20e646e442d55483e003c8Chris Banes decorContent.removeViewAt(0); 383c826d759805928c84b20e646e442d55483e003c8Chris Banes abcContent.addView(child); 384c826d759805928c84b20e646e442d55483e003c8Chris Banes } 385c826d759805928c84b20e646e442d55483e003c8Chris Banes 386f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes // Now set the Window's content view with the decor 38716e8d4dd91083260223c007c797e46bc8f631055Chris Banes mWindow.setContentView(mSubDecor); 3881f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes 38992b18eb0263ef2421fda5bf977fea3bf044bf941Chris Banes // Change our content FrameLayout to use the android.R.id.content id. 39092b18eb0263ef2421fda5bf977fea3bf044bf941Chris Banes // Useful for fragments. 3914b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes decorContent.setId(View.NO_ID); 39292b18eb0263ef2421fda5bf977fea3bf044bf941Chris Banes abcContent.setId(android.R.id.content); 39392b18eb0263ef2421fda5bf977fea3bf044bf941Chris Banes 3944b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes // The decorContent may have a foreground drawable set (windowContentOverlay). 3954b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes // Remove this as we handle it ourselves 3964b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes if (decorContent instanceof FrameLayout) { 3974b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes ((FrameLayout) decorContent).setForeground(null); 3984b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes } 3994b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes 40016e8d4dd91083260223c007c797e46bc8f631055Chris Banes // If a title was set before we installed the decor, propogate it now 40116e8d4dd91083260223c007c797e46bc8f631055Chris Banes CharSequence title = getTitle(); 40216e8d4dd91083260223c007c797e46bc8f631055Chris Banes if (!TextUtils.isEmpty(title)) { 40316e8d4dd91083260223c007c797e46bc8f631055Chris Banes onTitleChanged(title); 404f53c7bf3146bf9bcba46324f9f06449df475be36Chris Banes } 405556ac47ce764a4a9320b5ac914536e9da2524176Chris Banes 40619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes applyFixedSizeWindow(abcContent); 40756fd50144df518461398a9b3397ee4842b346708Chris Banes 40816e8d4dd91083260223c007c797e46bc8f631055Chris Banes onSubDecorInstalled(mSubDecor); 40949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 410f53c7bf3146bf9bcba46324f9f06449df475be36Chris Banes mSubDecorInstalled = true; 4118902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 41200d183885b54de433e43118d3032340f40cac8c0Chris Banes // Invalidate if the panel menu hasn't been created before this. 41300d183885b54de433e43118d3032340f40cac8c0Chris Banes // Panel menu invalidation is deferred avoiding application onCreateOptionsMenu 41400d183885b54de433e43118d3032340f40cac8c0Chris Banes // being called in the middle of onCreate or similar. 41500d183885b54de433e43118d3032340f40cac8c0Chris Banes // A pending invalidation will typically be resolved before the posted message 41600d183885b54de433e43118d3032340f40cac8c0Chris Banes // would run normally in order to satisfy instance state restoration. 41700d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false); 4189b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (!isDestroyed() && (st == null || st.menu == null)) { 41900d183885b54de433e43118d3032340f40cac8c0Chris Banes invalidatePanelMenu(FEATURE_ACTION_BAR); 42000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 4216386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 4226386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 4236386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 42416e8d4dd91083260223c007c797e46bc8f631055Chris Banes void onSubDecorInstalled(ViewGroup subDecor) {} 42549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 42619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes private void applyFixedSizeWindow(ContentFrameLayout contentFrameLayout) { 427d8b7157eae680353a2821dca3c9e52b3aaf737a5Chris Banes // This is a bit weird. In the framework, the window sizing attributes control 428d8b7157eae680353a2821dca3c9e52b3aaf737a5Chris Banes // the decor view's size, meaning that any padding is inset for the min/max widths below. 429d8b7157eae680353a2821dca3c9e52b3aaf737a5Chris Banes // We don't control measurement at that level, so we need to workaround it by making sure 430d8b7157eae680353a2821dca3c9e52b3aaf737a5Chris Banes // that the decor view's padding is taken into account. 431d8b7157eae680353a2821dca3c9e52b3aaf737a5Chris Banes contentFrameLayout.setDecorPadding(mWindowDecor.getPaddingLeft(), 432d8b7157eae680353a2821dca3c9e52b3aaf737a5Chris Banes mWindowDecor.getPaddingTop(), mWindowDecor.getPaddingRight(), 433d8b7157eae680353a2821dca3c9e52b3aaf737a5Chris Banes mWindowDecor.getPaddingBottom()); 434d8b7157eae680353a2821dca3c9e52b3aaf737a5Chris Banes 435d8b7157eae680353a2821dca3c9e52b3aaf737a5Chris Banes 43616e8d4dd91083260223c007c797e46bc8f631055Chris Banes TypedArray a = mContext.obtainStyledAttributes(R.styleable.Theme); 43719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes a.getValue(R.styleable.Theme_windowMinWidthMajor, contentFrameLayout.getMinWidthMajor()); 43819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes a.getValue(R.styleable.Theme_windowMinWidthMinor, contentFrameLayout.getMinWidthMinor()); 43956fd50144df518461398a9b3397ee4842b346708Chris Banes 44049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (a.hasValue(R.styleable.Theme_windowFixedWidthMajor)) { 44119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes a.getValue(R.styleable.Theme_windowFixedWidthMajor, 44219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes contentFrameLayout.getFixedWidthMajor()); 44356fd50144df518461398a9b3397ee4842b346708Chris Banes } 44449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (a.hasValue(R.styleable.Theme_windowFixedWidthMinor)) { 44519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes a.getValue(R.styleable.Theme_windowFixedWidthMinor, 44619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes contentFrameLayout.getFixedWidthMinor()); 44756fd50144df518461398a9b3397ee4842b346708Chris Banes } 44849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (a.hasValue(R.styleable.Theme_windowFixedHeightMajor)) { 44919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes a.getValue(R.styleable.Theme_windowFixedHeightMajor, 45019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes contentFrameLayout.getFixedHeightMajor()); 45156fd50144df518461398a9b3397ee4842b346708Chris Banes } 45249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (a.hasValue(R.styleable.Theme_windowFixedHeightMinor)) { 45319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes a.getValue(R.styleable.Theme_windowFixedHeightMinor, 45419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes contentFrameLayout.getFixedHeightMinor()); 45556fd50144df518461398a9b3397ee4842b346708Chris Banes } 45656fd50144df518461398a9b3397ee4842b346708Chris Banes a.recycle(); 45719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes 45819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes contentFrameLayout.requestLayout(); 45956fd50144df518461398a9b3397ee4842b346708Chris Banes } 46056fd50144df518461398a9b3397ee4842b346708Chris Banes 4616386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 462f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public boolean requestWindowFeature(int featureId) { 4636386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes switch (featureId) { 46400d183885b54de433e43118d3032340f40cac8c0Chris Banes case FEATURE_ACTION_BAR: 465cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes throwFeatureRequestIfSubDecorInstalled(); 4665a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes mHasActionBar = true; 4676386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes return true; 46800d183885b54de433e43118d3032340f40cac8c0Chris Banes case FEATURE_ACTION_BAR_OVERLAY: 469cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes throwFeatureRequestIfSubDecorInstalled(); 4705a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes mOverlayActionBar = true; 4716386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes return true; 47200d183885b54de433e43118d3032340f40cac8c0Chris Banes case FEATURE_ACTION_MODE_OVERLAY: 473cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes throwFeatureRequestIfSubDecorInstalled(); 474de9f38cc4a30b33ac46b105edf470fbc4a044e99Chris Banes mOverlayActionMode = true; 475de9f38cc4a30b33ac46b105edf470fbc4a044e99Chris Banes return true; 476ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes case Window.FEATURE_PROGRESS: 477cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes throwFeatureRequestIfSubDecorInstalled(); 478ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mFeatureProgress = true; 479ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return true; 480ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes case Window.FEATURE_INDETERMINATE_PROGRESS: 481cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes throwFeatureRequestIfSubDecorInstalled(); 482ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mFeatureIndeterminateProgress = true; 483ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return true; 48419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes case Window.FEATURE_NO_TITLE: 48519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes throwFeatureRequestIfSubDecorInstalled(); 48619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes mWindowNoTitle = true; 48719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes return true; 4886386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 489cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes 49016e8d4dd91083260223c007c797e46bc8f631055Chris Banes return mWindow.requestFeature(featureId); 4916386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 4926386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 4936386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 49416e8d4dd91083260223c007c797e46bc8f631055Chris Banes void onTitleChanged(CharSequence title) { 49549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mDecorContentParent != null) { 49649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mDecorContentParent.setWindowTitle(title); 49749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else if (getSupportActionBar() != null) { 498ca58f2ce7cd9f0e0f2c4a46c3bcc98013209f6b3Chris Banes getSupportActionBar().setWindowTitle(title); 49916e8d4dd91083260223c007c797e46bc8f631055Chris Banes } else if (mTitleView != null) { 50016e8d4dd91083260223c007c797e46bc8f631055Chris Banes mTitleView.setText(title); 5016386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 5026386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 5036386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 5046386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 505f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes boolean onPanelClosed(final int featureId, Menu menu) { 50600d183885b54de433e43118d3032340f40cac8c0Chris Banes if (featureId == FEATURE_ACTION_BAR) { 50700d183885b54de433e43118d3032340f40cac8c0Chris Banes ActionBar ab = getSupportActionBar(); 50800d183885b54de433e43118d3032340f40cac8c0Chris Banes if (ab != null) { 50900d183885b54de433e43118d3032340f40cac8c0Chris Banes ab.dispatchMenuVisibilityChanged(false); 51000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 511f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes return true; 512436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes } else if (featureId == FEATURE_OPTIONS_PANEL) { 513436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes // Make sure that the options panel is closed. This is mainly used when we're using a 514436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes // ToolbarActionBar 515436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes PanelFeatureState st = getPanelState(featureId, true); 516436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes if (st.isOpen) { 517436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes closePanel(st, false); 518436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes } 519c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes } 520f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes return false; 521c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes } 522c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes 523c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes @Override 52400d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean onMenuOpened(final int featureId, Menu menu) { 52500d183885b54de433e43118d3032340f40cac8c0Chris Banes if (featureId == FEATURE_ACTION_BAR) { 52600d183885b54de433e43118d3032340f40cac8c0Chris Banes ActionBar ab = getSupportActionBar(); 52700d183885b54de433e43118d3032340f40cac8c0Chris Banes if (ab != null) { 52800d183885b54de433e43118d3032340f40cac8c0Chris Banes ab.dispatchMenuVisibilityChanged(true); 52900d183885b54de433e43118d3032340f40cac8c0Chris Banes } 53000d183885b54de433e43118d3032340f40cac8c0Chris Banes return true; 531c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes } 532f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes return false; 53303fc11b659da1645507062bddda450136e13af35Chris Banes } 53403fc11b659da1645507062bddda450136e13af35Chris Banes 53503fc11b659da1645507062bddda450136e13af35Chris Banes @Override 5366386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { 537f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes final Window.Callback cb = getWindowCallback(); 5389b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (cb != null && !isDestroyed()) { 5399b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes final PanelFeatureState panel = findMenuPanel(menu.getRootMenu()); 5409b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (panel != null) { 5419b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes return cb.onMenuItemSelected(panel.featureId, item); 5429b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes } 5439b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes } 5449b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes return false; 5456386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 5466386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 5476386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 5486386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public void onMenuModeChange(MenuBuilder menu) { 5496386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes reopenMenu(menu, true); 5506386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 5516386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 5526386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 553d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes public ActionMode startSupportActionMode(ActionMode.Callback callback) { 554d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes if (callback == null) { 555d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes throw new IllegalArgumentException("ActionMode callback can not be null."); 556d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 557d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 558d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes if (mActionMode != null) { 559d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes mActionMode.finish(); 560d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 561d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 562547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes final ActionMode.Callback wrappedCallback = new ActionModeCallbackWrapperV7(callback); 563d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 56449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ActionBar ab = getSupportActionBar(); 565d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes if (ab != null) { 5665a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes mActionMode = ab.startActionMode(wrappedCallback); 567f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes if (mActionMode != null && mAppCompatCallback != null) { 568f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes mAppCompatCallback.onSupportActionModeStarted(mActionMode); 5690bf48858279237f95d6aad565a074490745491cdChris Banes } 570d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 571d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 5720bf48858279237f95d6aad565a074490745491cdChris Banes if (mActionMode == null) { 5730bf48858279237f95d6aad565a074490745491cdChris Banes // If the action bar didn't provide an action mode, start the emulated window one 5740bf48858279237f95d6aad565a074490745491cdChris Banes mActionMode = startSupportActionModeFromWindow(wrappedCallback); 575d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 5760bf48858279237f95d6aad565a074490745491cdChris Banes 577d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes return mActionMode; 578d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 579d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 580d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes @Override 581f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public void invalidateOptionsMenu() { 582f2045f06bdfc9e2cc40a734e41e45d11adf2bc23Chris Banes final ActionBar ab = getSupportActionBar(); 583f2045f06bdfc9e2cc40a734e41e45d11adf2bc23Chris Banes if (ab != null && ab.invalidateOptionsMenu()) return; 584f2045f06bdfc9e2cc40a734e41e45d11adf2bc23Chris Banes 58500d183885b54de433e43118d3032340f40cac8c0Chris Banes invalidatePanelMenu(FEATURE_OPTIONS_PANEL); 5866386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 5876386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 5884c2a95906254748cb9a843b061288265d6e185a9Chris Banes @Override 5894c2a95906254748cb9a843b061288265d6e185a9Chris Banes ActionMode startSupportActionModeFromWindow(ActionMode.Callback callback) { 5904c2a95906254748cb9a843b061288265d6e185a9Chris Banes if (mActionMode != null) { 5914c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionMode.finish(); 5924c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 5934c2a95906254748cb9a843b061288265d6e185a9Chris Banes 594547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes final ActionMode.Callback wrappedCallback = new ActionModeCallbackWrapperV7(callback); 595547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes ActionMode mode = null; 596547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes if (mAppCompatCallback != null && !isDestroyed()) { 597547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes try { 598547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mode = mAppCompatCallback.onWindowStartingSupportActionMode(wrappedCallback); 599547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } catch (AbstractMethodError ame) { 600547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes // Older apps might not implement this callback method. 6014c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 6024c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 6034c2a95906254748cb9a843b061288265d6e185a9Chris Banes 604547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes if (mode != null) { 605547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionMode = mode; 606547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } else { 607547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes if (mActionModeView == null) { 608547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes if (mIsFloating) { 609547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes // Use the action bar theme. 610547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes final TypedValue outValue = new TypedValue(); 611547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes final Resources.Theme baseTheme = mContext.getTheme(); 612547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes baseTheme.resolveAttribute(R.attr.actionBarTheme, outValue, true); 613547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes 614547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes final Context actionBarContext; 615547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes if (outValue.resourceId != 0) { 616547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes final Resources.Theme actionBarTheme = mContext.getResources().newTheme(); 617547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes actionBarTheme.setTo(baseTheme); 618547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes actionBarTheme.applyStyle(outValue.resourceId, true); 619547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes 620547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes actionBarContext = new ContextThemeWrapper(mContext, 0); 621547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes actionBarContext.getTheme().setTo(actionBarTheme); 622547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } else { 623547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes actionBarContext = mContext; 624547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } 625547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes 626547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModeView = new ActionBarContextView(actionBarContext); 627547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModePopup = new PopupWindow(actionBarContext, null, 628547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes R.attr.actionModePopupWindowStyle); 629547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModePopup.setContentView(mActionModeView); 630547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModePopup.setWidth(ViewGroup.LayoutParams.MATCH_PARENT); 631547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes 632547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes actionBarContext.getTheme().resolveAttribute( 633547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes R.attr.actionBarSize, outValue, true); 634547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes final int height = TypedValue.complexToDimensionPixelSize(outValue.data, 635547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes actionBarContext.getResources().getDisplayMetrics()); 636547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModeView.setContentHeight(height); 637547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModePopup.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); 638547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mShowActionModePopup = new Runnable() { 639547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes public void run() { 640547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModePopup.showAtLocation( 641547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModeView, 642547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0); 643547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } 644547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes }; 645547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } else { 646547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes ViewStubCompat stub = (ViewStubCompat) mSubDecor 647547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes .findViewById(R.id.action_mode_bar_stub); 648547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes if (stub != null) { 649547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes // Set the layout inflater so that it is inflated with the action bar's context 650547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes stub.setLayoutInflater(LayoutInflater.from(getActionBarThemedContext())); 651547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModeView = (ActionBarContextView) stub.inflate(); 652547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } 6534c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 654547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } 655ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes 656547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes if (mActionModeView != null) { 657547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModeView.killMode(); 658547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mode = new StandaloneActionMode(mActionModeView.getContext(), mActionModeView, 659547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes wrappedCallback, mActionModePopup == null); 660547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes if (callback.onCreateActionMode(mode, mode.getMenu())) { 661547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mode.invalidate(); 662547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModeView.initForMode(mode); 663547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModeView.setVisibility(View.VISIBLE); 664547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionMode = mode; 665547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes if (mActionModePopup != null) { 666547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mWindow.getDecorView().post(mShowActionModePopup); 667547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } 668547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModeView.sendAccessibilityEvent( 669547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); 670547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes 671547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes if (mActionModeView.getParent() != null) { 672547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes ViewCompat.requestApplyInsets((View) mActionModeView.getParent()); 673547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } 674547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } else { 675547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionMode = null; 676ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 6774c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 6784c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 679f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes if (mActionMode != null && mAppCompatCallback != null) { 680f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes mAppCompatCallback.onSupportActionModeStarted(mActionMode); 6814c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 6824c2a95906254748cb9a843b061288265d6e185a9Chris Banes return mActionMode; 6834c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 6844c2a95906254748cb9a843b061288265d6e185a9Chris Banes 685f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes boolean onBackPressed() { 686d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes // Back cancels action modes first. 687d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes if (mActionMode != null) { 688d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes mActionMode.finish(); 689d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes return true; 690d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 691d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 692d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes // Next collapse any expanded action views. 69349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ActionBar ab = getSupportActionBar(); 69449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (ab != null && ab.collapseActionView()) { 695d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes return true; 696d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 697d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 698f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes // Let the call through... 699d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes return false; 700d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 701d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 702d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes @Override 70300d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean onKeyShortcut(int keyCode, KeyEvent ev) { 704d15ee7df01f2f48b536a610c4739f33b226d3f81Chris Banes // Let the Action Bar have a chance at handling the shortcut 705d15ee7df01f2f48b536a610c4739f33b226d3f81Chris Banes ActionBar ab = getSupportActionBar(); 706d15ee7df01f2f48b536a610c4739f33b226d3f81Chris Banes if (ab != null && ab.onKeyShortcut(keyCode, ev)) { 707d15ee7df01f2f48b536a610c4739f33b226d3f81Chris Banes return true; 708d15ee7df01f2f48b536a610c4739f33b226d3f81Chris Banes } 709d15ee7df01f2f48b536a610c4739f33b226d3f81Chris Banes 710dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // If the panel is already prepared, then perform the shortcut using it. 71100d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean handled; 71200d183885b54de433e43118d3032340f40cac8c0Chris Banes if (mPreparedPanel != null) { 71300d183885b54de433e43118d3032340f40cac8c0Chris Banes handled = performPanelShortcut(mPreparedPanel, ev.getKeyCode(), ev, 71400d183885b54de433e43118d3032340f40cac8c0Chris Banes Menu.FLAG_PERFORM_NO_CLOSE); 71500d183885b54de433e43118d3032340f40cac8c0Chris Banes if (handled) { 71600d183885b54de433e43118d3032340f40cac8c0Chris Banes if (mPreparedPanel != null) { 71700d183885b54de433e43118d3032340f40cac8c0Chris Banes mPreparedPanel.isHandled = true; 71800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 71900d183885b54de433e43118d3032340f40cac8c0Chris Banes return true; 72000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 72100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 72200d183885b54de433e43118d3032340f40cac8c0Chris Banes 72300d183885b54de433e43118d3032340f40cac8c0Chris Banes // If the panel is not prepared, then we may be trying to handle a shortcut key 72400d183885b54de433e43118d3032340f40cac8c0Chris Banes // combination such as Control+C. Temporarily prepare the panel then mark it 72500d183885b54de433e43118d3032340f40cac8c0Chris Banes // unprepared again when finished to ensure that the panel will again be prepared 72600d183885b54de433e43118d3032340f40cac8c0Chris Banes // the next time it is shown for real. 72700d183885b54de433e43118d3032340f40cac8c0Chris Banes if (mPreparedPanel == null) { 72800d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true); 72900d183885b54de433e43118d3032340f40cac8c0Chris Banes preparePanel(st, ev); 73000d183885b54de433e43118d3032340f40cac8c0Chris Banes handled = performPanelShortcut(st, ev.getKeyCode(), ev, Menu.FLAG_PERFORM_NO_CLOSE); 73100d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isPrepared = false; 73200d183885b54de433e43118d3032340f40cac8c0Chris Banes if (handled) { 73300d183885b54de433e43118d3032340f40cac8c0Chris Banes return true; 73400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 73500d183885b54de433e43118d3032340f40cac8c0Chris Banes } 73600d183885b54de433e43118d3032340f40cac8c0Chris Banes return false; 737dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 738dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 739dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes @Override 74046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes boolean dispatchKeyEvent(KeyEvent event) { 74146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes final int keyCode = event.getKeyCode(); 74246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes final int action = event.getAction(); 74346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes final boolean isDown = action == KeyEvent.ACTION_DOWN; 74446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 74546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return isDown ? onKeyDown(keyCode, event) : onKeyUp(keyCode, event); 74646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 74746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 748f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes boolean onKeyUp(int keyCode, KeyEvent event) { 74946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes switch (keyCode) { 75046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes case KeyEvent.KEYCODE_MENU: 75146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes onKeyUpPanel(Window.FEATURE_OPTIONS_PANEL, event); 75246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return true; 75346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes case KeyEvent.KEYCODE_BACK: 75446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes PanelFeatureState st = getPanelState(Window.FEATURE_OPTIONS_PANEL, false); 75546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (st != null && st.isOpen) { 75646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes closePanel(st, true); 75746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return true; 75846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 759f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes if (onBackPressed()) { 760f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes return true; 761f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 76246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes break; 76346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 76446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return false; 76546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 76646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 767f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes boolean onKeyDown(int keyCode, KeyEvent event) { 768f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes switch (keyCode) { 769f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes case KeyEvent.KEYCODE_MENU: 770f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes onKeyDownPanel(Window.FEATURE_OPTIONS_PANEL, event); 771f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes return true; 77246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 77346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 774dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // On API v7-10 we need to manually call onKeyShortcut() as this is not called 775dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // from the Activity 77646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { 77746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return onKeyShortcut(keyCode, event); 77846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 77946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return false; 780dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 781dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 782469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes @Override 783f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public View createView(View parent, final String name, @NonNull Context context, 784fd1eb27a3700de31507de34fd1bcc51830fe876cChris Banes @NonNull AttributeSet attrs) { 785a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes final boolean isPre21 = Build.VERSION.SDK_INT < 21; 786878ed08a784cafb112a5d350573b0d1e81c554dbChris Banes 7872cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes if (mAppCompatViewInflater == null) { 7882cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes mAppCompatViewInflater = new AppCompatViewInflater(mContext); 789469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 790fd1eb27a3700de31507de34fd1bcc51830fe876cChris Banes 791a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes // We only want the View to inherit it's context from the parent if it is from the 792a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes // apps content, and not part of our sub-decor 793a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes final boolean inheritContext = isPre21 && mSubDecorInstalled && parent != null 794a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes && parent.getId() != android.R.id.content; 795a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes 7962cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes return mAppCompatViewInflater.createView(parent, name, context, attrs, 797a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes inheritContext, isPre21); 798469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 799469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 800f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes @Override 801f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public void installViewFactory() { 80216e8d4dd91083260223c007c797e46bc8f631055Chris Banes LayoutInflater layoutInflater = LayoutInflater.from(mContext); 803f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes if (layoutInflater.getFactory() == null) { 804f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes LayoutInflaterCompat.setFactory(layoutInflater, this); 805f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } else { 806f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes Log.i(TAG, "The Activity's LayoutInflater already has a Factory installed" 807f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes + " so we can not install AppCompat's"); 808f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 809f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 810f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 811f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes /** 812f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes * From {@link android.support.v4.view.LayoutInflaterFactory} 813f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes */ 814f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes @Override 815498356fea126122c3e3720a419969055cb889428Chris Banes public final View onCreateView(View parent, String name, 816f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes Context context, AttributeSet attrs) { 817498356fea126122c3e3720a419969055cb889428Chris Banes // First let the Activity's Factory try and inflate the view 818498356fea126122c3e3720a419969055cb889428Chris Banes final View view = callActivityOnCreateView(parent, name, context, attrs); 819498356fea126122c3e3720a419969055cb889428Chris Banes if (view != null) { 820498356fea126122c3e3720a419969055cb889428Chris Banes return view; 821498356fea126122c3e3720a419969055cb889428Chris Banes } 822498356fea126122c3e3720a419969055cb889428Chris Banes 823498356fea126122c3e3720a419969055cb889428Chris Banes // If the Factory didn't handle it, let our createView() method try 824498356fea126122c3e3720a419969055cb889428Chris Banes return createView(parent, name, context, attrs); 825498356fea126122c3e3720a419969055cb889428Chris Banes } 82616e8d4dd91083260223c007c797e46bc8f631055Chris Banes 827498356fea126122c3e3720a419969055cb889428Chris Banes View callActivityOnCreateView(View parent, String name, Context context, AttributeSet attrs) { 828498356fea126122c3e3720a419969055cb889428Chris Banes // Let the Activity's LayoutInflater.Factory try and handle it 82916e8d4dd91083260223c007c797e46bc8f631055Chris Banes if (mOriginalWindowCallback instanceof LayoutInflater.Factory) { 830498356fea126122c3e3720a419969055cb889428Chris Banes final View result = ((LayoutInflater.Factory) mOriginalWindowCallback) 83116e8d4dd91083260223c007c797e46bc8f631055Chris Banes .onCreateView(name, context, attrs); 83216e8d4dd91083260223c007c797e46bc8f631055Chris Banes if (result != null) { 83316e8d4dd91083260223c007c797e46bc8f631055Chris Banes return result; 83416e8d4dd91083260223c007c797e46bc8f631055Chris Banes } 835f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 836498356fea126122c3e3720a419969055cb889428Chris Banes return null; 837f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 838f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 83900d183885b54de433e43118d3032340f40cac8c0Chris Banes private void openPanel(final PanelFeatureState st, KeyEvent event) { 84000d183885b54de433e43118d3032340f40cac8c0Chris Banes // Already open, return 8419b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (st.isOpen || isDestroyed()) { 84200d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 84300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 84400d183885b54de433e43118d3032340f40cac8c0Chris Banes 84500d183885b54de433e43118d3032340f40cac8c0Chris Banes // Don't open an options panel for honeycomb apps on xlarge devices. 84600d183885b54de433e43118d3032340f40cac8c0Chris Banes // (The app should be using an action bar for menu items.) 84700d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st.featureId == FEATURE_OPTIONS_PANEL) { 84816e8d4dd91083260223c007c797e46bc8f631055Chris Banes Context context = mContext; 84900d183885b54de433e43118d3032340f40cac8c0Chris Banes Configuration config = context.getResources().getConfiguration(); 85000d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean isXLarge = (config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == 85100d183885b54de433e43118d3032340f40cac8c0Chris Banes Configuration.SCREENLAYOUT_SIZE_XLARGE; 85200d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean isHoneycombApp = context.getApplicationInfo().targetSdkVersion >= 85300d183885b54de433e43118d3032340f40cac8c0Chris Banes android.os.Build.VERSION_CODES.HONEYCOMB; 85400d183885b54de433e43118d3032340f40cac8c0Chris Banes 85500d183885b54de433e43118d3032340f40cac8c0Chris Banes if (isXLarge && isHoneycombApp) { 85600d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 85700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 85800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 85900d183885b54de433e43118d3032340f40cac8c0Chris Banes 860f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes Window.Callback cb = getWindowCallback(); 86100d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((cb != null) && (!cb.onMenuOpened(st.featureId, st.menu))) { 86200d183885b54de433e43118d3032340f40cac8c0Chris Banes // Callback doesn't want the menu to open, reset any state 86300d183885b54de433e43118d3032340f40cac8c0Chris Banes closePanel(st, true); 86400d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 86500d183885b54de433e43118d3032340f40cac8c0Chris Banes } 86600d183885b54de433e43118d3032340f40cac8c0Chris Banes 86716e8d4dd91083260223c007c797e46bc8f631055Chris Banes final WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); 86846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (wm == null) { 86946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return; 87046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 87146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 87200d183885b54de433e43118d3032340f40cac8c0Chris Banes // Prepare panel (should have been done before, but just in case) 87300d183885b54de433e43118d3032340f40cac8c0Chris Banes if (!preparePanel(st, event)) { 87400d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 87500d183885b54de433e43118d3032340f40cac8c0Chris Banes } 87600d183885b54de433e43118d3032340f40cac8c0Chris Banes 87746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes int width = WRAP_CONTENT; 87800d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st.decorView == null || st.refreshDecorView) { 87946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (st.decorView == null) { 88046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Initialize the panel decor, this will populate st.decorView 88146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (!initializePanelDecor(st) || (st.decorView == null)) 88246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return; 88346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } else if (st.refreshDecorView && (st.decorView.getChildCount() > 0)) { 88446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Decor needs refreshing, so remove its views 88546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.decorView.removeAllViews(); 88646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 88700d183885b54de433e43118d3032340f40cac8c0Chris Banes 88846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // This will populate st.shownPanelView 88946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (!initializePanelContent(st) || !st.hasPanelItems()) { 89046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return; 89146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 89246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 89346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes ViewGroup.LayoutParams lp = st.shownPanelView.getLayoutParams(); 89446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (lp == null) { 89546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes lp = new ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT); 89646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 89746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 89846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes int backgroundResId = st.background; 89946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.decorView.setBackgroundResource(backgroundResId); 90046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 90146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes ViewParent shownPanelParent = st.shownPanelView.getParent(); 90246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (shownPanelParent != null && shownPanelParent instanceof ViewGroup) { 90346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes ((ViewGroup) shownPanelParent).removeView(st.shownPanelView); 90446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 90546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.decorView.addView(st.shownPanelView, lp); 90646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 90746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes /* 90846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes * Give focus to the view, if it or one of its children does not 90946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes * already have it. 91046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes */ 91146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (!st.shownPanelView.hasFocus()) { 91246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.shownPanelView.requestFocus(); 91346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 91446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } else if (st.createdPanelView != null) { 91546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // If we already had a panel view, carry width=MATCH_PARENT through 91646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // as we did above when it was created. 91746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes ViewGroup.LayoutParams lp = st.createdPanelView.getLayoutParams(); 91846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (lp != null && lp.width == ViewGroup.LayoutParams.MATCH_PARENT) { 91946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes width = MATCH_PARENT; 92046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 92100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 92200d183885b54de433e43118d3032340f40cac8c0Chris Banes 92300d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isHandled = false; 92446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 92546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 92646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes width, WRAP_CONTENT, 92746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.x, st.y, WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL, 92846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM 92946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, 93046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes PixelFormat.TRANSLUCENT); 93146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 93246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes lp.gravity = st.gravity; 93346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes lp.windowAnimations = st.windowAnimations; 93446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 93546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes wm.addView(st.decorView, lp); 93600d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isOpen = true; 93700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 93800d183885b54de433e43118d3032340f40cac8c0Chris Banes 93946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes private boolean initializePanelDecor(PanelFeatureState st) { 94057c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes st.setStyle(getActionBarThemedContext()); 94146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.decorView = new ListMenuDecorView(st.listPresenterContext); 94246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.gravity = Gravity.CENTER | Gravity.BOTTOM; 94346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return true; 94400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 94500d183885b54de433e43118d3032340f40cac8c0Chris Banes 94600d183885b54de433e43118d3032340f40cac8c0Chris Banes private void reopenMenu(MenuBuilder menu, boolean toggleMenuMode) { 94700d183885b54de433e43118d3032340f40cac8c0Chris Banes if (mDecorContentParent != null && mDecorContentParent.canShowOverflowMenu() && 94816e8d4dd91083260223c007c797e46bc8f631055Chris Banes (!ViewConfigurationCompat.hasPermanentMenuKey(ViewConfiguration.get(mContext)) || 94900d183885b54de433e43118d3032340f40cac8c0Chris Banes mDecorContentParent.isOverflowMenuShowPending())) { 9509b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes 951f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes final Window.Callback cb = getWindowCallback(); 9529b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes 95300d183885b54de433e43118d3032340f40cac8c0Chris Banes if (!mDecorContentParent.isOverflowMenuShowing() || !toggleMenuMode) { 9549b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (cb != null && !isDestroyed()) { 9559b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes // If we have a menu invalidation pending, do it now. 9569b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (mInvalidatePanelMenuPosted && 9579b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes (mInvalidatePanelMenuFeatures & (1 << FEATURE_OPTIONS_PANEL)) != 0) { 9589b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes mWindowDecor.removeCallbacks(mInvalidatePanelMenuRunnable); 9599b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes mInvalidatePanelMenuRunnable.run(); 9609b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes } 96100d183885b54de433e43118d3032340f40cac8c0Chris Banes 9629b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true); 96300d183885b54de433e43118d3032340f40cac8c0Chris Banes 9649b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes // If we don't have a menu or we're waiting for a full content refresh, 9659b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes // forget it. This is a lingering event that no longer matters. 9669b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (st.menu != null && !st.refreshMenuContent && 96746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes cb.onPreparePanel(FEATURE_OPTIONS_PANEL, st.createdPanelView, st.menu)) { 9689b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes cb.onMenuOpened(FEATURE_ACTION_BAR, st.menu); 9699b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes mDecorContentParent.showOverflowMenu(); 9709b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes } 97100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 97200d183885b54de433e43118d3032340f40cac8c0Chris Banes } else { 97300d183885b54de433e43118d3032340f40cac8c0Chris Banes mDecorContentParent.hideOverflowMenu(); 9749b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (!isDestroyed()) { 9759b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true); 97646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes cb.onPanelClosed(FEATURE_ACTION_BAR, st.menu); 9779b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes } 97800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 97900d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 98000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 98100d183885b54de433e43118d3032340f40cac8c0Chris Banes 98200d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true); 98300d183885b54de433e43118d3032340f40cac8c0Chris Banes 98400d183885b54de433e43118d3032340f40cac8c0Chris Banes st.refreshDecorView = true; 98500d183885b54de433e43118d3032340f40cac8c0Chris Banes closePanel(st, false); 98600d183885b54de433e43118d3032340f40cac8c0Chris Banes 98700d183885b54de433e43118d3032340f40cac8c0Chris Banes openPanel(st, null); 98800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 98900d183885b54de433e43118d3032340f40cac8c0Chris Banes 99000d183885b54de433e43118d3032340f40cac8c0Chris Banes private boolean initializePanelMenu(final PanelFeatureState st) { 99116e8d4dd91083260223c007c797e46bc8f631055Chris Banes Context context = mContext; 99261c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes 99300d183885b54de433e43118d3032340f40cac8c0Chris Banes // If we have an action bar, initialize the menu with the right theme. 99400d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((st.featureId == FEATURE_OPTIONS_PANEL || st.featureId == FEATURE_ACTION_BAR) && 99500d183885b54de433e43118d3032340f40cac8c0Chris Banes mDecorContentParent != null) { 99661c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes final TypedValue outValue = new TypedValue(); 99761c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes final Resources.Theme baseTheme = context.getTheme(); 99861c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes baseTheme.resolveAttribute(R.attr.actionBarTheme, outValue, true); 99961c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes 100061c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes Resources.Theme widgetTheme = null; 100161c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes if (outValue.resourceId != 0) { 100261c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme = context.getResources().newTheme(); 100361c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme.setTo(baseTheme); 100461c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme.applyStyle(outValue.resourceId, true); 100561c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme.resolveAttribute( 100661c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes R.attr.actionBarWidgetTheme, outValue, true); 100761c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes } else { 100861c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes baseTheme.resolveAttribute( 100961c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes R.attr.actionBarWidgetTheme, outValue, true); 101061c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes } 101161c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes 101261c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes if (outValue.resourceId != 0) { 101361c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes if (widgetTheme == null) { 101461c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme = context.getResources().newTheme(); 101561c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme.setTo(baseTheme); 101661c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes } 101761c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme.applyStyle(outValue.resourceId, true); 101861c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes } 101961c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes 102061c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes if (widgetTheme != null) { 102161c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes context = new ContextThemeWrapper(context, 0); 102261c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes context.getTheme().setTo(widgetTheme); 102361c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes } 102461c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes } 102561c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes 102600d183885b54de433e43118d3032340f40cac8c0Chris Banes final MenuBuilder menu = new MenuBuilder(context); 102700d183885b54de433e43118d3032340f40cac8c0Chris Banes menu.setCallback(this); 102800d183885b54de433e43118d3032340f40cac8c0Chris Banes st.setMenu(menu); 102961c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes 10308902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes return true; 10318902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 10328902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 103300d183885b54de433e43118d3032340f40cac8c0Chris Banes private boolean initializePanelContent(PanelFeatureState st) { 103446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (st.createdPanelView != null) { 103546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.shownPanelView = st.createdPanelView; 103646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return true; 103746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 103846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 103900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st.menu == null) { 104000d183885b54de433e43118d3032340f40cac8c0Chris Banes return false; 104100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 104200d183885b54de433e43118d3032340f40cac8c0Chris Banes 104300d183885b54de433e43118d3032340f40cac8c0Chris Banes if (mPanelMenuPresenterCallback == null) { 104400d183885b54de433e43118d3032340f40cac8c0Chris Banes mPanelMenuPresenterCallback = new PanelMenuPresenterCallback(); 104500d183885b54de433e43118d3032340f40cac8c0Chris Banes } 104600d183885b54de433e43118d3032340f40cac8c0Chris Banes 104757c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes MenuView menuView = st.getListMenuView(mPanelMenuPresenterCallback); 104800d183885b54de433e43118d3032340f40cac8c0Chris Banes 104900d183885b54de433e43118d3032340f40cac8c0Chris Banes st.shownPanelView = (View) menuView; 105000d183885b54de433e43118d3032340f40cac8c0Chris Banes 105100d183885b54de433e43118d3032340f40cac8c0Chris Banes return st.shownPanelView != null; 105200d183885b54de433e43118d3032340f40cac8c0Chris Banes } 105300d183885b54de433e43118d3032340f40cac8c0Chris Banes 105400d183885b54de433e43118d3032340f40cac8c0Chris Banes private boolean preparePanel(PanelFeatureState st, KeyEvent event) { 10559b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (isDestroyed()) { 10569b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes return false; 10579b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes } 10589b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes 10598902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // Already prepared (isPrepared will be reset to false later) 106000d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st.isPrepared) { 10618902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes return true; 10628902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 10638902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 106400d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((mPreparedPanel != null) && (mPreparedPanel != st)) { 106500d183885b54de433e43118d3032340f40cac8c0Chris Banes // Another Panel is prepared and possibly open, so close it 106600d183885b54de433e43118d3032340f40cac8c0Chris Banes closePanel(mPreparedPanel, false); 106700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 106800d183885b54de433e43118d3032340f40cac8c0Chris Banes 1069f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes final Window.Callback cb = getWindowCallback(); 107046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 107146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (cb != null) { 107246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.createdPanelView = cb.onCreatePanelView(st.featureId); 107346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 107446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 107500d183885b54de433e43118d3032340f40cac8c0Chris Banes final boolean isActionBarMenu = 107600d183885b54de433e43118d3032340f40cac8c0Chris Banes (st.featureId == FEATURE_OPTIONS_PANEL || st.featureId == FEATURE_ACTION_BAR); 107700d183885b54de433e43118d3032340f40cac8c0Chris Banes 107800d183885b54de433e43118d3032340f40cac8c0Chris Banes if (isActionBarMenu && mDecorContentParent != null) { 10798088261dec5dd277ccace13fe00f280ffa80098cChris Banes // Enforce ordering guarantees around events so that the action bar never 10808088261dec5dd277ccace13fe00f280ffa80098cChris Banes // dispatches menu-related events before the panel is prepared. 10818088261dec5dd277ccace13fe00f280ffa80098cChris Banes mDecorContentParent.setMenuPrepared(); 10828088261dec5dd277ccace13fe00f280ffa80098cChris Banes } 10838088261dec5dd277ccace13fe00f280ffa80098cChris Banes 108446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (st.createdPanelView == null) { 108546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Init the panel state's menu--return false if init failed 108646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (st.menu == null || st.refreshMenuContent) { 108746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (st.menu == null) { 108846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (!initializePanelMenu(st) || (st.menu == null)) { 108946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return false; 109046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 10918902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 10928902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 109346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (isActionBarMenu && mDecorContentParent != null) { 109446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (mActionMenuPresenterCallback == null) { 109546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes mActionMenuPresenterCallback = new ActionMenuPresenterCallback(); 109646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 109746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes mDecorContentParent.setMenu(st.menu, mActionMenuPresenterCallback); 109846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 109946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 110046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Creating the panel menu will involve a lot of manipulation; 110146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // don't dispatch change events to presenters until we're done. 110246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.menu.stopDispatchingItemsChanged(); 1103f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes if (!cb.onCreatePanelMenu(st.featureId, st.menu)) { 110446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Ditch the menu created above 110546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.setMenu(null); 110646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 110746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (isActionBarMenu && mDecorContentParent != null) { 110846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Don't show it in the action bar either 110946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes mDecorContentParent.setMenu(null, mActionMenuPresenterCallback); 111046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 111146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 111246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return false; 111303fc11b659da1645507062bddda450136e13af35Chris Banes } 111446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 111546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.refreshMenuContent = false; 11168902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 11178902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 111846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Preparing the panel menu can involve a lot of manipulation; 11198902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // don't dispatch change events to presenters until we're done. 112000d183885b54de433e43118d3032340f40cac8c0Chris Banes st.menu.stopDispatchingItemsChanged(); 11218902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 112246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Restore action view state before we prepare. This gives apps 112346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // an opportunity to override frozen/restored state in onPrepare. 112446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (st.frozenActionViewState != null) { 112546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.menu.restoreActionViewStates(st.frozenActionViewState); 112646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.frozenActionViewState = null; 112746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 112846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 112946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Callback and return if the callback does not want to show the menu 113046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (!cb.onPreparePanel(FEATURE_OPTIONS_PANEL, st.createdPanelView, st.menu)) { 113100d183885b54de433e43118d3032340f40cac8c0Chris Banes if (isActionBarMenu && mDecorContentParent != null) { 113246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // The app didn't want to show the menu for now but it still exists. 113346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Clear it out of the action bar. 113403fc11b659da1645507062bddda450136e13af35Chris Banes mDecorContentParent.setMenu(null, mActionMenuPresenterCallback); 11358902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 113646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.menu.startDispatchingItemsChanged(); 11378902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes return false; 11388902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 11398902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 114046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Set the proper keymap 114146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes KeyCharacterMap kmap = KeyCharacterMap.load( 114246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes event != null ? event.getDeviceId() : KeyCharacterMap.VIRTUAL_KEYBOARD); 114346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.qwertyMode = kmap.getKeyboardType() != KeyCharacterMap.NUMERIC; 114446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.menu.setQwertyMode(st.qwertyMode); 114500d183885b54de433e43118d3032340f40cac8c0Chris Banes st.menu.startDispatchingItemsChanged(); 11468902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 11478902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 11488902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // Set other state 114900d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isPrepared = true; 115000d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isHandled = false; 115100d183885b54de433e43118d3032340f40cac8c0Chris Banes mPreparedPanel = st; 11528902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 11538902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes return true; 11548902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 11558902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 115600d183885b54de433e43118d3032340f40cac8c0Chris Banes private void checkCloseActionMenu(MenuBuilder menu) { 115703fc11b659da1645507062bddda450136e13af35Chris Banes if (mClosingActionMenu) { 115803fc11b659da1645507062bddda450136e13af35Chris Banes return; 115903fc11b659da1645507062bddda450136e13af35Chris Banes } 116003fc11b659da1645507062bddda450136e13af35Chris Banes 116103fc11b659da1645507062bddda450136e13af35Chris Banes mClosingActionMenu = true; 116203fc11b659da1645507062bddda450136e13af35Chris Banes mDecorContentParent.dismissPopups(); 1163f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes Window.Callback cb = getWindowCallback(); 11649b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (cb != null && !isDestroyed()) { 116500d183885b54de433e43118d3032340f40cac8c0Chris Banes cb.onPanelClosed(FEATURE_ACTION_BAR, menu); 116600d183885b54de433e43118d3032340f40cac8c0Chris Banes } 116703fc11b659da1645507062bddda450136e13af35Chris Banes mClosingActionMenu = false; 116803fc11b659da1645507062bddda450136e13af35Chris Banes } 116903fc11b659da1645507062bddda450136e13af35Chris Banes 117046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes private void closePanel(int featureId) { 117146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes closePanel(getPanelState(featureId, true), true); 117246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 117346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 117400d183885b54de433e43118d3032340f40cac8c0Chris Banes private void closePanel(PanelFeatureState st, boolean doCallback) { 117500d183885b54de433e43118d3032340f40cac8c0Chris Banes if (doCallback && st.featureId == FEATURE_OPTIONS_PANEL && 117600d183885b54de433e43118d3032340f40cac8c0Chris Banes mDecorContentParent != null && mDecorContentParent.isOverflowMenuShowing()) { 117700d183885b54de433e43118d3032340f40cac8c0Chris Banes checkCloseActionMenu(st.menu); 117800d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 117900d183885b54de433e43118d3032340f40cac8c0Chris Banes } 118000d183885b54de433e43118d3032340f40cac8c0Chris Banes 1181436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes final boolean wasOpen = st.isOpen; 118246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 1183436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes final WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); 1184436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes if (wm != null && wasOpen && st.decorView != null) { 1185436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes wm.removeView(st.decorView); 118600d183885b54de433e43118d3032340f40cac8c0Chris Banes } 118700d183885b54de433e43118d3032340f40cac8c0Chris Banes 118800d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isPrepared = false; 118900d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isHandled = false; 119000d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isOpen = false; 119100d183885b54de433e43118d3032340f40cac8c0Chris Banes 1192436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes if (wasOpen && doCallback) { 1193436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes // If the panel was open and we should callback, do so. This should be done after 1194436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes // isOpen is updated to ensure that we do not get into an infinite recursion 1195436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes callOnPanelClosed(st.featureId, st, null); 1196436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes } 1197436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes 119800d183885b54de433e43118d3032340f40cac8c0Chris Banes // This view is no longer shown, so null it out 119900d183885b54de433e43118d3032340f40cac8c0Chris Banes st.shownPanelView = null; 120000d183885b54de433e43118d3032340f40cac8c0Chris Banes 120100d183885b54de433e43118d3032340f40cac8c0Chris Banes // Next time the menu opens, it should not be in expanded mode, so 120200d183885b54de433e43118d3032340f40cac8c0Chris Banes // force a refresh of the decor 120300d183885b54de433e43118d3032340f40cac8c0Chris Banes st.refreshDecorView = true; 120400d183885b54de433e43118d3032340f40cac8c0Chris Banes 120500d183885b54de433e43118d3032340f40cac8c0Chris Banes if (mPreparedPanel == st) { 120600d183885b54de433e43118d3032340f40cac8c0Chris Banes mPreparedPanel = null; 120703fc11b659da1645507062bddda450136e13af35Chris Banes } 120803fc11b659da1645507062bddda450136e13af35Chris Banes } 120903fc11b659da1645507062bddda450136e13af35Chris Banes 121046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes private boolean onKeyDownPanel(int featureId, KeyEvent event) { 121146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (event.getRepeatCount() == 0) { 121246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes PanelFeatureState st = getPanelState(featureId, true); 121346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (!st.isOpen) { 121446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return preparePanel(st, event); 121546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 121646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 121746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 121846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return false; 121946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 122046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 122146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes private void onKeyUpPanel(int featureId, KeyEvent event) { 122246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (mActionMode != null) { 122346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return; 122446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 122546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 122646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes boolean playSoundEffect = false; 122746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes final PanelFeatureState st = getPanelState(featureId, true); 122846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (featureId == FEATURE_OPTIONS_PANEL && mDecorContentParent != null && 122946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes mDecorContentParent.canShowOverflowMenu() && 123016e8d4dd91083260223c007c797e46bc8f631055Chris Banes !ViewConfigurationCompat.hasPermanentMenuKey(ViewConfiguration.get(mContext))) { 123146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (!mDecorContentParent.isOverflowMenuShowing()) { 123246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (!isDestroyed() && preparePanel(st, event)) { 123346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes playSoundEffect = mDecorContentParent.showOverflowMenu(); 123446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 123546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } else { 123646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes playSoundEffect = mDecorContentParent.hideOverflowMenu(); 123746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 123846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } else { 123946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (st.isOpen || st.isHandled) { 124046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 124146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Play the sound effect if the user closed an open menu (and not if 124246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // they just released a menu shortcut) 124346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes playSoundEffect = st.isOpen; 124446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 124546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Close menu 124646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes closePanel(st, true); 124746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 124846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } else if (st.isPrepared) { 124946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes boolean show = true; 125046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (st.refreshMenuContent) { 125146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Something may have invalidated the menu since we prepared it. 125246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Re-prepare it to refresh. 125346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.isPrepared = false; 125446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes show = preparePanel(st, event); 125546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 125646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 125746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (show) { 125846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Show menu 125946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes openPanel(st, event); 126046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 126146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes playSoundEffect = true; 126246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 126346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 126446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 126546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 126646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (playSoundEffect) { 126716e8d4dd91083260223c007c797e46bc8f631055Chris Banes AudioManager audioManager = (AudioManager) mContext.getSystemService( 126846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes Context.AUDIO_SERVICE); 126946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (audioManager != null) { 127046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK); 127146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } else { 127246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes Log.w(TAG, "Couldn't get audio manager"); 127346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 127446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 127546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 127646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 127700d183885b54de433e43118d3032340f40cac8c0Chris Banes private void callOnPanelClosed(int featureId, PanelFeatureState panel, Menu menu) { 127800d183885b54de433e43118d3032340f40cac8c0Chris Banes // Try to get a menu 127900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu == null) { 128000d183885b54de433e43118d3032340f40cac8c0Chris Banes // Need a panel to grab the menu, so try to get that 128100d183885b54de433e43118d3032340f40cac8c0Chris Banes if (panel == null) { 128200d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((featureId >= 0) && (featureId < mPanels.length)) { 128300d183885b54de433e43118d3032340f40cac8c0Chris Banes panel = mPanels[featureId]; 128400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 128500d183885b54de433e43118d3032340f40cac8c0Chris Banes } 128600d183885b54de433e43118d3032340f40cac8c0Chris Banes 128700d183885b54de433e43118d3032340f40cac8c0Chris Banes if (panel != null) { 128800d183885b54de433e43118d3032340f40cac8c0Chris Banes // menu still may be null, which is okay--we tried our best 128900d183885b54de433e43118d3032340f40cac8c0Chris Banes menu = panel.menu; 129000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 129100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 129200d183885b54de433e43118d3032340f40cac8c0Chris Banes 129300d183885b54de433e43118d3032340f40cac8c0Chris Banes // If the panel is not open, do not callback 129400d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((panel != null) && (!panel.isOpen)) 129500d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 129600d183885b54de433e43118d3032340f40cac8c0Chris Banes 1297f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes Window.Callback cb = getWindowCallback(); 1298f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes if (cb != null) { 1299f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes cb.onPanelClosed(featureId, menu); 1300f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 130100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 130200d183885b54de433e43118d3032340f40cac8c0Chris Banes 130300d183885b54de433e43118d3032340f40cac8c0Chris Banes private PanelFeatureState findMenuPanel(Menu menu) { 130400d183885b54de433e43118d3032340f40cac8c0Chris Banes final PanelFeatureState[] panels = mPanels; 130500d183885b54de433e43118d3032340f40cac8c0Chris Banes final int N = panels != null ? panels.length : 0; 130600d183885b54de433e43118d3032340f40cac8c0Chris Banes for (int i = 0; i < N; i++) { 130700d183885b54de433e43118d3032340f40cac8c0Chris Banes final PanelFeatureState panel = panels[i]; 130800d183885b54de433e43118d3032340f40cac8c0Chris Banes if (panel != null && panel.menu == menu) { 130900d183885b54de433e43118d3032340f40cac8c0Chris Banes return panel; 131000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 131100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 131200d183885b54de433e43118d3032340f40cac8c0Chris Banes return null; 131300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 131400d183885b54de433e43118d3032340f40cac8c0Chris Banes 131500d183885b54de433e43118d3032340f40cac8c0Chris Banes private PanelFeatureState getPanelState(int featureId, boolean required) { 131600d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState[] ar; 131700d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((ar = mPanels) == null || ar.length <= featureId) { 131800d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState[] nar = new PanelFeatureState[featureId + 1]; 131900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (ar != null) { 132000d183885b54de433e43118d3032340f40cac8c0Chris Banes System.arraycopy(ar, 0, nar, 0, ar.length); 132100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 132200d183885b54de433e43118d3032340f40cac8c0Chris Banes mPanels = ar = nar; 132303fc11b659da1645507062bddda450136e13af35Chris Banes } 132400d183885b54de433e43118d3032340f40cac8c0Chris Banes 132500d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState st = ar[featureId]; 132600d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st == null) { 132700d183885b54de433e43118d3032340f40cac8c0Chris Banes ar[featureId] = st = new PanelFeatureState(featureId); 132800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 132900d183885b54de433e43118d3032340f40cac8c0Chris Banes return st; 133003fc11b659da1645507062bddda450136e13af35Chris Banes } 133103fc11b659da1645507062bddda450136e13af35Chris Banes 1332f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes private boolean performPanelShortcut(PanelFeatureState st, int keyCode, KeyEvent event, 133300d183885b54de433e43118d3032340f40cac8c0Chris Banes int flags) { 1334dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes if (event.isSystem()) { 1335dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes return false; 1336dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 1337dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 1338dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes boolean handled = false; 1339dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 1340dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // Only try to perform menu shortcuts if preparePanel returned true (possible false 1341dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // return value from application not wanting to show the menu). 134200d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((st.isPrepared || preparePanel(st, event)) && st.menu != null) { 1343dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // The menu is prepared now, perform the shortcut on it 134400d183885b54de433e43118d3032340f40cac8c0Chris Banes handled = st.menu.performShortcut(keyCode, event, flags); 1345dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 1346dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 1347dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes if (handled) { 1348dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // Only close down the menu if we don't have an action bar keeping it open. 1349dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes if ((flags & Menu.FLAG_PERFORM_NO_CLOSE) == 0 && mDecorContentParent == null) { 135000d183885b54de433e43118d3032340f40cac8c0Chris Banes closePanel(st, true); 1351dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 1352dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 1353dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 1354dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes return handled; 1355dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 1356dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 135700d183885b54de433e43118d3032340f40cac8c0Chris Banes private void invalidatePanelMenu(int featureId) { 135800d183885b54de433e43118d3032340f40cac8c0Chris Banes mInvalidatePanelMenuFeatures |= 1 << featureId; 135900d183885b54de433e43118d3032340f40cac8c0Chris Banes 136000d183885b54de433e43118d3032340f40cac8c0Chris Banes if (!mInvalidatePanelMenuPosted && mWindowDecor != null) { 136100d183885b54de433e43118d3032340f40cac8c0Chris Banes ViewCompat.postOnAnimation(mWindowDecor, mInvalidatePanelMenuRunnable); 136200d183885b54de433e43118d3032340f40cac8c0Chris Banes mInvalidatePanelMenuPosted = true; 136300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 136400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 136500d183885b54de433e43118d3032340f40cac8c0Chris Banes 136600d183885b54de433e43118d3032340f40cac8c0Chris Banes private void doInvalidatePanelMenu(int featureId) { 136700d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState st = getPanelState(featureId, true); 136800d183885b54de433e43118d3032340f40cac8c0Chris Banes Bundle savedActionViewStates = null; 136900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st.menu != null) { 137000d183885b54de433e43118d3032340f40cac8c0Chris Banes savedActionViewStates = new Bundle(); 137100d183885b54de433e43118d3032340f40cac8c0Chris Banes st.menu.saveActionViewStates(savedActionViewStates); 137200d183885b54de433e43118d3032340f40cac8c0Chris Banes if (savedActionViewStates.size() > 0) { 137300d183885b54de433e43118d3032340f40cac8c0Chris Banes st.frozenActionViewState = savedActionViewStates; 137400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 137500d183885b54de433e43118d3032340f40cac8c0Chris Banes // This will be started again when the panel is prepared. 137600d183885b54de433e43118d3032340f40cac8c0Chris Banes st.menu.stopDispatchingItemsChanged(); 137700d183885b54de433e43118d3032340f40cac8c0Chris Banes st.menu.clear(); 137800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 137900d183885b54de433e43118d3032340f40cac8c0Chris Banes st.refreshMenuContent = true; 138000d183885b54de433e43118d3032340f40cac8c0Chris Banes st.refreshDecorView = true; 138100d183885b54de433e43118d3032340f40cac8c0Chris Banes 138200d183885b54de433e43118d3032340f40cac8c0Chris Banes // Prepare the options panel if we have an action bar 138300d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((featureId == FEATURE_ACTION_BAR || featureId == FEATURE_OPTIONS_PANEL) 138400d183885b54de433e43118d3032340f40cac8c0Chris Banes && mDecorContentParent != null) { 138500d183885b54de433e43118d3032340f40cac8c0Chris Banes st = getPanelState(Window.FEATURE_OPTIONS_PANEL, false); 138600d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st != null) { 138700d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isPrepared = false; 138800d183885b54de433e43118d3032340f40cac8c0Chris Banes preparePanel(st, null); 138900d183885b54de433e43118d3032340f40cac8c0Chris Banes } 139000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 139100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 139200d183885b54de433e43118d3032340f40cac8c0Chris Banes 1393ea4f700ac38424954c56df5138ff794def50b019Chris Banes /** 1394ea4f700ac38424954c56df5138ff794def50b019Chris Banes * Updates the status bar guard 1395ea4f700ac38424954c56df5138ff794def50b019Chris Banes * 1396ea4f700ac38424954c56df5138ff794def50b019Chris Banes * @param insetTop the current top system window inset 1397ea4f700ac38424954c56df5138ff794def50b019Chris Banes * @return the new top system window inset 1398ea4f700ac38424954c56df5138ff794def50b019Chris Banes */ 1399ea4f700ac38424954c56df5138ff794def50b019Chris Banes private int updateStatusGuard(int insetTop) { 1400ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes boolean showStatusGuard = false; 1401ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes // Show the status guard when the non-overlay contextual action bar is showing 1402ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mActionModeView != null) { 1403ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mActionModeView.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { 1404ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) 1405ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mActionModeView.getLayoutParams(); 1406ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes boolean mlpChanged = false; 1407ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes 1408ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mActionModeView.isShown()) { 14097efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell if (mTempRect1 == null) { 14107efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell mTempRect1 = new Rect(); 14117efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell mTempRect2 = new Rect(); 14127efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell } 14137efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell final Rect insets = mTempRect1; 14147efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell final Rect localInsets = mTempRect2; 14157efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell insets.set(0, insetTop, 0, 0); 14167efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell 14177efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell ViewUtils.computeFitSystemWindows(mSubDecor, insets, localInsets); 14187efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell final int newMargin = localInsets.top == 0 ? insetTop : 0; 14197efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell if (mlp.topMargin != newMargin) { 14207efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell mlpChanged = true; 14217efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell mlp.topMargin = insetTop; 14227efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell 1423ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mStatusGuard == null) { 142416e8d4dd91083260223c007c797e46bc8f631055Chris Banes mStatusGuard = new View(mContext); 142516e8d4dd91083260223c007c797e46bc8f631055Chris Banes mStatusGuard.setBackgroundColor(mContext.getResources() 1426ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes .getColor(R.color.abc_input_method_navigation_guard)); 14277efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell mSubDecor.addView(mStatusGuard, -1, 1428ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1429ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes insetTop)); 1430ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } else { 1431ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes ViewGroup.LayoutParams lp = mStatusGuard.getLayoutParams(); 1432ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (lp.height != insetTop) { 1433ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes lp.height = insetTop; 1434ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mStatusGuard.setLayoutParams(lp); 1435ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1436ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1437ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1438ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes 1439bbb50c78cc6ee24677c79bd4548fa38fcdc41d92Adam Powell // The action mode's theme may differ from the app, so 1440bbb50c78cc6ee24677c79bd4548fa38fcdc41d92Adam Powell // always show the status guard above it. 1441bbb50c78cc6ee24677c79bd4548fa38fcdc41d92Adam Powell showStatusGuard = mStatusGuard != null; 1442bbb50c78cc6ee24677c79bd4548fa38fcdc41d92Adam Powell 14437efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell // We only need to consume the insets if the action 14447efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell // mode is overlaid on the app content (e.g. it's 14457efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell // sitting in a FrameLayout, see 14467efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell // screen_simple_overlay_action_mode.xml). 1447bbb50c78cc6ee24677c79bd4548fa38fcdc41d92Adam Powell if (!mOverlayActionMode && showStatusGuard) { 14487efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell insetTop = 0; 14497efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell } 1450ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } else { 1451ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes // reset top margin 1452ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mlp.topMargin != 0) { 1453ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mlpChanged = true; 1454ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mlp.topMargin = 0; 1455ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1456ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1457ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mlpChanged) { 1458ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mActionModeView.setLayoutParams(mlp); 1459ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1460ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1461ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1462ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mStatusGuard != null) { 1463ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mStatusGuard.setVisibility(showStatusGuard ? View.VISIBLE : View.GONE); 1464ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1465ea4f700ac38424954c56df5138ff794def50b019Chris Banes 1466ea4f700ac38424954c56df5138ff794def50b019Chris Banes return insetTop; 1467ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1468ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes 1469cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes private void throwFeatureRequestIfSubDecorInstalled() { 1470cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes if (mSubDecorInstalled) { 1471cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes throw new AndroidRuntimeException( 1472f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes "Window feature must be requested before adding content"); 1473cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes } 1474cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes } 1475cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes 147616e8d4dd91083260223c007c797e46bc8f631055Chris Banes ViewGroup getSubDecor() { 147716e8d4dd91083260223c007c797e46bc8f631055Chris Banes return mSubDecor; 147816e8d4dd91083260223c007c797e46bc8f631055Chris Banes } 147916e8d4dd91083260223c007c797e46bc8f631055Chris Banes 1480ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 1481d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes * Clears out internal reference when the action mode is destroyed. 1482d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes */ 1483547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes class ActionModeCallbackWrapperV7 implements ActionMode.Callback { 1484d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes private ActionMode.Callback mWrapped; 1485d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 1486547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes public ActionModeCallbackWrapperV7(ActionMode.Callback wrapped) { 1487d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes mWrapped = wrapped; 1488d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 1489d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 1490d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes public boolean onCreateActionMode(ActionMode mode, Menu menu) { 1491d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes return mWrapped.onCreateActionMode(mode, menu); 1492d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 1493d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 1494d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes public boolean onPrepareActionMode(ActionMode mode, Menu menu) { 14959addcff1698f71fb4145f39dacaf33a9c1fef24fChris Banes return mWrapped.onPrepareActionMode(mode, menu); 1496d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 1497d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 1498d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes public boolean onActionItemClicked(ActionMode mode, MenuItem item) { 1499d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes return mWrapped.onActionItemClicked(mode, item); 1500d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 1501d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 1502d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes public void onDestroyActionMode(ActionMode mode) { 1503d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes mWrapped.onDestroyActionMode(mode); 15044c2a95906254748cb9a843b061288265d6e185a9Chris Banes if (mActionModePopup != null) { 150516e8d4dd91083260223c007c797e46bc8f631055Chris Banes mWindow.getDecorView().removeCallbacks(mShowActionModePopup); 15064c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionModePopup.dismiss(); 15074c2a95906254748cb9a843b061288265d6e185a9Chris Banes } else if (mActionModeView != null) { 15084c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionModeView.setVisibility(View.GONE); 1509ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mActionModeView.getParent() != null) { 1510ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes ViewCompat.requestApplyInsets((View) mActionModeView.getParent()); 1511ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 15124c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 15134c2a95906254748cb9a843b061288265d6e185a9Chris Banes if (mActionModeView != null) { 15144c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionModeView.removeAllViews(); 15154c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 1516f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes if (mAppCompatCallback != null) { 1517f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes mAppCompatCallback.onSupportActionModeFinished(mActionMode); 15184c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 1519d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes mActionMode = null; 1520d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 1521d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 1522d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 152303fc11b659da1645507062bddda450136e13af35Chris Banes private final class PanelMenuPresenterCallback implements MenuPresenter.Callback { 152403fc11b659da1645507062bddda450136e13af35Chris Banes @Override 152500d183885b54de433e43118d3032340f40cac8c0Chris Banes public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 152600d183885b54de433e43118d3032340f40cac8c0Chris Banes final Menu parentMenu = menu.getRootMenu(); 152700d183885b54de433e43118d3032340f40cac8c0Chris Banes final boolean isSubMenu = parentMenu != menu; 152800d183885b54de433e43118d3032340f40cac8c0Chris Banes final PanelFeatureState panel = findMenuPanel(isSubMenu ? parentMenu : menu); 152900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (panel != null) { 153000d183885b54de433e43118d3032340f40cac8c0Chris Banes if (isSubMenu) { 153100d183885b54de433e43118d3032340f40cac8c0Chris Banes callOnPanelClosed(panel.featureId, panel, parentMenu); 153200d183885b54de433e43118d3032340f40cac8c0Chris Banes closePanel(panel, true); 153300d183885b54de433e43118d3032340f40cac8c0Chris Banes } else { 153400d183885b54de433e43118d3032340f40cac8c0Chris Banes // Close the panel and only do the callback if the menu is being 153500d183885b54de433e43118d3032340f40cac8c0Chris Banes // closed completely, not if opening a sub menu 153600d183885b54de433e43118d3032340f40cac8c0Chris Banes closePanel(panel, allMenusAreClosing); 153700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 153800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 153903fc11b659da1645507062bddda450136e13af35Chris Banes } 154003fc11b659da1645507062bddda450136e13af35Chris Banes 154103fc11b659da1645507062bddda450136e13af35Chris Banes @Override 154200d183885b54de433e43118d3032340f40cac8c0Chris Banes public boolean onOpenSubMenu(MenuBuilder subMenu) { 154300d183885b54de433e43118d3032340f40cac8c0Chris Banes if (subMenu == null && mHasActionBar) { 1544f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes Window.Callback cb = getWindowCallback(); 15459b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (cb != null && !isDestroyed()) { 154600d183885b54de433e43118d3032340f40cac8c0Chris Banes cb.onMenuOpened(FEATURE_ACTION_BAR, subMenu); 154700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 154800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 154900d183885b54de433e43118d3032340f40cac8c0Chris Banes return true; 155003fc11b659da1645507062bddda450136e13af35Chris Banes } 155103fc11b659da1645507062bddda450136e13af35Chris Banes } 155203fc11b659da1645507062bddda450136e13af35Chris Banes 155303fc11b659da1645507062bddda450136e13af35Chris Banes private final class ActionMenuPresenterCallback implements MenuPresenter.Callback { 155403fc11b659da1645507062bddda450136e13af35Chris Banes @Override 155503fc11b659da1645507062bddda450136e13af35Chris Banes public boolean onOpenSubMenu(MenuBuilder subMenu) { 1556f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes Window.Callback cb = getWindowCallback(); 155700d183885b54de433e43118d3032340f40cac8c0Chris Banes if (cb != null) { 155800d183885b54de433e43118d3032340f40cac8c0Chris Banes cb.onMenuOpened(FEATURE_ACTION_BAR, subMenu); 155900d183885b54de433e43118d3032340f40cac8c0Chris Banes } 156000d183885b54de433e43118d3032340f40cac8c0Chris Banes return true; 156103fc11b659da1645507062bddda450136e13af35Chris Banes } 156203fc11b659da1645507062bddda450136e13af35Chris Banes 156303fc11b659da1645507062bddda450136e13af35Chris Banes @Override 156403fc11b659da1645507062bddda450136e13af35Chris Banes public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 156500d183885b54de433e43118d3032340f40cac8c0Chris Banes checkCloseActionMenu(menu); 156600d183885b54de433e43118d3032340f40cac8c0Chris Banes } 156700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 156800d183885b54de433e43118d3032340f40cac8c0Chris Banes 156900d183885b54de433e43118d3032340f40cac8c0Chris Banes private static final class PanelFeatureState { 15709b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes 157100d183885b54de433e43118d3032340f40cac8c0Chris Banes /** Feature ID for this panel. */ 157200d183885b54de433e43118d3032340f40cac8c0Chris Banes int featureId; 157300d183885b54de433e43118d3032340f40cac8c0Chris Banes 157446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes int background; 157546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 157646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes int gravity; 157746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 157846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes int x; 157946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 158046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes int y; 158146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 158246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes int windowAnimations; 158346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 158400d183885b54de433e43118d3032340f40cac8c0Chris Banes /** Dynamic state of the panel. */ 158500d183885b54de433e43118d3032340f40cac8c0Chris Banes ViewGroup decorView; 158600d183885b54de433e43118d3032340f40cac8c0Chris Banes 158700d183885b54de433e43118d3032340f40cac8c0Chris Banes /** The panel that we are actually showing. */ 158800d183885b54de433e43118d3032340f40cac8c0Chris Banes View shownPanelView; 158900d183885b54de433e43118d3032340f40cac8c0Chris Banes 159046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes /** The panel that was returned by onCreatePanelView(). */ 159146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes View createdPanelView; 159246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 159300d183885b54de433e43118d3032340f40cac8c0Chris Banes /** Use {@link #setMenu} to set this. */ 159400d183885b54de433e43118d3032340f40cac8c0Chris Banes MenuBuilder menu; 159500d183885b54de433e43118d3032340f40cac8c0Chris Banes 159600d183885b54de433e43118d3032340f40cac8c0Chris Banes ListMenuPresenter listMenuPresenter; 159700d183885b54de433e43118d3032340f40cac8c0Chris Banes 159857c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes Context listPresenterContext; 159900d183885b54de433e43118d3032340f40cac8c0Chris Banes 160000d183885b54de433e43118d3032340f40cac8c0Chris Banes /** 160100d183885b54de433e43118d3032340f40cac8c0Chris Banes * Whether the panel has been prepared (see 16029b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes * {@link #preparePanel}). 160300d183885b54de433e43118d3032340f40cac8c0Chris Banes */ 160400d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean isPrepared; 160500d183885b54de433e43118d3032340f40cac8c0Chris Banes 160600d183885b54de433e43118d3032340f40cac8c0Chris Banes /** 160700d183885b54de433e43118d3032340f40cac8c0Chris Banes * Whether an item's action has been performed. This happens in obvious 160800d183885b54de433e43118d3032340f40cac8c0Chris Banes * scenarios (user clicks on menu item), but can also happen with 160900d183885b54de433e43118d3032340f40cac8c0Chris Banes * chording menu+(shortcut key). 161000d183885b54de433e43118d3032340f40cac8c0Chris Banes */ 161100d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean isHandled; 161200d183885b54de433e43118d3032340f40cac8c0Chris Banes 161300d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean isOpen; 161400d183885b54de433e43118d3032340f40cac8c0Chris Banes 161500d183885b54de433e43118d3032340f40cac8c0Chris Banes public boolean qwertyMode; 161600d183885b54de433e43118d3032340f40cac8c0Chris Banes 161700d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean refreshDecorView; 161800d183885b54de433e43118d3032340f40cac8c0Chris Banes 161900d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean refreshMenuContent; 162000d183885b54de433e43118d3032340f40cac8c0Chris Banes 162100d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean wasLastOpen; 162200d183885b54de433e43118d3032340f40cac8c0Chris Banes 162300d183885b54de433e43118d3032340f40cac8c0Chris Banes /** 162400d183885b54de433e43118d3032340f40cac8c0Chris Banes * Contains the state of the menu when told to freeze. 162500d183885b54de433e43118d3032340f40cac8c0Chris Banes */ 162600d183885b54de433e43118d3032340f40cac8c0Chris Banes Bundle frozenMenuState; 162700d183885b54de433e43118d3032340f40cac8c0Chris Banes 162800d183885b54de433e43118d3032340f40cac8c0Chris Banes /** 162900d183885b54de433e43118d3032340f40cac8c0Chris Banes * Contains the state of associated action views when told to freeze. 163000d183885b54de433e43118d3032340f40cac8c0Chris Banes * These are saved across invalidations. 163100d183885b54de433e43118d3032340f40cac8c0Chris Banes */ 163200d183885b54de433e43118d3032340f40cac8c0Chris Banes Bundle frozenActionViewState; 163300d183885b54de433e43118d3032340f40cac8c0Chris Banes 163400d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState(int featureId) { 163500d183885b54de433e43118d3032340f40cac8c0Chris Banes this.featureId = featureId; 163600d183885b54de433e43118d3032340f40cac8c0Chris Banes 163700d183885b54de433e43118d3032340f40cac8c0Chris Banes refreshDecorView = false; 163800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 163900d183885b54de433e43118d3032340f40cac8c0Chris Banes 164000d183885b54de433e43118d3032340f40cac8c0Chris Banes public boolean hasPanelItems() { 164100d183885b54de433e43118d3032340f40cac8c0Chris Banes if (shownPanelView == null) return false; 164246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (createdPanelView != null) return true; 164300d183885b54de433e43118d3032340f40cac8c0Chris Banes 164400d183885b54de433e43118d3032340f40cac8c0Chris Banes return listMenuPresenter.getAdapter().getCount() > 0; 164500d183885b54de433e43118d3032340f40cac8c0Chris Banes } 164600d183885b54de433e43118d3032340f40cac8c0Chris Banes 164700d183885b54de433e43118d3032340f40cac8c0Chris Banes /** 164800d183885b54de433e43118d3032340f40cac8c0Chris Banes * Unregister and free attached MenuPresenters. They will be recreated as needed. 164900d183885b54de433e43118d3032340f40cac8c0Chris Banes */ 165000d183885b54de433e43118d3032340f40cac8c0Chris Banes public void clearMenuPresenters() { 165100d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu != null) { 165200d183885b54de433e43118d3032340f40cac8c0Chris Banes menu.removeMenuPresenter(listMenuPresenter); 165300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 165400d183885b54de433e43118d3032340f40cac8c0Chris Banes listMenuPresenter = null; 165500d183885b54de433e43118d3032340f40cac8c0Chris Banes } 165600d183885b54de433e43118d3032340f40cac8c0Chris Banes 165700d183885b54de433e43118d3032340f40cac8c0Chris Banes void setStyle(Context context) { 165857c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes final TypedValue outValue = new TypedValue(); 165957c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes final Resources.Theme widgetTheme = context.getResources().newTheme(); 166057c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes widgetTheme.setTo(context.getTheme()); 166157c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes 166257c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes // First apply the actionBarPopupTheme 166357c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes widgetTheme.resolveAttribute(R.attr.actionBarPopupTheme, outValue, true); 166457c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes if (outValue.resourceId != 0) { 166557c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes widgetTheme.applyStyle(outValue.resourceId, true); 166657c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes } 166757c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes 166857c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes // Now apply the panelMenuListTheme 166957c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes widgetTheme.resolveAttribute(R.attr.panelMenuListTheme, outValue, true); 167057c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes if (outValue.resourceId != 0) { 167157c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes widgetTheme.applyStyle(outValue.resourceId, true); 167257c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes } else { 167357c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes widgetTheme.applyStyle(R.style.Theme_AppCompat_CompactMenu, true); 167457c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes } 167557c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes 167657c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes context = new ContextThemeWrapper(context, 0); 167757c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes context.getTheme().setTo(widgetTheme); 167857c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes 167957c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes listPresenterContext = context; 168046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 168146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes TypedArray a = context.obtainStyledAttributes(R.styleable.Theme); 168246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes background = a.getResourceId( 168346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes R.styleable.Theme_panelBackground, 0); 168446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes windowAnimations = a.getResourceId( 168546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes R.styleable.Theme_android_windowAnimationStyle, 0); 168646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes a.recycle(); 168700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 168800d183885b54de433e43118d3032340f40cac8c0Chris Banes 168900d183885b54de433e43118d3032340f40cac8c0Chris Banes void setMenu(MenuBuilder menu) { 169000d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu == this.menu) return; 169100d183885b54de433e43118d3032340f40cac8c0Chris Banes 169200d183885b54de433e43118d3032340f40cac8c0Chris Banes if (this.menu != null) { 169300d183885b54de433e43118d3032340f40cac8c0Chris Banes this.menu.removeMenuPresenter(listMenuPresenter); 169400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 169500d183885b54de433e43118d3032340f40cac8c0Chris Banes this.menu = menu; 169600d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu != null) { 169700d183885b54de433e43118d3032340f40cac8c0Chris Banes if (listMenuPresenter != null) menu.addMenuPresenter(listMenuPresenter); 169800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 169900d183885b54de433e43118d3032340f40cac8c0Chris Banes } 170000d183885b54de433e43118d3032340f40cac8c0Chris Banes 170157c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes MenuView getListMenuView(MenuPresenter.Callback cb) { 170200d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu == null) return null; 170300d183885b54de433e43118d3032340f40cac8c0Chris Banes 170400d183885b54de433e43118d3032340f40cac8c0Chris Banes if (listMenuPresenter == null) { 170557c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes listMenuPresenter = new ListMenuPresenter(listPresenterContext, 170657c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes R.layout.abc_list_menu_item_layout); 170700d183885b54de433e43118d3032340f40cac8c0Chris Banes listMenuPresenter.setCallback(cb); 170800d183885b54de433e43118d3032340f40cac8c0Chris Banes menu.addMenuPresenter(listMenuPresenter); 170900d183885b54de433e43118d3032340f40cac8c0Chris Banes } 171000d183885b54de433e43118d3032340f40cac8c0Chris Banes 171100d183885b54de433e43118d3032340f40cac8c0Chris Banes MenuView result = listMenuPresenter.getMenuView(decorView); 171200d183885b54de433e43118d3032340f40cac8c0Chris Banes 171300d183885b54de433e43118d3032340f40cac8c0Chris Banes return result; 171400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 171500d183885b54de433e43118d3032340f40cac8c0Chris Banes 171600d183885b54de433e43118d3032340f40cac8c0Chris Banes Parcelable onSaveInstanceState() { 171700d183885b54de433e43118d3032340f40cac8c0Chris Banes SavedState savedState = new SavedState(); 171800d183885b54de433e43118d3032340f40cac8c0Chris Banes savedState.featureId = featureId; 171900d183885b54de433e43118d3032340f40cac8c0Chris Banes savedState.isOpen = isOpen; 172000d183885b54de433e43118d3032340f40cac8c0Chris Banes 172100d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu != null) { 172200d183885b54de433e43118d3032340f40cac8c0Chris Banes savedState.menuState = new Bundle(); 172300d183885b54de433e43118d3032340f40cac8c0Chris Banes menu.savePresenterStates(savedState.menuState); 172400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 172500d183885b54de433e43118d3032340f40cac8c0Chris Banes 172600d183885b54de433e43118d3032340f40cac8c0Chris Banes return savedState; 172700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 172800d183885b54de433e43118d3032340f40cac8c0Chris Banes 172900d183885b54de433e43118d3032340f40cac8c0Chris Banes void onRestoreInstanceState(Parcelable state) { 173000d183885b54de433e43118d3032340f40cac8c0Chris Banes SavedState savedState = (SavedState) state; 173100d183885b54de433e43118d3032340f40cac8c0Chris Banes featureId = savedState.featureId; 173200d183885b54de433e43118d3032340f40cac8c0Chris Banes wasLastOpen = savedState.isOpen; 173300d183885b54de433e43118d3032340f40cac8c0Chris Banes frozenMenuState = savedState.menuState; 173400d183885b54de433e43118d3032340f40cac8c0Chris Banes 173500d183885b54de433e43118d3032340f40cac8c0Chris Banes shownPanelView = null; 173600d183885b54de433e43118d3032340f40cac8c0Chris Banes decorView = null; 173700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 173800d183885b54de433e43118d3032340f40cac8c0Chris Banes 173900d183885b54de433e43118d3032340f40cac8c0Chris Banes void applyFrozenState() { 174000d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu != null && frozenMenuState != null) { 174100d183885b54de433e43118d3032340f40cac8c0Chris Banes menu.restorePresenterStates(frozenMenuState); 174200d183885b54de433e43118d3032340f40cac8c0Chris Banes frozenMenuState = null; 174300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 174400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 174500d183885b54de433e43118d3032340f40cac8c0Chris Banes 174600d183885b54de433e43118d3032340f40cac8c0Chris Banes private static class SavedState implements Parcelable { 174700d183885b54de433e43118d3032340f40cac8c0Chris Banes int featureId; 174800d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean isOpen; 174900d183885b54de433e43118d3032340f40cac8c0Chris Banes Bundle menuState; 175000d183885b54de433e43118d3032340f40cac8c0Chris Banes 175100d183885b54de433e43118d3032340f40cac8c0Chris Banes public int describeContents() { 175200d183885b54de433e43118d3032340f40cac8c0Chris Banes return 0; 175300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 175400d183885b54de433e43118d3032340f40cac8c0Chris Banes 175500d183885b54de433e43118d3032340f40cac8c0Chris Banes public void writeToParcel(Parcel dest, int flags) { 175600d183885b54de433e43118d3032340f40cac8c0Chris Banes dest.writeInt(featureId); 175700d183885b54de433e43118d3032340f40cac8c0Chris Banes dest.writeInt(isOpen ? 1 : 0); 175800d183885b54de433e43118d3032340f40cac8c0Chris Banes 175900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (isOpen) { 176000d183885b54de433e43118d3032340f40cac8c0Chris Banes dest.writeBundle(menuState); 176100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 176200d183885b54de433e43118d3032340f40cac8c0Chris Banes } 176300d183885b54de433e43118d3032340f40cac8c0Chris Banes 176400d183885b54de433e43118d3032340f40cac8c0Chris Banes private static SavedState readFromParcel(Parcel source) { 176500d183885b54de433e43118d3032340f40cac8c0Chris Banes SavedState savedState = new SavedState(); 176600d183885b54de433e43118d3032340f40cac8c0Chris Banes savedState.featureId = source.readInt(); 176700d183885b54de433e43118d3032340f40cac8c0Chris Banes savedState.isOpen = source.readInt() == 1; 176800d183885b54de433e43118d3032340f40cac8c0Chris Banes 176900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (savedState.isOpen) { 177000d183885b54de433e43118d3032340f40cac8c0Chris Banes savedState.menuState = source.readBundle(); 177100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 177200d183885b54de433e43118d3032340f40cac8c0Chris Banes 177300d183885b54de433e43118d3032340f40cac8c0Chris Banes return savedState; 177400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 177500d183885b54de433e43118d3032340f40cac8c0Chris Banes 177600d183885b54de433e43118d3032340f40cac8c0Chris Banes public static final Parcelable.Creator<SavedState> CREATOR 177700d183885b54de433e43118d3032340f40cac8c0Chris Banes = new Parcelable.Creator<SavedState>() { 177800d183885b54de433e43118d3032340f40cac8c0Chris Banes public SavedState createFromParcel(Parcel in) { 177900d183885b54de433e43118d3032340f40cac8c0Chris Banes return readFromParcel(in); 178000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 178100d183885b54de433e43118d3032340f40cac8c0Chris Banes 178200d183885b54de433e43118d3032340f40cac8c0Chris Banes public SavedState[] newArray(int size) { 178300d183885b54de433e43118d3032340f40cac8c0Chris Banes return new SavedState[size]; 178400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 178500d183885b54de433e43118d3032340f40cac8c0Chris Banes }; 178603fc11b659da1645507062bddda450136e13af35Chris Banes } 178703fc11b659da1645507062bddda450136e13af35Chris Banes } 178803fc11b659da1645507062bddda450136e13af35Chris Banes 178946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes private class ListMenuDecorView extends FrameLayout { 179046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes public ListMenuDecorView(Context context) { 179146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes super(context); 179246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 179346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 179446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes @Override 179546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes public boolean dispatchKeyEvent(KeyEvent event) { 1796f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes return AppCompatDelegateImplV7.this.dispatchKeyEvent(event); 179746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 179846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 179946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes @Override 180046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes public boolean onInterceptTouchEvent(MotionEvent event) { 180146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes int action = event.getAction(); 180246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (action == MotionEvent.ACTION_DOWN) { 180346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes int x = (int) event.getX(); 180446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes int y = (int) event.getY(); 180546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (isOutOfBounds(x, y)) { 180646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes closePanel(Window.FEATURE_OPTIONS_PANEL); 180746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return true; 180846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 180946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 181046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return super.onInterceptTouchEvent(event); 181146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 181246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 181346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes @Override 181446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes public void setBackgroundResource(int resid) { 181546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes setBackgroundDrawable(TintManager.getDrawable(getContext(), resid)); 181646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 181746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 181846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes private boolean isOutOfBounds(int x, int y) { 181946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return x < -5 || y < -5 || x > (getWidth() + 5) || y > (getHeight() + 5); 182046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 182146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 182246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 18236386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes} 1824