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; 328c3845ebb7e8198950510cd7a08bc8e66e2195feChris Banesimport android.support.annotation.IdRes; 33469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.support.annotation.NonNull; 348c3845ebb7e8198950510cd7a08bc8e66e2195feChris Banesimport android.support.annotation.Nullable; 3549c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v4.app.NavUtils; 3662ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banesimport android.support.v4.os.ParcelableCompat; 3762ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banesimport android.support.v4.os.ParcelableCompatCreatorCallbacks; 38f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.support.v4.view.LayoutInflaterCompat; 39f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.support.v4.view.LayoutInflaterFactory; 40ea4f700ac38424954c56df5138ff794def50b019Chris Banesimport android.support.v4.view.OnApplyWindowInsetsListener; 4103fc11b659da1645507062bddda450136e13af35Chris Banesimport android.support.v4.view.ViewCompat; 4249c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v4.view.ViewConfigurationCompat; 43c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liuimport android.support.v4.view.ViewPropertyAnimatorCompat; 44c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liuimport android.support.v4.view.ViewPropertyAnimatorListenerAdapter; 45d25af35061a9f20d59b25329d613c62c20184dadChris Banesimport android.support.v4.view.WindowCompat; 46ea4f700ac38424954c56df5138ff794def50b019Chris Banesimport android.support.v4.view.WindowInsetsCompat; 47f5829201b976fc650789accc22f325a2541ed478Chris Banesimport android.support.v4.widget.PopupWindowCompat; 486386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.support.v7.appcompat.R; 49d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banesimport android.support.v7.view.ActionMode; 5066698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v7.view.ContextThemeWrapper; 5166698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v7.view.StandaloneActionMode; 5266698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v7.view.menu.ListMenuPresenter; 5366698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v7.view.menu.MenuBuilder; 5466698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v7.view.menu.MenuPresenter; 5566698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v7.view.menu.MenuView; 5666698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v7.widget.ActionBarContextView; 5766698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v7.widget.AppCompatDrawableManager; 5866698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v7.widget.ContentFrameLayout; 5966698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v7.widget.DecorContentParent; 6066698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v7.widget.FitWindowsViewGroup; 6149c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.widget.Toolbar; 625fa121a1f51114f3a2f6d705139e83c0e0aea610Chris Banesimport android.support.v7.widget.VectorEnabledTintResources; 6366698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v7.widget.ViewStubCompat; 6466698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v7.widget.ViewUtils; 6516e8d4dd91083260223c007c797e46bc8f631055Chris Banesimport android.text.TextUtils; 66cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banesimport android.util.AndroidRuntimeException; 67469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.util.AttributeSet; 6846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banesimport android.util.Log; 6956fd50144df518461398a9b3397ee4842b346708Chris Banesimport android.util.TypedValue; 704c2a95906254748cb9a843b061288265d6e185a9Chris Banesimport android.view.Gravity; 7100d183885b54de433e43118d3032340f40cac8c0Chris Banesimport android.view.KeyCharacterMap; 72dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banesimport android.view.KeyEvent; 73dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banesimport android.view.LayoutInflater; 7430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.Menu; 7530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.MenuItem; 7646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banesimport android.view.MotionEvent; 776386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.view.View; 7849c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.view.ViewConfiguration; 796386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.view.ViewGroup; 8046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banesimport android.view.ViewParent; 816386aac7ea9be44d23dcea28d9a02110c174e988Chris Banesimport android.view.Window; 8246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banesimport android.view.WindowManager; 834c2a95906254748cb9a843b061288265d6e185a9Chris Banesimport android.view.accessibility.AccessibilityEvent; 8430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.widget.FrameLayout; 854c2a95906254748cb9a843b061288265d6e185a9Chris Banesimport android.widget.PopupWindow; 8616e8d4dd91083260223c007c797e46bc8f631055Chris Banesimport android.widget.TextView; 876386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 8846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banesimport static android.view.ViewGroup.LayoutParams.MATCH_PARENT; 8946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banesimport static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; 9000d183885b54de433e43118d3032340f40cac8c0Chris Banesimport static android.view.Window.FEATURE_OPTIONS_PANEL; 9100d183885b54de433e43118d3032340f40cac8c0Chris Banes 92f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesclass AppCompatDelegateImplV7 extends AppCompatDelegateImplBase 93f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes implements MenuBuilder.Callback, LayoutInflaterFactory { 946386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 9549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private DecorContentParent mDecorContentParent; 9603fc11b659da1645507062bddda450136e13af35Chris Banes private ActionMenuPresenterCallback mActionMenuPresenterCallback; 9703fc11b659da1645507062bddda450136e13af35Chris Banes private PanelMenuPresenterCallback mPanelMenuPresenterCallback; 9803fc11b659da1645507062bddda450136e13af35Chris Banes 994c2a95906254748cb9a843b061288265d6e185a9Chris Banes ActionMode mActionMode; 1004c2a95906254748cb9a843b061288265d6e185a9Chris Banes ActionBarContextView mActionModeView; 1014c2a95906254748cb9a843b061288265d6e185a9Chris Banes PopupWindow mActionModePopup; 1024c2a95906254748cb9a843b061288265d6e185a9Chris Banes Runnable mShowActionModePopup; 103c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu ViewPropertyAnimatorCompat mFadeAnim = null; 1045a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes 1055a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes // true if we have installed a window sub-decor layout. 1065a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes private boolean mSubDecorInstalled; 107ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes private ViewGroup mSubDecor; 108ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes 10916e8d4dd91083260223c007c797e46bc8f631055Chris Banes private TextView mTitleView; 110ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes private View mStatusGuard; 111d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 112ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // Used to keep track of Progress Bar Window features 113ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private boolean mFeatureProgress, mFeatureIndeterminateProgress; 114ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 1158902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // Used for emulating PanelFeatureState 1168902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes private boolean mClosingActionMenu; 11700d183885b54de433e43118d3032340f40cac8c0Chris Banes private PanelFeatureState[] mPanels; 11800d183885b54de433e43118d3032340f40cac8c0Chris Banes private PanelFeatureState mPreparedPanel; 119556ac47ce764a4a9320b5ac914536e9da2524176Chris Banes 120625c9c3db9bb6f6b92ca35b74f26a61a04ec8cd7Chris Banes private boolean mLongPressBackDown; 121625c9c3db9bb6f6b92ca35b74f26a61a04ec8cd7Chris Banes 12203fc11b659da1645507062bddda450136e13af35Chris Banes private boolean mInvalidatePanelMenuPosted; 12300d183885b54de433e43118d3032340f40cac8c0Chris Banes private int mInvalidatePanelMenuFeatures; 12403fc11b659da1645507062bddda450136e13af35Chris Banes private final Runnable mInvalidatePanelMenuRunnable = new Runnable() { 12503fc11b659da1645507062bddda450136e13af35Chris Banes @Override 12603fc11b659da1645507062bddda450136e13af35Chris Banes public void run() { 12700d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((mInvalidatePanelMenuFeatures & 1 << FEATURE_OPTIONS_PANEL) != 0) { 12800d183885b54de433e43118d3032340f40cac8c0Chris Banes doInvalidatePanelMenu(FEATURE_OPTIONS_PANEL); 12900d183885b54de433e43118d3032340f40cac8c0Chris Banes } 130d25af35061a9f20d59b25329d613c62c20184dadChris Banes if ((mInvalidatePanelMenuFeatures & 1 << FEATURE_SUPPORT_ACTION_BAR) != 0) { 131d25af35061a9f20d59b25329d613c62c20184dadChris Banes doInvalidatePanelMenu(FEATURE_SUPPORT_ACTION_BAR); 13200d183885b54de433e43118d3032340f40cac8c0Chris Banes } 13300d183885b54de433e43118d3032340f40cac8c0Chris Banes mInvalidatePanelMenuPosted = false; 13400d183885b54de433e43118d3032340f40cac8c0Chris Banes mInvalidatePanelMenuFeatures = 0; 13503fc11b659da1645507062bddda450136e13af35Chris Banes } 13603fc11b659da1645507062bddda450136e13af35Chris Banes }; 13703fc11b659da1645507062bddda450136e13af35Chris Banes 13849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private boolean mEnableDefaultActionBarUp; 13949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 1407efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell private Rect mTempRect1; 1417efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell private Rect mTempRect2; 1427efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell 1432cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes private AppCompatViewInflater mAppCompatViewInflater; 144fd1eb27a3700de31507de34fd1bcc51830fe876cChris Banes 14516e8d4dd91083260223c007c797e46bc8f631055Chris Banes AppCompatDelegateImplV7(Context context, Window window, AppCompatCallback callback) { 14616e8d4dd91083260223c007c797e46bc8f631055Chris Banes super(context, window, callback); 1476386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 1486386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 1496386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 150f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public void onCreate(Bundle savedInstanceState) { 15116e8d4dd91083260223c007c797e46bc8f631055Chris Banes if (mOriginalWindowCallback instanceof Activity) { 15216e8d4dd91083260223c007c797e46bc8f631055Chris Banes if (NavUtils.getParentActivityName((Activity) mOriginalWindowCallback) != null) { 15316e8d4dd91083260223c007c797e46bc8f631055Chris Banes // Peek at the Action Bar and update it if it already exists 15416e8d4dd91083260223c007c797e46bc8f631055Chris Banes ActionBar ab = peekSupportActionBar(); 15516e8d4dd91083260223c007c797e46bc8f631055Chris Banes if (ab == null) { 15616e8d4dd91083260223c007c797e46bc8f631055Chris Banes mEnableDefaultActionBarUp = true; 15716e8d4dd91083260223c007c797e46bc8f631055Chris Banes } else { 15816e8d4dd91083260223c007c797e46bc8f631055Chris Banes ab.setDefaultDisplayHomeAsUpEnabled(true); 15916e8d4dd91083260223c007c797e46bc8f631055Chris Banes } 16049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 16149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 16249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 16349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 16449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 165f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public void onPostCreate(Bundle savedInstanceState) { 166c826d759805928c84b20e646e442d55483e003c8Chris Banes // Make sure that the sub decor is installed 167c826d759805928c84b20e646e442d55483e003c8Chris Banes ensureSubDecor(); 168c826d759805928c84b20e646e442d55483e003c8Chris Banes } 169c826d759805928c84b20e646e442d55483e003c8Chris Banes 170c826d759805928c84b20e646e442d55483e003c8Chris Banes @Override 1718122ad54f129c2214631fad86cabda82815cc0d8Chris Banes public void initWindowDecorActionBar() { 17230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell ensureSubDecor(); 17388c0ac5649d6b82c882e2de4bc4f043b107a4428Chris Banes 1748122ad54f129c2214631fad86cabda82815cc0d8Chris Banes if (!mHasActionBar || mActionBar != null) { 1758122ad54f129c2214631fad86cabda82815cc0d8Chris Banes return; 17688c0ac5649d6b82c882e2de4bc4f043b107a4428Chris Banes } 17788c0ac5649d6b82c882e2de4bc4f043b107a4428Chris Banes 17816e8d4dd91083260223c007c797e46bc8f631055Chris Banes if (mOriginalWindowCallback instanceof Activity) { 1798122ad54f129c2214631fad86cabda82815cc0d8Chris Banes mActionBar = new WindowDecorActionBar((Activity) mOriginalWindowCallback, 1808122ad54f129c2214631fad86cabda82815cc0d8Chris Banes mOverlayActionBar); 18116e8d4dd91083260223c007c797e46bc8f631055Chris Banes } else if (mOriginalWindowCallback instanceof Dialog) { 1828122ad54f129c2214631fad86cabda82815cc0d8Chris Banes mActionBar = new WindowDecorActionBar((Dialog) mOriginalWindowCallback); 18316e8d4dd91083260223c007c797e46bc8f631055Chris Banes } 1848122ad54f129c2214631fad86cabda82815cc0d8Chris Banes if (mActionBar != null) { 1858122ad54f129c2214631fad86cabda82815cc0d8Chris Banes mActionBar.setDefaultDisplayHomeAsUpEnabled(mEnableDefaultActionBarUp); 18616e8d4dd91083260223c007c797e46bc8f631055Chris Banes } 18749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 18849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 18949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 190f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public void setSupportActionBar(Toolbar toolbar) { 19116e8d4dd91083260223c007c797e46bc8f631055Chris Banes if (!(mOriginalWindowCallback instanceof Activity)) { 19216e8d4dd91083260223c007c797e46bc8f631055Chris Banes // Only Activities support custom Action Bars 19316e8d4dd91083260223c007c797e46bc8f631055Chris Banes return; 19416e8d4dd91083260223c007c797e46bc8f631055Chris Banes } 19516e8d4dd91083260223c007c797e46bc8f631055Chris Banes 196da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes final ActionBar ab = getSupportActionBar(); 197da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes if (ab instanceof WindowDecorActionBar) { 19849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes throw new IllegalStateException("This Activity already has an action bar supplied " + 199d25af35061a9f20d59b25329d613c62c20184dadChris Banes "by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set " + 20049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes "windowActionBar to false in your theme to use a Toolbar instead."); 20149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 202733d0b2acb07ede7455b9d020901a10586053923Chris Banes 203733d0b2acb07ede7455b9d020901a10586053923Chris Banes // If we reach here then we're setting a new action bar 204733d0b2acb07ede7455b9d020901a10586053923Chris Banes // First clear out the MenuInflater to make sure that it is valid for the new Action Bar 2055ecdb2c5042da49d36d7cda3fa08f1d9151a1fbdChris Banes mMenuInflater = null; 206da0b9d63d6f940cbfd5b526c3f81858aeadcb7e8Chris Banes 207733d0b2acb07ede7455b9d020901a10586053923Chris Banes // If we have an action bar currently, destroy it 208733d0b2acb07ede7455b9d020901a10586053923Chris Banes if (ab != null) { 209733d0b2acb07ede7455b9d020901a10586053923Chris Banes ab.onDestroy(); 210733d0b2acb07ede7455b9d020901a10586053923Chris Banes } 211733d0b2acb07ede7455b9d020901a10586053923Chris Banes 212740e50456ff7aa7b93d40e7bdc59f8a619197ed5Chris Banes if (toolbar != null) { 213740e50456ff7aa7b93d40e7bdc59f8a619197ed5Chris Banes final ToolbarActionBar tbab = new ToolbarActionBar(toolbar, 214740e50456ff7aa7b93d40e7bdc59f8a619197ed5Chris Banes ((Activity) mContext).getTitle(), mAppCompatWindowCallback); 215740e50456ff7aa7b93d40e7bdc59f8a619197ed5Chris Banes mActionBar = tbab; 216740e50456ff7aa7b93d40e7bdc59f8a619197ed5Chris Banes mWindow.setCallback(tbab.getWrappedWindowCallback()); 217740e50456ff7aa7b93d40e7bdc59f8a619197ed5Chris Banes } else { 218740e50456ff7aa7b93d40e7bdc59f8a619197ed5Chris Banes mActionBar = null; 219740e50456ff7aa7b93d40e7bdc59f8a619197ed5Chris Banes // Re-set the original window callback since we may have already set a Toolbar wrapper 220740e50456ff7aa7b93d40e7bdc59f8a619197ed5Chris Banes mWindow.setCallback(mAppCompatWindowCallback); 221740e50456ff7aa7b93d40e7bdc59f8a619197ed5Chris Banes } 222740e50456ff7aa7b93d40e7bdc59f8a619197ed5Chris Banes 223740e50456ff7aa7b93d40e7bdc59f8a619197ed5Chris Banes invalidateOptionsMenu(); 2246386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 2256386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 2268c3845ebb7e8198950510cd7a08bc8e66e2195feChris Banes @Nullable 2278c3845ebb7e8198950510cd7a08bc8e66e2195feChris Banes @Override 2288c3845ebb7e8198950510cd7a08bc8e66e2195feChris Banes public View findViewById(@IdRes int id) { 2298c3845ebb7e8198950510cd7a08bc8e66e2195feChris Banes ensureSubDecor(); 2308c3845ebb7e8198950510cd7a08bc8e66e2195feChris Banes return mWindow.findViewById(id); 2318c3845ebb7e8198950510cd7a08bc8e66e2195feChris Banes } 2328c3845ebb7e8198950510cd7a08bc8e66e2195feChris Banes 2336386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 2346386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public void onConfigurationChanged(Configuration newConfig) { 2356386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes // If this is called before sub-decor is installed, ActionBar will not 2366386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes // be properly initialized. 2375a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes if (mHasActionBar && mSubDecorInstalled) { 2386386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes // Note: The action bar will need to access 2396386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes // view changes from superclass. 24049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ActionBar ab = getSupportActionBar(); 24149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (ab != null) { 24249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ab.onConfigurationChanged(newConfig); 24349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 2446386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 245862ce3b5a8789281e0510da9195bc8ea22581706Chris Banes 246862ce3b5a8789281e0510da9195bc8ea22581706Chris Banes // Re-apply Day/Night to the new configuration 247862ce3b5a8789281e0510da9195bc8ea22581706Chris Banes applyDayNight(); 2486386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 2496386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 2506386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 251a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes public void onStop() { 25249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ActionBar ab = getSupportActionBar(); 253a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes if (ab != null) { 254a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes ab.setShowHideAnimationEnabled(false); 255a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes } 256a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes } 257a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes 258a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes @Override 259a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes public void onPostResume() { 26049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ActionBar ab = getSupportActionBar(); 261a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes if (ab != null) { 262a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes ab.setShowHideAnimationEnabled(true); 263a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes } 264a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes } 265a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes 266a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes @Override 2676386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public void setContentView(View v) { 2686386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes ensureSubDecor(); 26916e8d4dd91083260223c007c797e46bc8f631055Chris Banes ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content); 27056fd50144df518461398a9b3397ee4842b346708Chris Banes contentParent.removeAllViews(); 27156fd50144df518461398a9b3397ee4842b346708Chris Banes contentParent.addView(v); 27216e8d4dd91083260223c007c797e46bc8f631055Chris Banes mOriginalWindowCallback.onContentChanged(); 2736386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 2746386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 2756386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 2766386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public void setContentView(int resId) { 2776386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes ensureSubDecor(); 27816e8d4dd91083260223c007c797e46bc8f631055Chris Banes ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content); 27956fd50144df518461398a9b3397ee4842b346708Chris Banes contentParent.removeAllViews(); 28016e8d4dd91083260223c007c797e46bc8f631055Chris Banes LayoutInflater.from(mContext).inflate(resId, contentParent); 28116e8d4dd91083260223c007c797e46bc8f631055Chris Banes mOriginalWindowCallback.onContentChanged(); 2826386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 2836386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 2846386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 2856386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public void setContentView(View v, ViewGroup.LayoutParams lp) { 2866386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes ensureSubDecor(); 28716e8d4dd91083260223c007c797e46bc8f631055Chris Banes ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content); 28856fd50144df518461398a9b3397ee4842b346708Chris Banes contentParent.removeAllViews(); 28956fd50144df518461398a9b3397ee4842b346708Chris Banes contentParent.addView(v, lp); 29016e8d4dd91083260223c007c797e46bc8f631055Chris Banes mOriginalWindowCallback.onContentChanged(); 2916386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 2926386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 2936386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 2946386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public void addContentView(View v, ViewGroup.LayoutParams lp) { 2956386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes ensureSubDecor(); 29616e8d4dd91083260223c007c797e46bc8f631055Chris Banes ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content); 29756fd50144df518461398a9b3397ee4842b346708Chris Banes contentParent.addView(v, lp); 29816e8d4dd91083260223c007c797e46bc8f631055Chris Banes mOriginalWindowCallback.onContentChanged(); 299d64322f4b9686fabfd5a03f402d50a8e3fe5adedChris Banes } 300d64322f4b9686fabfd5a03f402d50a8e3fe5adedChris Banes 301733d0b2acb07ede7455b9d020901a10586053923Chris Banes @Override 302733d0b2acb07ede7455b9d020901a10586053923Chris Banes public void onDestroy() { 303733d0b2acb07ede7455b9d020901a10586053923Chris Banes super.onDestroy(); 304733d0b2acb07ede7455b9d020901a10586053923Chris Banes 305733d0b2acb07ede7455b9d020901a10586053923Chris Banes if (mActionBar != null) { 306733d0b2acb07ede7455b9d020901a10586053923Chris Banes mActionBar.onDestroy(); 307733d0b2acb07ede7455b9d020901a10586053923Chris Banes } 308733d0b2acb07ede7455b9d020901a10586053923Chris Banes } 309733d0b2acb07ede7455b9d020901a10586053923Chris Banes 310f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes private void ensureSubDecor() { 31156fd50144df518461398a9b3397ee4842b346708Chris Banes if (!mSubDecorInstalled) { 312a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes mSubDecor = createSubDecor(); 31391a95c4599d0d5fa936b81396c71210ae7e68e54Chris Banes 31416e8d4dd91083260223c007c797e46bc8f631055Chris Banes // If a title was set before we installed the decor, propogate it now 31516e8d4dd91083260223c007c797e46bc8f631055Chris Banes CharSequence title = getTitle(); 31616e8d4dd91083260223c007c797e46bc8f631055Chris Banes if (!TextUtils.isEmpty(title)) { 31716e8d4dd91083260223c007c797e46bc8f631055Chris Banes onTitleChanged(title); 318f53c7bf3146bf9bcba46324f9f06449df475be36Chris Banes } 3194b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes 320a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes applyFixedSizeWindow(); 3210f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes 32216e8d4dd91083260223c007c797e46bc8f631055Chris Banes onSubDecorInstalled(mSubDecor); 3230f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes 324f53c7bf3146bf9bcba46324f9f06449df475be36Chris Banes mSubDecorInstalled = true; 3250f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes 32600d183885b54de433e43118d3032340f40cac8c0Chris Banes // Invalidate if the panel menu hasn't been created before this. 32700d183885b54de433e43118d3032340f40cac8c0Chris Banes // Panel menu invalidation is deferred avoiding application onCreateOptionsMenu 32800d183885b54de433e43118d3032340f40cac8c0Chris Banes // being called in the middle of onCreate or similar. 32900d183885b54de433e43118d3032340f40cac8c0Chris Banes // A pending invalidation will typically be resolved before the posted message 33000d183885b54de433e43118d3032340f40cac8c0Chris Banes // would run normally in order to satisfy instance state restoration. 33100d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false); 3329b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (!isDestroyed() && (st == null || st.menu == null)) { 333d25af35061a9f20d59b25329d613c62c20184dadChris Banes invalidatePanelMenu(FEATURE_SUPPORT_ACTION_BAR); 33400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 3356386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 3366386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 337ea4f700ac38424954c56df5138ff794def50b019Chris Banes 338a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes private ViewGroup createSubDecor() { 339a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes TypedArray a = mContext.obtainStyledAttributes(R.styleable.AppCompatTheme); 340a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes 341a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes if (!a.hasValue(R.styleable.AppCompatTheme_windowActionBar)) { 342a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes a.recycle(); 343a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes throw new IllegalStateException( 344a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes "You need to use a Theme.AppCompat theme (or descendant) with this activity."); 345a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes } 346a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes 347a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes if (a.getBoolean(R.styleable.AppCompatTheme_windowNoTitle, false)) { 348a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes requestWindowFeature(Window.FEATURE_NO_TITLE); 349a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes } else if (a.getBoolean(R.styleable.AppCompatTheme_windowActionBar, false)) { 350a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes // Don't allow an action bar if there is no title. 351a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes requestWindowFeature(FEATURE_SUPPORT_ACTION_BAR); 352a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes } 353a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes if (a.getBoolean(R.styleable.AppCompatTheme_windowActionBarOverlay, false)) { 354a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes requestWindowFeature(FEATURE_SUPPORT_ACTION_BAR_OVERLAY); 355a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes } 356a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes if (a.getBoolean(R.styleable.AppCompatTheme_windowActionModeOverlay, false)) { 357a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes requestWindowFeature(FEATURE_ACTION_MODE_OVERLAY); 358a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes } 359a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes mIsFloating = a.getBoolean(R.styleable.AppCompatTheme_android_windowIsFloating, false); 360a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes a.recycle(); 361a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes 362d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes // Now let's make sure that the Window has installed its decor by retrieving it 363d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes mWindow.getDecorView(); 364d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes 365a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes final LayoutInflater inflater = LayoutInflater.from(mContext); 366a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes ViewGroup subDecor = null; 367a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes 368a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes 369a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes if (!mWindowNoTitle) { 370a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes if (mIsFloating) { 371a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes // If we're floating, inflate the dialog title decor 372a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes subDecor = (ViewGroup) inflater.inflate( 373a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes R.layout.abc_dialog_title_material, null); 374a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes 375a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes // Floating windows can never have an action bar, reset the flags 376a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes mHasActionBar = mOverlayActionBar = false; 377a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes } else if (mHasActionBar) { 378a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes /** 379a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes * This needs some explanation. As we can not use the android:theme attribute 380a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes * pre-L, we emulate it by manually creating a LayoutInflater using a 381a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes * ContextThemeWrapper pointing to actionBarTheme. 382a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes */ 383a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes TypedValue outValue = new TypedValue(); 384a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes mContext.getTheme().resolveAttribute(R.attr.actionBarTheme, outValue, true); 385a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes 386a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes Context themedContext; 387a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes if (outValue.resourceId != 0) { 388a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes themedContext = new ContextThemeWrapper(mContext, outValue.resourceId); 389ea4f700ac38424954c56df5138ff794def50b019Chris Banes } else { 390a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes themedContext = mContext; 391ea4f700ac38424954c56df5138ff794def50b019Chris Banes } 3923954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes 393a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes // Now inflate the view using the themed context and set it as the content view 394a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes subDecor = (ViewGroup) LayoutInflater.from(themedContext) 395a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes .inflate(R.layout.abc_screen_toolbar, null); 3960f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes 397a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes mDecorContentParent = (DecorContentParent) subDecor 398a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes .findViewById(R.id.decor_content_parent); 399a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes mDecorContentParent.setWindowCallback(getWindowCallback()); 40016e8d4dd91083260223c007c797e46bc8f631055Chris Banes 401a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes /** 402a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes * Propagate features to DecorContentParent 403a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes */ 404a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes if (mOverlayActionBar) { 405a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes mDecorContentParent.initFeature(FEATURE_SUPPORT_ACTION_BAR_OVERLAY); 406a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes } 407a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes if (mFeatureProgress) { 408a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes mDecorContentParent.initFeature(Window.FEATURE_PROGRESS); 409a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes } 410a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes if (mFeatureIndeterminateProgress) { 411a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes mDecorContentParent.initFeature(Window.FEATURE_INDETERMINATE_PROGRESS); 412a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes } 413a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes } 414a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes } else { 415a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes if (mOverlayActionMode) { 416a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes subDecor = (ViewGroup) inflater.inflate( 417a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes R.layout.abc_screen_simple_overlay_action_mode, null); 418a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes } else { 419a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes subDecor = (ViewGroup) inflater.inflate(R.layout.abc_screen_simple, null); 420a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes } 4211f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes 422a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes if (Build.VERSION.SDK_INT >= 21) { 423a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes // If we're running on L or above, we can rely on ViewCompat's 424a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes // setOnApplyWindowInsetsListener 425a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes ViewCompat.setOnApplyWindowInsetsListener(subDecor, 426a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes new OnApplyWindowInsetsListener() { 427a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes @Override 428a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes public WindowInsetsCompat onApplyWindowInsets(View v, 429a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes WindowInsetsCompat insets) { 430a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes final int top = insets.getSystemWindowInsetTop(); 431a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes final int newTop = updateStatusGuard(top); 432a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes 433a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes if (top != newTop) { 434a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes insets = insets.replaceSystemWindowInsets( 435a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes insets.getSystemWindowInsetLeft(), 436a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes newTop, 437a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes insets.getSystemWindowInsetRight(), 438a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes insets.getSystemWindowInsetBottom()); 439a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes } 440c826d759805928c84b20e646e442d55483e003c8Chris Banes 441a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes // Now apply the insets on our view 442a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes return ViewCompat.onApplyWindowInsets(v, insets); 443a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes } 444a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes }); 445a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes } else { 446a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes // Else, we need to use our own FitWindowsViewGroup handling 447a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes ((FitWindowsViewGroup) subDecor).setOnFitSystemWindowsListener( 448a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes new FitWindowsViewGroup.OnFitSystemWindowsListener() { 449a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes @Override 450a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes public void onFitSystemWindows(Rect insets) { 451a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes insets.top = updateStatusGuard(insets.top); 452a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes } 453a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes }); 454c826d759805928c84b20e646e442d55483e003c8Chris Banes } 455a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes } 456c826d759805928c84b20e646e442d55483e003c8Chris Banes 457a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes if (subDecor == null) { 458a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes throw new IllegalArgumentException( 459a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes "AppCompat does not support the current theme features: { " 460a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes + "windowActionBar: " + mHasActionBar 461a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes + ", windowActionBarOverlay: "+ mOverlayActionBar 462a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes + ", android:windowIsFloating: " + mIsFloating 463a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes + ", windowActionModeOverlay: " + mOverlayActionMode 464a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes + ", windowNoTitle: " + mWindowNoTitle 465a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes + " }"); 466a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes } 4671f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes 468a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes if (mDecorContentParent == null) { 469a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes mTitleView = (TextView) subDecor.findViewById(R.id.title); 470a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes } 47192b18eb0263ef2421fda5bf977fea3bf044bf941Chris Banes 472a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes // Make the decor optionally fit system windows, like the window's decor 473a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes ViewUtils.makeOptionalFitsSystemWindows(subDecor); 4744b217eaec19887b37d6d124df5ba04c5bb8b8141Chris Banes 475d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes final ContentFrameLayout contentView = (ContentFrameLayout) subDecor.findViewById( 476a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes R.id.action_bar_activity_content); 477556ac47ce764a4a9320b5ac914536e9da2524176Chris Banes 478d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes final ViewGroup windowContentView = (ViewGroup) mWindow.findViewById(android.R.id.content); 479d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes if (windowContentView != null) { 480d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes // There might be Views already added to the Window's content view so we need to 481d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes // migrate them to our content view 482d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes while (windowContentView.getChildCount() > 0) { 483d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes final View child = windowContentView.getChildAt(0); 484d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes windowContentView.removeViewAt(0); 485d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes contentView.addView(child); 486d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes } 487d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes 488d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes // Change our content FrameLayout to use the android.R.id.content id. 489d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes // Useful for fragments. 490d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes windowContentView.setId(View.NO_ID); 491d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes contentView.setId(android.R.id.content); 492d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes 493d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes // The decorContent may have a foreground drawable set (windowContentOverlay). 494d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes // Remove this as we handle it ourselves 495d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes if (windowContentView instanceof FrameLayout) { 496d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes ((FrameLayout) windowContentView).setForeground(null); 497d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes } 498a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes } 49956fd50144df518461398a9b3397ee4842b346708Chris Banes 500a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes // Now set the Window's content view with the decor 501a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes mWindow.setContentView(subDecor); 50249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 503d3c6a162266698b98df2fa7793d9fe4d8ee8935bChris Banes contentView.setAttachListener(new ContentFrameLayout.OnAttachListener() { 504b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes @Override 505b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes public void onAttachedFromWindow() {} 506b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes 507b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes @Override 508b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes public void onDetachedFromWindow() { 509b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes dismissPopups(); 510b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes } 511b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes }); 512b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes 513a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes return subDecor; 5146386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 5156386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 51616e8d4dd91083260223c007c797e46bc8f631055Chris Banes void onSubDecorInstalled(ViewGroup subDecor) {} 51749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 518a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes private void applyFixedSizeWindow() { 519a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes ContentFrameLayout cfl = (ContentFrameLayout) mSubDecor.findViewById(android.R.id.content); 520a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes 521d8b7157eae680353a2821dca3c9e52b3aaf737a5Chris Banes // This is a bit weird. In the framework, the window sizing attributes control 522d8b7157eae680353a2821dca3c9e52b3aaf737a5Chris Banes // the decor view's size, meaning that any padding is inset for the min/max widths below. 523d8b7157eae680353a2821dca3c9e52b3aaf737a5Chris Banes // We don't control measurement at that level, so we need to workaround it by making sure 524d8b7157eae680353a2821dca3c9e52b3aaf737a5Chris Banes // that the decor view's padding is taken into account. 525ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes final View windowDecor = mWindow.getDecorView(); 526ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes cfl.setDecorPadding(windowDecor.getPaddingLeft(), 527ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes windowDecor.getPaddingTop(), windowDecor.getPaddingRight(), 528ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes windowDecor.getPaddingBottom()); 529d8b7157eae680353a2821dca3c9e52b3aaf737a5Chris Banes 530a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes TypedArray a = mContext.obtainStyledAttributes(R.styleable.AppCompatTheme); 531a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes a.getValue(R.styleable.AppCompatTheme_windowMinWidthMajor, cfl.getMinWidthMajor()); 532a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes a.getValue(R.styleable.AppCompatTheme_windowMinWidthMinor, cfl.getMinWidthMinor()); 53356fd50144df518461398a9b3397ee4842b346708Chris Banes 534a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes if (a.hasValue(R.styleable.AppCompatTheme_windowFixedWidthMajor)) { 535a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes a.getValue(R.styleable.AppCompatTheme_windowFixedWidthMajor, 536a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes cfl.getFixedWidthMajor()); 53756fd50144df518461398a9b3397ee4842b346708Chris Banes } 538a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes if (a.hasValue(R.styleable.AppCompatTheme_windowFixedWidthMinor)) { 539a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes a.getValue(R.styleable.AppCompatTheme_windowFixedWidthMinor, 540a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes cfl.getFixedWidthMinor()); 54156fd50144df518461398a9b3397ee4842b346708Chris Banes } 542a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes if (a.hasValue(R.styleable.AppCompatTheme_windowFixedHeightMajor)) { 543a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes a.getValue(R.styleable.AppCompatTheme_windowFixedHeightMajor, 544a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes cfl.getFixedHeightMajor()); 54556fd50144df518461398a9b3397ee4842b346708Chris Banes } 546a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes if (a.hasValue(R.styleable.AppCompatTheme_windowFixedHeightMinor)) { 547a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes a.getValue(R.styleable.AppCompatTheme_windowFixedHeightMinor, 548a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes cfl.getFixedHeightMinor()); 54956fd50144df518461398a9b3397ee4842b346708Chris Banes } 55056fd50144df518461398a9b3397ee4842b346708Chris Banes a.recycle(); 55119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes 552a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes cfl.requestLayout(); 55356fd50144df518461398a9b3397ee4842b346708Chris Banes } 55456fd50144df518461398a9b3397ee4842b346708Chris Banes 5556386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 556f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public boolean requestWindowFeature(int featureId) { 5578122ad54f129c2214631fad86cabda82815cc0d8Chris Banes featureId = sanitizeWindowFeatureId(featureId); 5588122ad54f129c2214631fad86cabda82815cc0d8Chris Banes 55988c0ac5649d6b82c882e2de4bc4f043b107a4428Chris Banes if (mWindowNoTitle && featureId == FEATURE_SUPPORT_ACTION_BAR) { 56088c0ac5649d6b82c882e2de4bc4f043b107a4428Chris Banes return false; // Ignore. No title dominates. 56188c0ac5649d6b82c882e2de4bc4f043b107a4428Chris Banes } 56288c0ac5649d6b82c882e2de4bc4f043b107a4428Chris Banes if (mHasActionBar && featureId == Window.FEATURE_NO_TITLE) { 56388c0ac5649d6b82c882e2de4bc4f043b107a4428Chris Banes // Remove the action bar feature if we have no title. No title dominates. 56488c0ac5649d6b82c882e2de4bc4f043b107a4428Chris Banes mHasActionBar = false; 56588c0ac5649d6b82c882e2de4bc4f043b107a4428Chris Banes } 56688c0ac5649d6b82c882e2de4bc4f043b107a4428Chris Banes 5676386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes switch (featureId) { 568d25af35061a9f20d59b25329d613c62c20184dadChris Banes case FEATURE_SUPPORT_ACTION_BAR: 569cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes throwFeatureRequestIfSubDecorInstalled(); 5705a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes mHasActionBar = true; 5716386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes return true; 572d25af35061a9f20d59b25329d613c62c20184dadChris Banes case FEATURE_SUPPORT_ACTION_BAR_OVERLAY: 573cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes throwFeatureRequestIfSubDecorInstalled(); 5745a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes mOverlayActionBar = true; 5756386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes return true; 57600d183885b54de433e43118d3032340f40cac8c0Chris Banes case FEATURE_ACTION_MODE_OVERLAY: 577cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes throwFeatureRequestIfSubDecorInstalled(); 578de9f38cc4a30b33ac46b105edf470fbc4a044e99Chris Banes mOverlayActionMode = true; 579de9f38cc4a30b33ac46b105edf470fbc4a044e99Chris Banes return true; 580ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes case Window.FEATURE_PROGRESS: 581cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes throwFeatureRequestIfSubDecorInstalled(); 582ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mFeatureProgress = true; 583ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return true; 584ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes case Window.FEATURE_INDETERMINATE_PROGRESS: 585cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes throwFeatureRequestIfSubDecorInstalled(); 586ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mFeatureIndeterminateProgress = true; 587ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return true; 58819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes case Window.FEATURE_NO_TITLE: 58919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes throwFeatureRequestIfSubDecorInstalled(); 59019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes mWindowNoTitle = true; 59119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes return true; 5926386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 593cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes 59416e8d4dd91083260223c007c797e46bc8f631055Chris Banes return mWindow.requestFeature(featureId); 5956386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 5966386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 5976386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 598eba6361c28fad482737765413aed1290da67f2daChris Banes public boolean hasWindowFeature(int featureId) { 599eba6361c28fad482737765413aed1290da67f2daChris Banes featureId = sanitizeWindowFeatureId(featureId); 600eba6361c28fad482737765413aed1290da67f2daChris Banes switch (featureId) { 601eba6361c28fad482737765413aed1290da67f2daChris Banes case FEATURE_SUPPORT_ACTION_BAR: 602eba6361c28fad482737765413aed1290da67f2daChris Banes return mHasActionBar; 603eba6361c28fad482737765413aed1290da67f2daChris Banes case FEATURE_SUPPORT_ACTION_BAR_OVERLAY: 604eba6361c28fad482737765413aed1290da67f2daChris Banes return mOverlayActionBar; 605eba6361c28fad482737765413aed1290da67f2daChris Banes case FEATURE_ACTION_MODE_OVERLAY: 606eba6361c28fad482737765413aed1290da67f2daChris Banes return mOverlayActionMode; 607eba6361c28fad482737765413aed1290da67f2daChris Banes case Window.FEATURE_PROGRESS: 608eba6361c28fad482737765413aed1290da67f2daChris Banes return mFeatureProgress; 609eba6361c28fad482737765413aed1290da67f2daChris Banes case Window.FEATURE_INDETERMINATE_PROGRESS: 610eba6361c28fad482737765413aed1290da67f2daChris Banes return mFeatureIndeterminateProgress; 611eba6361c28fad482737765413aed1290da67f2daChris Banes case Window.FEATURE_NO_TITLE: 612eba6361c28fad482737765413aed1290da67f2daChris Banes return mWindowNoTitle; 613eba6361c28fad482737765413aed1290da67f2daChris Banes } 614eba6361c28fad482737765413aed1290da67f2daChris Banes return mWindow.hasFeature(featureId); 615eba6361c28fad482737765413aed1290da67f2daChris Banes } 616eba6361c28fad482737765413aed1290da67f2daChris Banes 617eba6361c28fad482737765413aed1290da67f2daChris Banes @Override 61816e8d4dd91083260223c007c797e46bc8f631055Chris Banes void onTitleChanged(CharSequence title) { 61949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mDecorContentParent != null) { 62049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mDecorContentParent.setWindowTitle(title); 621535c5737ba868a622d7783d57f7078ab285717c0Chris Banes } else if (peekSupportActionBar() != null) { 622535c5737ba868a622d7783d57f7078ab285717c0Chris Banes peekSupportActionBar().setWindowTitle(title); 62316e8d4dd91083260223c007c797e46bc8f631055Chris Banes } else if (mTitleView != null) { 62416e8d4dd91083260223c007c797e46bc8f631055Chris Banes mTitleView.setText(title); 6256386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 6266386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 6276386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 6286386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 629d25af35061a9f20d59b25329d613c62c20184dadChris Banes void onPanelClosed(final int featureId, Menu menu) { 630d25af35061a9f20d59b25329d613c62c20184dadChris Banes if (featureId == FEATURE_SUPPORT_ACTION_BAR) { 63100d183885b54de433e43118d3032340f40cac8c0Chris Banes ActionBar ab = getSupportActionBar(); 63200d183885b54de433e43118d3032340f40cac8c0Chris Banes if (ab != null) { 63300d183885b54de433e43118d3032340f40cac8c0Chris Banes ab.dispatchMenuVisibilityChanged(false); 63400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 635436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes } else if (featureId == FEATURE_OPTIONS_PANEL) { 636436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes // Make sure that the options panel is closed. This is mainly used when we're using a 637436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes // ToolbarActionBar 638436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes PanelFeatureState st = getPanelState(featureId, true); 639436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes if (st.isOpen) { 640436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes closePanel(st, false); 641436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes } 642c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes } 643c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes } 644c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes 645c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes @Override 64600d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean onMenuOpened(final int featureId, Menu menu) { 647d25af35061a9f20d59b25329d613c62c20184dadChris Banes if (featureId == FEATURE_SUPPORT_ACTION_BAR) { 64800d183885b54de433e43118d3032340f40cac8c0Chris Banes ActionBar ab = getSupportActionBar(); 64900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (ab != null) { 65000d183885b54de433e43118d3032340f40cac8c0Chris Banes ab.dispatchMenuVisibilityChanged(true); 65100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 65200d183885b54de433e43118d3032340f40cac8c0Chris Banes return true; 653c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes } 654f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes return false; 65503fc11b659da1645507062bddda450136e13af35Chris Banes } 65603fc11b659da1645507062bddda450136e13af35Chris Banes 65703fc11b659da1645507062bddda450136e13af35Chris Banes @Override 6586386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { 659f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes final Window.Callback cb = getWindowCallback(); 6609b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (cb != null && !isDestroyed()) { 6619b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes final PanelFeatureState panel = findMenuPanel(menu.getRootMenu()); 6629b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (panel != null) { 6639b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes return cb.onMenuItemSelected(panel.featureId, item); 6649b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes } 6659b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes } 6669b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes return false; 6676386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 6686386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 6696386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 6706386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes public void onMenuModeChange(MenuBuilder menu) { 6716386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes reopenMenu(menu, true); 6726386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 6736386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 6746386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes @Override 675bfc9bd50c5c7e6874dc6f32a5d81620398a5c1e5Chris Banes public ActionMode startSupportActionMode(@NonNull final ActionMode.Callback callback) { 676d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes if (callback == null) { 677d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes throw new IllegalArgumentException("ActionMode callback can not be null."); 678d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 679d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 680d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes if (mActionMode != null) { 681d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes mActionMode.finish(); 682d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 683d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 684547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes final ActionMode.Callback wrappedCallback = new ActionModeCallbackWrapperV7(callback); 685d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 68649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ActionBar ab = getSupportActionBar(); 687d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes if (ab != null) { 6885a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes mActionMode = ab.startActionMode(wrappedCallback); 689f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes if (mActionMode != null && mAppCompatCallback != null) { 690f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes mAppCompatCallback.onSupportActionModeStarted(mActionMode); 6910bf48858279237f95d6aad565a074490745491cdChris Banes } 692d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 693d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 6940bf48858279237f95d6aad565a074490745491cdChris Banes if (mActionMode == null) { 6950bf48858279237f95d6aad565a074490745491cdChris Banes // If the action bar didn't provide an action mode, start the emulated window one 6960bf48858279237f95d6aad565a074490745491cdChris Banes mActionMode = startSupportActionModeFromWindow(wrappedCallback); 697d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 6980bf48858279237f95d6aad565a074490745491cdChris Banes 699d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes return mActionMode; 700d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 701d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 702d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes @Override 703f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public void invalidateOptionsMenu() { 704f2045f06bdfc9e2cc40a734e41e45d11adf2bc23Chris Banes final ActionBar ab = getSupportActionBar(); 705f2045f06bdfc9e2cc40a734e41e45d11adf2bc23Chris Banes if (ab != null && ab.invalidateOptionsMenu()) return; 706f2045f06bdfc9e2cc40a734e41e45d11adf2bc23Chris Banes 70700d183885b54de433e43118d3032340f40cac8c0Chris Banes invalidatePanelMenu(FEATURE_OPTIONS_PANEL); 7086386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes } 7096386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes 7104c2a95906254748cb9a843b061288265d6e185a9Chris Banes @Override 711bfc9bd50c5c7e6874dc6f32a5d81620398a5c1e5Chris Banes ActionMode startSupportActionModeFromWindow(@NonNull ActionMode.Callback callback) { 712c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu endOnGoingFadeAnimation(); 7134c2a95906254748cb9a843b061288265d6e185a9Chris Banes if (mActionMode != null) { 7144c2a95906254748cb9a843b061288265d6e185a9Chris Banes mActionMode.finish(); 7154c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 7164c2a95906254748cb9a843b061288265d6e185a9Chris Banes 717bfc9bd50c5c7e6874dc6f32a5d81620398a5c1e5Chris Banes if (!(callback instanceof ActionModeCallbackWrapperV7)) { 718bfc9bd50c5c7e6874dc6f32a5d81620398a5c1e5Chris Banes // If the callback hasn't been wrapped yet, wrap it 719bfc9bd50c5c7e6874dc6f32a5d81620398a5c1e5Chris Banes callback = new ActionModeCallbackWrapperV7(callback); 720bfc9bd50c5c7e6874dc6f32a5d81620398a5c1e5Chris Banes } 721bfc9bd50c5c7e6874dc6f32a5d81620398a5c1e5Chris Banes 722547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes ActionMode mode = null; 723547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes if (mAppCompatCallback != null && !isDestroyed()) { 724547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes try { 725bfc9bd50c5c7e6874dc6f32a5d81620398a5c1e5Chris Banes mode = mAppCompatCallback.onWindowStartingSupportActionMode(callback); 726547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } catch (AbstractMethodError ame) { 727547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes // Older apps might not implement this callback method. 7284c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 7294c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 7304c2a95906254748cb9a843b061288265d6e185a9Chris Banes 731547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes if (mode != null) { 732547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionMode = mode; 733547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } else { 734547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes if (mActionModeView == null) { 735547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes if (mIsFloating) { 736547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes // Use the action bar theme. 737547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes final TypedValue outValue = new TypedValue(); 738547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes final Resources.Theme baseTheme = mContext.getTheme(); 739547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes baseTheme.resolveAttribute(R.attr.actionBarTheme, outValue, true); 740547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes 741547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes final Context actionBarContext; 742547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes if (outValue.resourceId != 0) { 743547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes final Resources.Theme actionBarTheme = mContext.getResources().newTheme(); 744547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes actionBarTheme.setTo(baseTheme); 745547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes actionBarTheme.applyStyle(outValue.resourceId, true); 746547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes 747547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes actionBarContext = new ContextThemeWrapper(mContext, 0); 748547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes actionBarContext.getTheme().setTo(actionBarTheme); 749547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } else { 750547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes actionBarContext = mContext; 751547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } 752547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes 753547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModeView = new ActionBarContextView(actionBarContext); 754547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModePopup = new PopupWindow(actionBarContext, null, 755547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes R.attr.actionModePopupWindowStyle); 756f5829201b976fc650789accc22f325a2541ed478Chris Banes PopupWindowCompat.setWindowLayoutType(mActionModePopup, 757f5829201b976fc650789accc22f325a2541ed478Chris Banes WindowManager.LayoutParams.TYPE_APPLICATION); 758547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModePopup.setContentView(mActionModeView); 759547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModePopup.setWidth(ViewGroup.LayoutParams.MATCH_PARENT); 760547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes 761547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes actionBarContext.getTheme().resolveAttribute( 762547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes R.attr.actionBarSize, outValue, true); 763547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes final int height = TypedValue.complexToDimensionPixelSize(outValue.data, 764547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes actionBarContext.getResources().getDisplayMetrics()); 765547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModeView.setContentHeight(height); 766547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModePopup.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); 767547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mShowActionModePopup = new Runnable() { 768547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes public void run() { 769547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModePopup.showAtLocation( 770547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModeView, 771547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0); 772c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu endOnGoingFadeAnimation(); 773c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu 77445b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes if (shouldAnimateActionModeView()) { 77545b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes ViewCompat.setAlpha(mActionModeView, 0f); 77645b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes mFadeAnim = ViewCompat.animate(mActionModeView).alpha(1f); 77745b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes mFadeAnim.setListener(new ViewPropertyAnimatorListenerAdapter() { 77845b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes @Override 77945b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes public void onAnimationStart(View view) { 78045b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes mActionModeView.setVisibility(View.VISIBLE); 78145b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes } 78245b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes 78345b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes @Override 78445b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes public void onAnimationEnd(View view) { 78545b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes ViewCompat.setAlpha(mActionModeView, 1f); 78645b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes mFadeAnim.setListener(null); 78745b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes mFadeAnim = null; 78845b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes } 78945b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes }); 79045b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes } else { 79145b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes ViewCompat.setAlpha(mActionModeView, 1f); 79245b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes mActionModeView.setVisibility(View.VISIBLE); 79345b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes } 794547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } 795547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes }; 796547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } else { 797547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes ViewStubCompat stub = (ViewStubCompat) mSubDecor 798547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes .findViewById(R.id.action_mode_bar_stub); 799547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes if (stub != null) { 800547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes // Set the layout inflater so that it is inflated with the action bar's context 801547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes stub.setLayoutInflater(LayoutInflater.from(getActionBarThemedContext())); 802547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModeView = (ActionBarContextView) stub.inflate(); 803547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } 8044c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 805547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } 806ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes 807547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes if (mActionModeView != null) { 808c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu endOnGoingFadeAnimation(); 809547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModeView.killMode(); 810547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mode = new StandaloneActionMode(mActionModeView.getContext(), mActionModeView, 811bfc9bd50c5c7e6874dc6f32a5d81620398a5c1e5Chris Banes callback, mActionModePopup == null); 812547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes if (callback.onCreateActionMode(mode, mode.getMenu())) { 813547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mode.invalidate(); 814547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionModeView.initForMode(mode); 815547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionMode = mode; 816c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu 81745b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes if (shouldAnimateActionModeView()) { 81845b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes ViewCompat.setAlpha(mActionModeView, 0f); 81945b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes mFadeAnim = ViewCompat.animate(mActionModeView).alpha(1f); 82045b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes mFadeAnim.setListener(new ViewPropertyAnimatorListenerAdapter() { 82145b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes @Override 82245b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes public void onAnimationStart(View view) { 82345b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes mActionModeView.setVisibility(View.VISIBLE); 82445b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes mActionModeView.sendAccessibilityEvent( 82545b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); 82645b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes if (mActionModeView.getParent() != null) { 82745b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes ViewCompat.requestApplyInsets((View) mActionModeView.getParent()); 82845b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes } 8298ba0fdde8e91fd59808ce3453eef079e54915ce8Chris Banes } 83045b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes 83145b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes @Override 83245b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes public void onAnimationEnd(View view) { 83345b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes ViewCompat.setAlpha(mActionModeView, 1f); 83445b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes mFadeAnim.setListener(null); 83545b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes mFadeAnim = null; 83645b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes } 83745b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes }); 83845b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes } else { 83945b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes ViewCompat.setAlpha(mActionModeView, 1f); 84045b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes mActionModeView.setVisibility(View.VISIBLE); 84145b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes mActionModeView.sendAccessibilityEvent( 84245b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); 84345b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes if (mActionModeView.getParent() != null) { 84445b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes ViewCompat.requestApplyInsets((View) mActionModeView.getParent()); 845c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu } 84645b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes } 84745b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes 848547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes if (mActionModePopup != null) { 849547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mWindow.getDecorView().post(mShowActionModePopup); 850547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } 851547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } else { 852547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes mActionMode = null; 853ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 8544c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 8554c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 856f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes if (mActionMode != null && mAppCompatCallback != null) { 857f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes mAppCompatCallback.onSupportActionModeStarted(mActionMode); 8584c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 8594c2a95906254748cb9a843b061288265d6e185a9Chris Banes return mActionMode; 8604c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 8614c2a95906254748cb9a843b061288265d6e185a9Chris Banes 86245b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes final boolean shouldAnimateActionModeView() { 86345b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes // We only to animate the action mode in if the sub decor has already been laid out. 86445b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes // If it hasn't been laid out, it hasn't been drawn to screen yet. 86545b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes return mSubDecorInstalled && mSubDecor != null && ViewCompat.isLaidOut(mSubDecor); 86645b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes } 86745b0ea2a10e79b580aabb411126d8d6b79c9da95Chris Banes 868c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu private void endOnGoingFadeAnimation() { 869c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu if (mFadeAnim != null) { 870c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu mFadeAnim.cancel(); 871c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu } 872c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu } 873c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu 874f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes boolean onBackPressed() { 875d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes // Back cancels action modes first. 876d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes if (mActionMode != null) { 877d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes mActionMode.finish(); 878d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes return true; 879d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 880d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 881d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes // Next collapse any expanded action views. 88249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ActionBar ab = getSupportActionBar(); 88349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (ab != null && ab.collapseActionView()) { 884d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes return true; 885d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 886d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 887f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes // Let the call through... 888d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes return false; 889d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 890d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 891d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes @Override 89200d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean onKeyShortcut(int keyCode, KeyEvent ev) { 893d15ee7df01f2f48b536a610c4739f33b226d3f81Chris Banes // Let the Action Bar have a chance at handling the shortcut 894d15ee7df01f2f48b536a610c4739f33b226d3f81Chris Banes ActionBar ab = getSupportActionBar(); 895d15ee7df01f2f48b536a610c4739f33b226d3f81Chris Banes if (ab != null && ab.onKeyShortcut(keyCode, ev)) { 896d15ee7df01f2f48b536a610c4739f33b226d3f81Chris Banes return true; 897d15ee7df01f2f48b536a610c4739f33b226d3f81Chris Banes } 898d15ee7df01f2f48b536a610c4739f33b226d3f81Chris Banes 899dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // If the panel is already prepared, then perform the shortcut using it. 90000d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean handled; 90100d183885b54de433e43118d3032340f40cac8c0Chris Banes if (mPreparedPanel != null) { 90200d183885b54de433e43118d3032340f40cac8c0Chris Banes handled = performPanelShortcut(mPreparedPanel, ev.getKeyCode(), ev, 90300d183885b54de433e43118d3032340f40cac8c0Chris Banes Menu.FLAG_PERFORM_NO_CLOSE); 90400d183885b54de433e43118d3032340f40cac8c0Chris Banes if (handled) { 90500d183885b54de433e43118d3032340f40cac8c0Chris Banes if (mPreparedPanel != null) { 90600d183885b54de433e43118d3032340f40cac8c0Chris Banes mPreparedPanel.isHandled = true; 90700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 90800d183885b54de433e43118d3032340f40cac8c0Chris Banes return true; 90900d183885b54de433e43118d3032340f40cac8c0Chris Banes } 91000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 91100d183885b54de433e43118d3032340f40cac8c0Chris Banes 91200d183885b54de433e43118d3032340f40cac8c0Chris Banes // If the panel is not prepared, then we may be trying to handle a shortcut key 91300d183885b54de433e43118d3032340f40cac8c0Chris Banes // combination such as Control+C. Temporarily prepare the panel then mark it 91400d183885b54de433e43118d3032340f40cac8c0Chris Banes // unprepared again when finished to ensure that the panel will again be prepared 91500d183885b54de433e43118d3032340f40cac8c0Chris Banes // the next time it is shown for real. 91600d183885b54de433e43118d3032340f40cac8c0Chris Banes if (mPreparedPanel == null) { 91700d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true); 91800d183885b54de433e43118d3032340f40cac8c0Chris Banes preparePanel(st, ev); 91900d183885b54de433e43118d3032340f40cac8c0Chris Banes handled = performPanelShortcut(st, ev.getKeyCode(), ev, Menu.FLAG_PERFORM_NO_CLOSE); 92000d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isPrepared = false; 92100d183885b54de433e43118d3032340f40cac8c0Chris Banes if (handled) { 92200d183885b54de433e43118d3032340f40cac8c0Chris Banes return true; 92300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 92400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 92500d183885b54de433e43118d3032340f40cac8c0Chris Banes return false; 926dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 927dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 928dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes @Override 92946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes boolean dispatchKeyEvent(KeyEvent event) { 9304d95686e7ade79bfb1081047e90de4bf2affbbcaChris Banes if (event.getKeyCode() == KeyEvent.KEYCODE_MENU) { 9314d95686e7ade79bfb1081047e90de4bf2affbbcaChris Banes // If this is a MENU event, let the Activity have a go. 9324d95686e7ade79bfb1081047e90de4bf2affbbcaChris Banes if (mOriginalWindowCallback.dispatchKeyEvent(event)) { 9334d95686e7ade79bfb1081047e90de4bf2affbbcaChris Banes return true; 9344d95686e7ade79bfb1081047e90de4bf2affbbcaChris Banes } 9354d95686e7ade79bfb1081047e90de4bf2affbbcaChris Banes } 9364d95686e7ade79bfb1081047e90de4bf2affbbcaChris Banes 93746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes final int keyCode = event.getKeyCode(); 93846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes final int action = event.getAction(); 93946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes final boolean isDown = action == KeyEvent.ACTION_DOWN; 94046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 94146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return isDown ? onKeyDown(keyCode, event) : onKeyUp(keyCode, event); 94246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 94346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 944f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes boolean onKeyUp(int keyCode, KeyEvent event) { 94546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes switch (keyCode) { 94646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes case KeyEvent.KEYCODE_MENU: 9474d95686e7ade79bfb1081047e90de4bf2affbbcaChris Banes onKeyUpPanel(Window.FEATURE_OPTIONS_PANEL, event); 9484d95686e7ade79bfb1081047e90de4bf2affbbcaChris Banes return true; 94946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes case KeyEvent.KEYCODE_BACK: 950625c9c3db9bb6f6b92ca35b74f26a61a04ec8cd7Chris Banes final boolean wasLongPressBackDown = mLongPressBackDown; 951625c9c3db9bb6f6b92ca35b74f26a61a04ec8cd7Chris Banes mLongPressBackDown = false; 952625c9c3db9bb6f6b92ca35b74f26a61a04ec8cd7Chris Banes 95346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes PanelFeatureState st = getPanelState(Window.FEATURE_OPTIONS_PANEL, false); 95446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (st != null && st.isOpen) { 955625c9c3db9bb6f6b92ca35b74f26a61a04ec8cd7Chris Banes if (!wasLongPressBackDown) { 956625c9c3db9bb6f6b92ca35b74f26a61a04ec8cd7Chris Banes // Certain devices allow opening the options menu via a long press of the 957625c9c3db9bb6f6b92ca35b74f26a61a04ec8cd7Chris Banes // back button. We should only close the open options menu if it wasn't 958625c9c3db9bb6f6b92ca35b74f26a61a04ec8cd7Chris Banes // opened via a long press gesture. 959625c9c3db9bb6f6b92ca35b74f26a61a04ec8cd7Chris Banes closePanel(st, true); 960625c9c3db9bb6f6b92ca35b74f26a61a04ec8cd7Chris Banes } 96146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return true; 96246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 963f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes if (onBackPressed()) { 964f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes return true; 965f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 96646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes break; 96746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 96846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return false; 96946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 97046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 971f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes boolean onKeyDown(int keyCode, KeyEvent event) { 972f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes switch (keyCode) { 973f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes case KeyEvent.KEYCODE_MENU: 9744d95686e7ade79bfb1081047e90de4bf2affbbcaChris Banes onKeyDownPanel(Window.FEATURE_OPTIONS_PANEL, event); 9752f769dc974bd526d945efe8a644f3f89112e08feChris Banes // We need to return true here and not let it bubble up to the Window. 9762f769dc974bd526d945efe8a644f3f89112e08feChris Banes // For empty menus, PhoneWindow's KEYCODE_BACK handling will steals all events, 9772f769dc974bd526d945efe8a644f3f89112e08feChris Banes // not allowing the Activity to call onBackPressed(). 9782f769dc974bd526d945efe8a644f3f89112e08feChris Banes return true; 979625c9c3db9bb6f6b92ca35b74f26a61a04ec8cd7Chris Banes case KeyEvent.KEYCODE_BACK: 980625c9c3db9bb6f6b92ca35b74f26a61a04ec8cd7Chris Banes // Certain devices allow opening the options menu via a long press of the back 981625c9c3db9bb6f6b92ca35b74f26a61a04ec8cd7Chris Banes // button. We keep a record of whether the last event is from a long press. 982625c9c3db9bb6f6b92ca35b74f26a61a04ec8cd7Chris Banes mLongPressBackDown = (event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0; 983625c9c3db9bb6f6b92ca35b74f26a61a04ec8cd7Chris Banes break; 98446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 98546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 986dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // On API v7-10 we need to manually call onKeyShortcut() as this is not called 987dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // from the Activity 98846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { 989a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes // We do not return true here otherwise dispatchKeyEvent will not reach the Activity 990a4b5c35036e68c7551dd77641ceec17b92c6368dChris Banes // (which results in the back button not working) 991c9b517a68ed7070d4edcdd5be818540d81b43db0Chris Banes onKeyShortcut(keyCode, event); 99246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 99346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return false; 994dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 995dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 996469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes @Override 997f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public View createView(View parent, final String name, @NonNull Context context, 998fd1eb27a3700de31507de34fd1bcc51830fe876cChris Banes @NonNull AttributeSet attrs) { 999a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes final boolean isPre21 = Build.VERSION.SDK_INT < 21; 1000878ed08a784cafb112a5d350573b0d1e81c554dbChris Banes 10012cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes if (mAppCompatViewInflater == null) { 1002e183f2600fb31c69eceacc1c263cd56f12489a65Chris Banes mAppCompatViewInflater = new AppCompatViewInflater(); 1003469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 1004fd1eb27a3700de31507de34fd1bcc51830fe876cChris Banes 1005481ff5b456cc4ce7c75f03808ed344de4bdbf5ceChris Banes // We only want the View to inherit its context if we're running pre-v21 1006481ff5b456cc4ce7c75f03808ed344de4bdbf5ceChris Banes final boolean inheritContext = isPre21 && shouldInheritContext((ViewParent) parent); 1007a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes 1008484705a5e6fdc1f6ef746b822716a45f82652ab9Chris Banes return mAppCompatViewInflater.createView(parent, name, context, attrs, inheritContext, 1009484705a5e6fdc1f6ef746b822716a45f82652ab9Chris Banes isPre21, /* Only read android:theme pre-L (L+ handles this anyway) */ 10105fa121a1f51114f3a2f6d705139e83c0e0aea610Chris Banes true, /* Read read app:theme as a fallback at all times for legacy reasons */ 10115fa121a1f51114f3a2f6d705139e83c0e0aea610Chris Banes VectorEnabledTintResources.shouldBeUsed() /* Only tint wrap the context if enabled */ 1012484705a5e6fdc1f6ef746b822716a45f82652ab9Chris Banes ); 1013469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 1014469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 1015d95c99933cb57a5678afeff01d91269be61e2502Chris Banes private boolean shouldInheritContext(ViewParent parent) { 1016d95c99933cb57a5678afeff01d91269be61e2502Chris Banes if (parent == null) { 1017d95c99933cb57a5678afeff01d91269be61e2502Chris Banes // The initial parent is null so just return false 1018d95c99933cb57a5678afeff01d91269be61e2502Chris Banes return false; 1019d95c99933cb57a5678afeff01d91269be61e2502Chris Banes } 1020ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes final View windowDecor = mWindow.getDecorView(); 1021d95c99933cb57a5678afeff01d91269be61e2502Chris Banes while (true) { 1022d95c99933cb57a5678afeff01d91269be61e2502Chris Banes if (parent == null) { 1023d95c99933cb57a5678afeff01d91269be61e2502Chris Banes // Bingo. We've hit a view which has a null parent before being terminated from 1024d95c99933cb57a5678afeff01d91269be61e2502Chris Banes // the loop. This is (most probably) because it's the root view in an inflation 1025d95c99933cb57a5678afeff01d91269be61e2502Chris Banes // call, therefore we should inherit. This works as the inflated layout is only 1026d95c99933cb57a5678afeff01d91269be61e2502Chris Banes // added to the hierarchy at the end of the inflate() call. 1027d95c99933cb57a5678afeff01d91269be61e2502Chris Banes return true; 1028ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes } else if (parent == windowDecor || !(parent instanceof View) 1029d95c99933cb57a5678afeff01d91269be61e2502Chris Banes || ViewCompat.isAttachedToWindow((View) parent)) { 1030d95c99933cb57a5678afeff01d91269be61e2502Chris Banes // We have either hit the window's decor view, a parent which isn't a View 1031d95c99933cb57a5678afeff01d91269be61e2502Chris Banes // (i.e. ViewRootImpl), or an attached view, so we know that the original parent 1032d95c99933cb57a5678afeff01d91269be61e2502Chris Banes // is currently added to the view hierarchy. This means that it has not be 1033d95c99933cb57a5678afeff01d91269be61e2502Chris Banes // inflated in the current inflate() call and we should not inherit the context. 1034d95c99933cb57a5678afeff01d91269be61e2502Chris Banes return false; 1035d95c99933cb57a5678afeff01d91269be61e2502Chris Banes } 1036d95c99933cb57a5678afeff01d91269be61e2502Chris Banes parent = parent.getParent(); 1037d95c99933cb57a5678afeff01d91269be61e2502Chris Banes } 1038d95c99933cb57a5678afeff01d91269be61e2502Chris Banes } 1039d95c99933cb57a5678afeff01d91269be61e2502Chris Banes 1040f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes @Override 1041f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public void installViewFactory() { 104216e8d4dd91083260223c007c797e46bc8f631055Chris Banes LayoutInflater layoutInflater = LayoutInflater.from(mContext); 1043f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes if (layoutInflater.getFactory() == null) { 1044f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes LayoutInflaterCompat.setFactory(layoutInflater, this); 1045f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } else { 104656594b0cf74a9f71c52980044283ddb0e9e6f47cYuichi Araki if (!(LayoutInflaterCompat.getFactory(layoutInflater) 104756594b0cf74a9f71c52980044283ddb0e9e6f47cYuichi Araki instanceof AppCompatDelegateImplV7)) { 104856594b0cf74a9f71c52980044283ddb0e9e6f47cYuichi Araki Log.i(TAG, "The Activity's LayoutInflater already has a Factory installed" 104956594b0cf74a9f71c52980044283ddb0e9e6f47cYuichi Araki + " so we can not install AppCompat's"); 105056594b0cf74a9f71c52980044283ddb0e9e6f47cYuichi Araki } 1051f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 1052f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 1053f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 1054f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes /** 1055f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes * From {@link android.support.v4.view.LayoutInflaterFactory} 1056f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes */ 1057f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes @Override 1058498356fea126122c3e3720a419969055cb889428Chris Banes public final View onCreateView(View parent, String name, 1059f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes Context context, AttributeSet attrs) { 1060498356fea126122c3e3720a419969055cb889428Chris Banes // First let the Activity's Factory try and inflate the view 1061498356fea126122c3e3720a419969055cb889428Chris Banes final View view = callActivityOnCreateView(parent, name, context, attrs); 1062498356fea126122c3e3720a419969055cb889428Chris Banes if (view != null) { 1063498356fea126122c3e3720a419969055cb889428Chris Banes return view; 1064498356fea126122c3e3720a419969055cb889428Chris Banes } 1065498356fea126122c3e3720a419969055cb889428Chris Banes 1066498356fea126122c3e3720a419969055cb889428Chris Banes // If the Factory didn't handle it, let our createView() method try 1067498356fea126122c3e3720a419969055cb889428Chris Banes return createView(parent, name, context, attrs); 1068498356fea126122c3e3720a419969055cb889428Chris Banes } 106916e8d4dd91083260223c007c797e46bc8f631055Chris Banes 1070498356fea126122c3e3720a419969055cb889428Chris Banes View callActivityOnCreateView(View parent, String name, Context context, AttributeSet attrs) { 1071498356fea126122c3e3720a419969055cb889428Chris Banes // Let the Activity's LayoutInflater.Factory try and handle it 107216e8d4dd91083260223c007c797e46bc8f631055Chris Banes if (mOriginalWindowCallback instanceof LayoutInflater.Factory) { 1073498356fea126122c3e3720a419969055cb889428Chris Banes final View result = ((LayoutInflater.Factory) mOriginalWindowCallback) 107416e8d4dd91083260223c007c797e46bc8f631055Chris Banes .onCreateView(name, context, attrs); 107516e8d4dd91083260223c007c797e46bc8f631055Chris Banes if (result != null) { 107616e8d4dd91083260223c007c797e46bc8f631055Chris Banes return result; 107716e8d4dd91083260223c007c797e46bc8f631055Chris Banes } 1078f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 1079498356fea126122c3e3720a419969055cb889428Chris Banes return null; 1080f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 1081f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 108200d183885b54de433e43118d3032340f40cac8c0Chris Banes private void openPanel(final PanelFeatureState st, KeyEvent event) { 108300d183885b54de433e43118d3032340f40cac8c0Chris Banes // Already open, return 10849b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (st.isOpen || isDestroyed()) { 108500d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 108600d183885b54de433e43118d3032340f40cac8c0Chris Banes } 108700d183885b54de433e43118d3032340f40cac8c0Chris Banes 108800d183885b54de433e43118d3032340f40cac8c0Chris Banes // Don't open an options panel for honeycomb apps on xlarge devices. 108900d183885b54de433e43118d3032340f40cac8c0Chris Banes // (The app should be using an action bar for menu items.) 109000d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st.featureId == FEATURE_OPTIONS_PANEL) { 109116e8d4dd91083260223c007c797e46bc8f631055Chris Banes Context context = mContext; 109200d183885b54de433e43118d3032340f40cac8c0Chris Banes Configuration config = context.getResources().getConfiguration(); 109300d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean isXLarge = (config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == 109400d183885b54de433e43118d3032340f40cac8c0Chris Banes Configuration.SCREENLAYOUT_SIZE_XLARGE; 109500d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean isHoneycombApp = context.getApplicationInfo().targetSdkVersion >= 109600d183885b54de433e43118d3032340f40cac8c0Chris Banes android.os.Build.VERSION_CODES.HONEYCOMB; 109700d183885b54de433e43118d3032340f40cac8c0Chris Banes 109800d183885b54de433e43118d3032340f40cac8c0Chris Banes if (isXLarge && isHoneycombApp) { 109900d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 110000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 110100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 110200d183885b54de433e43118d3032340f40cac8c0Chris Banes 1103f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes Window.Callback cb = getWindowCallback(); 110400d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((cb != null) && (!cb.onMenuOpened(st.featureId, st.menu))) { 110500d183885b54de433e43118d3032340f40cac8c0Chris Banes // Callback doesn't want the menu to open, reset any state 110600d183885b54de433e43118d3032340f40cac8c0Chris Banes closePanel(st, true); 110700d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 110800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 110900d183885b54de433e43118d3032340f40cac8c0Chris Banes 111016e8d4dd91083260223c007c797e46bc8f631055Chris Banes final WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); 111146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (wm == null) { 111246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return; 111346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 111446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 111500d183885b54de433e43118d3032340f40cac8c0Chris Banes // Prepare panel (should have been done before, but just in case) 111600d183885b54de433e43118d3032340f40cac8c0Chris Banes if (!preparePanel(st, event)) { 111700d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 111800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 111900d183885b54de433e43118d3032340f40cac8c0Chris Banes 112046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes int width = WRAP_CONTENT; 112100d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st.decorView == null || st.refreshDecorView) { 112246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (st.decorView == null) { 112346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Initialize the panel decor, this will populate st.decorView 112446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (!initializePanelDecor(st) || (st.decorView == null)) 112546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return; 112646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } else if (st.refreshDecorView && (st.decorView.getChildCount() > 0)) { 112746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Decor needs refreshing, so remove its views 112846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.decorView.removeAllViews(); 112946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 113000d183885b54de433e43118d3032340f40cac8c0Chris Banes 113146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // This will populate st.shownPanelView 113246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (!initializePanelContent(st) || !st.hasPanelItems()) { 113346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return; 113446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 113546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 113646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes ViewGroup.LayoutParams lp = st.shownPanelView.getLayoutParams(); 113746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (lp == null) { 113846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes lp = new ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT); 113946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 114046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 114146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes int backgroundResId = st.background; 114246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.decorView.setBackgroundResource(backgroundResId); 114346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 114446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes ViewParent shownPanelParent = st.shownPanelView.getParent(); 114546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (shownPanelParent != null && shownPanelParent instanceof ViewGroup) { 114646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes ((ViewGroup) shownPanelParent).removeView(st.shownPanelView); 114746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 114846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.decorView.addView(st.shownPanelView, lp); 114946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 115046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes /* 115146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes * Give focus to the view, if it or one of its children does not 115246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes * already have it. 115346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes */ 115446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (!st.shownPanelView.hasFocus()) { 115546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.shownPanelView.requestFocus(); 115646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 115746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } else if (st.createdPanelView != null) { 115846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // If we already had a panel view, carry width=MATCH_PARENT through 115946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // as we did above when it was created. 116046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes ViewGroup.LayoutParams lp = st.createdPanelView.getLayoutParams(); 116146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (lp != null && lp.width == ViewGroup.LayoutParams.MATCH_PARENT) { 116246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes width = MATCH_PARENT; 116346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 116400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 116500d183885b54de433e43118d3032340f40cac8c0Chris Banes 116600d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isHandled = false; 116746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 116846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 116946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes width, WRAP_CONTENT, 117046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.x, st.y, WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL, 117146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM 117246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, 117346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes PixelFormat.TRANSLUCENT); 117446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 117546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes lp.gravity = st.gravity; 117646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes lp.windowAnimations = st.windowAnimations; 117746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 117846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes wm.addView(st.decorView, lp); 117900d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isOpen = true; 118000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 118100d183885b54de433e43118d3032340f40cac8c0Chris Banes 118246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes private boolean initializePanelDecor(PanelFeatureState st) { 118357c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes st.setStyle(getActionBarThemedContext()); 118446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.decorView = new ListMenuDecorView(st.listPresenterContext); 118546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.gravity = Gravity.CENTER | Gravity.BOTTOM; 118646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return true; 118700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 118800d183885b54de433e43118d3032340f40cac8c0Chris Banes 118900d183885b54de433e43118d3032340f40cac8c0Chris Banes private void reopenMenu(MenuBuilder menu, boolean toggleMenuMode) { 119000d183885b54de433e43118d3032340f40cac8c0Chris Banes if (mDecorContentParent != null && mDecorContentParent.canShowOverflowMenu() && 119116e8d4dd91083260223c007c797e46bc8f631055Chris Banes (!ViewConfigurationCompat.hasPermanentMenuKey(ViewConfiguration.get(mContext)) || 119200d183885b54de433e43118d3032340f40cac8c0Chris Banes mDecorContentParent.isOverflowMenuShowPending())) { 11939b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes 1194f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes final Window.Callback cb = getWindowCallback(); 11959b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes 119600d183885b54de433e43118d3032340f40cac8c0Chris Banes if (!mDecorContentParent.isOverflowMenuShowing() || !toggleMenuMode) { 11979b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (cb != null && !isDestroyed()) { 11989b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes // If we have a menu invalidation pending, do it now. 11999b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (mInvalidatePanelMenuPosted && 12009b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes (mInvalidatePanelMenuFeatures & (1 << FEATURE_OPTIONS_PANEL)) != 0) { 1201ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes mWindow.getDecorView().removeCallbacks(mInvalidatePanelMenuRunnable); 12029b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes mInvalidatePanelMenuRunnable.run(); 12039b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes } 120400d183885b54de433e43118d3032340f40cac8c0Chris Banes 12059b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true); 120600d183885b54de433e43118d3032340f40cac8c0Chris Banes 12079b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes // If we don't have a menu or we're waiting for a full content refresh, 12089b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes // forget it. This is a lingering event that no longer matters. 12099b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (st.menu != null && !st.refreshMenuContent && 121046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes cb.onPreparePanel(FEATURE_OPTIONS_PANEL, st.createdPanelView, st.menu)) { 1211d25af35061a9f20d59b25329d613c62c20184dadChris Banes cb.onMenuOpened(FEATURE_SUPPORT_ACTION_BAR, st.menu); 12129b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes mDecorContentParent.showOverflowMenu(); 12139b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes } 121400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 121500d183885b54de433e43118d3032340f40cac8c0Chris Banes } else { 121600d183885b54de433e43118d3032340f40cac8c0Chris Banes mDecorContentParent.hideOverflowMenu(); 12179b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (!isDestroyed()) { 12189b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true); 1219d25af35061a9f20d59b25329d613c62c20184dadChris Banes cb.onPanelClosed(FEATURE_SUPPORT_ACTION_BAR, st.menu); 12209b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes } 122100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 122200d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 122300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 122400d183885b54de433e43118d3032340f40cac8c0Chris Banes 122500d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true); 122600d183885b54de433e43118d3032340f40cac8c0Chris Banes 122700d183885b54de433e43118d3032340f40cac8c0Chris Banes st.refreshDecorView = true; 122800d183885b54de433e43118d3032340f40cac8c0Chris Banes closePanel(st, false); 122900d183885b54de433e43118d3032340f40cac8c0Chris Banes 123000d183885b54de433e43118d3032340f40cac8c0Chris Banes openPanel(st, null); 123100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 123200d183885b54de433e43118d3032340f40cac8c0Chris Banes 123300d183885b54de433e43118d3032340f40cac8c0Chris Banes private boolean initializePanelMenu(final PanelFeatureState st) { 123416e8d4dd91083260223c007c797e46bc8f631055Chris Banes Context context = mContext; 123561c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes 123600d183885b54de433e43118d3032340f40cac8c0Chris Banes // If we have an action bar, initialize the menu with the right theme. 1237d25af35061a9f20d59b25329d613c62c20184dadChris Banes if ((st.featureId == FEATURE_OPTIONS_PANEL || st.featureId == FEATURE_SUPPORT_ACTION_BAR) && 123800d183885b54de433e43118d3032340f40cac8c0Chris Banes mDecorContentParent != null) { 123961c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes final TypedValue outValue = new TypedValue(); 124061c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes final Resources.Theme baseTheme = context.getTheme(); 124161c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes baseTheme.resolveAttribute(R.attr.actionBarTheme, outValue, true); 124261c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes 124361c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes Resources.Theme widgetTheme = null; 124461c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes if (outValue.resourceId != 0) { 124561c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme = context.getResources().newTheme(); 124661c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme.setTo(baseTheme); 124761c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme.applyStyle(outValue.resourceId, true); 124861c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme.resolveAttribute( 124961c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes R.attr.actionBarWidgetTheme, outValue, true); 125061c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes } else { 125161c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes baseTheme.resolveAttribute( 125261c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes R.attr.actionBarWidgetTheme, outValue, true); 125361c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes } 125461c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes 125561c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes if (outValue.resourceId != 0) { 125661c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes if (widgetTheme == null) { 125761c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme = context.getResources().newTheme(); 125861c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme.setTo(baseTheme); 125961c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes } 126061c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes widgetTheme.applyStyle(outValue.resourceId, true); 126161c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes } 126261c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes 126361c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes if (widgetTheme != null) { 126461c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes context = new ContextThemeWrapper(context, 0); 126561c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes context.getTheme().setTo(widgetTheme); 126661c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes } 126761c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes } 126861c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes 126900d183885b54de433e43118d3032340f40cac8c0Chris Banes final MenuBuilder menu = new MenuBuilder(context); 127000d183885b54de433e43118d3032340f40cac8c0Chris Banes menu.setCallback(this); 127100d183885b54de433e43118d3032340f40cac8c0Chris Banes st.setMenu(menu); 127261c0bbe56a13fe55ce91a5b1d64e751164ecb894Chris Banes 12738902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes return true; 12748902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 12758902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 127600d183885b54de433e43118d3032340f40cac8c0Chris Banes private boolean initializePanelContent(PanelFeatureState st) { 127746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (st.createdPanelView != null) { 127846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.shownPanelView = st.createdPanelView; 127946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return true; 128046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 128146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 128200d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st.menu == null) { 128300d183885b54de433e43118d3032340f40cac8c0Chris Banes return false; 128400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 128500d183885b54de433e43118d3032340f40cac8c0Chris Banes 128600d183885b54de433e43118d3032340f40cac8c0Chris Banes if (mPanelMenuPresenterCallback == null) { 128700d183885b54de433e43118d3032340f40cac8c0Chris Banes mPanelMenuPresenterCallback = new PanelMenuPresenterCallback(); 128800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 128900d183885b54de433e43118d3032340f40cac8c0Chris Banes 129057c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes MenuView menuView = st.getListMenuView(mPanelMenuPresenterCallback); 129100d183885b54de433e43118d3032340f40cac8c0Chris Banes 129200d183885b54de433e43118d3032340f40cac8c0Chris Banes st.shownPanelView = (View) menuView; 129300d183885b54de433e43118d3032340f40cac8c0Chris Banes 129400d183885b54de433e43118d3032340f40cac8c0Chris Banes return st.shownPanelView != null; 129500d183885b54de433e43118d3032340f40cac8c0Chris Banes } 129600d183885b54de433e43118d3032340f40cac8c0Chris Banes 129700d183885b54de433e43118d3032340f40cac8c0Chris Banes private boolean preparePanel(PanelFeatureState st, KeyEvent event) { 12989b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (isDestroyed()) { 12999b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes return false; 13009b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes } 13019b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes 13028902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // Already prepared (isPrepared will be reset to false later) 130300d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st.isPrepared) { 13048902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes return true; 13058902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 13068902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 130700d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((mPreparedPanel != null) && (mPreparedPanel != st)) { 130800d183885b54de433e43118d3032340f40cac8c0Chris Banes // Another Panel is prepared and possibly open, so close it 130900d183885b54de433e43118d3032340f40cac8c0Chris Banes closePanel(mPreparedPanel, false); 131000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 131100d183885b54de433e43118d3032340f40cac8c0Chris Banes 1312f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes final Window.Callback cb = getWindowCallback(); 131346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 131446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (cb != null) { 131546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.createdPanelView = cb.onCreatePanelView(st.featureId); 131646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 131746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 131800d183885b54de433e43118d3032340f40cac8c0Chris Banes final boolean isActionBarMenu = 1319d25af35061a9f20d59b25329d613c62c20184dadChris Banes (st.featureId == FEATURE_OPTIONS_PANEL || st.featureId == FEATURE_SUPPORT_ACTION_BAR); 132000d183885b54de433e43118d3032340f40cac8c0Chris Banes 132100d183885b54de433e43118d3032340f40cac8c0Chris Banes if (isActionBarMenu && mDecorContentParent != null) { 13228088261dec5dd277ccace13fe00f280ffa80098cChris Banes // Enforce ordering guarantees around events so that the action bar never 13238088261dec5dd277ccace13fe00f280ffa80098cChris Banes // dispatches menu-related events before the panel is prepared. 13248088261dec5dd277ccace13fe00f280ffa80098cChris Banes mDecorContentParent.setMenuPrepared(); 13258088261dec5dd277ccace13fe00f280ffa80098cChris Banes } 13268088261dec5dd277ccace13fe00f280ffa80098cChris Banes 13276094d733a9bcc923491937532255f79eb23fab90Chris Banes if (st.createdPanelView == null && 13286094d733a9bcc923491937532255f79eb23fab90Chris Banes (!isActionBarMenu || !(peekSupportActionBar() instanceof ToolbarActionBar))) { 13296094d733a9bcc923491937532255f79eb23fab90Chris Banes // Since ToolbarActionBar handles the list options menu itself, we only want to 13306094d733a9bcc923491937532255f79eb23fab90Chris Banes // init this menu panel if we're not using a TAB. 133146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (st.menu == null || st.refreshMenuContent) { 133246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (st.menu == null) { 133346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (!initializePanelMenu(st) || (st.menu == null)) { 133446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return false; 133546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 13368902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 13378902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 133846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (isActionBarMenu && mDecorContentParent != null) { 133946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (mActionMenuPresenterCallback == null) { 134046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes mActionMenuPresenterCallback = new ActionMenuPresenterCallback(); 134146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 134246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes mDecorContentParent.setMenu(st.menu, mActionMenuPresenterCallback); 134346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 134446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 134546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Creating the panel menu will involve a lot of manipulation; 134646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // don't dispatch change events to presenters until we're done. 134746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.menu.stopDispatchingItemsChanged(); 1348f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes if (!cb.onCreatePanelMenu(st.featureId, st.menu)) { 134946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Ditch the menu created above 135046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.setMenu(null); 135146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 135246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (isActionBarMenu && mDecorContentParent != null) { 135346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Don't show it in the action bar either 135446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes mDecorContentParent.setMenu(null, mActionMenuPresenterCallback); 135546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 135646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 135746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return false; 135803fc11b659da1645507062bddda450136e13af35Chris Banes } 135946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 136046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.refreshMenuContent = false; 13618902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 13628902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 136346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Preparing the panel menu can involve a lot of manipulation; 13648902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // don't dispatch change events to presenters until we're done. 136500d183885b54de433e43118d3032340f40cac8c0Chris Banes st.menu.stopDispatchingItemsChanged(); 13668902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 136746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Restore action view state before we prepare. This gives apps 136846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // an opportunity to override frozen/restored state in onPrepare. 136946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (st.frozenActionViewState != null) { 137046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.menu.restoreActionViewStates(st.frozenActionViewState); 137146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.frozenActionViewState = null; 137246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 137346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 137446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Callback and return if the callback does not want to show the menu 137546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (!cb.onPreparePanel(FEATURE_OPTIONS_PANEL, st.createdPanelView, st.menu)) { 137600d183885b54de433e43118d3032340f40cac8c0Chris Banes if (isActionBarMenu && mDecorContentParent != null) { 137746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // The app didn't want to show the menu for now but it still exists. 137846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Clear it out of the action bar. 137903fc11b659da1645507062bddda450136e13af35Chris Banes mDecorContentParent.setMenu(null, mActionMenuPresenterCallback); 13808902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 138146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.menu.startDispatchingItemsChanged(); 13828902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes return false; 13838902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 13848902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 138546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Set the proper keymap 138646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes KeyCharacterMap kmap = KeyCharacterMap.load( 138746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes event != null ? event.getDeviceId() : KeyCharacterMap.VIRTUAL_KEYBOARD); 138846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.qwertyMode = kmap.getKeyboardType() != KeyCharacterMap.NUMERIC; 138946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.menu.setQwertyMode(st.qwertyMode); 139000d183885b54de433e43118d3032340f40cac8c0Chris Banes st.menu.startDispatchingItemsChanged(); 13918902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 13928902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 13938902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes // Set other state 139400d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isPrepared = true; 139500d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isHandled = false; 139600d183885b54de433e43118d3032340f40cac8c0Chris Banes mPreparedPanel = st; 13978902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 13988902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes return true; 13998902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes } 14008902df1bf0006a156503d40b1fc8a01f95d5b806Chris Banes 140100d183885b54de433e43118d3032340f40cac8c0Chris Banes private void checkCloseActionMenu(MenuBuilder menu) { 140203fc11b659da1645507062bddda450136e13af35Chris Banes if (mClosingActionMenu) { 140303fc11b659da1645507062bddda450136e13af35Chris Banes return; 140403fc11b659da1645507062bddda450136e13af35Chris Banes } 140503fc11b659da1645507062bddda450136e13af35Chris Banes 140603fc11b659da1645507062bddda450136e13af35Chris Banes mClosingActionMenu = true; 140703fc11b659da1645507062bddda450136e13af35Chris Banes mDecorContentParent.dismissPopups(); 1408f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes Window.Callback cb = getWindowCallback(); 14099b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (cb != null && !isDestroyed()) { 1410d25af35061a9f20d59b25329d613c62c20184dadChris Banes cb.onPanelClosed(FEATURE_SUPPORT_ACTION_BAR, menu); 141100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 141203fc11b659da1645507062bddda450136e13af35Chris Banes mClosingActionMenu = false; 141303fc11b659da1645507062bddda450136e13af35Chris Banes } 141403fc11b659da1645507062bddda450136e13af35Chris Banes 141546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes private void closePanel(int featureId) { 141646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes closePanel(getPanelState(featureId, true), true); 141746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 141846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 141900d183885b54de433e43118d3032340f40cac8c0Chris Banes private void closePanel(PanelFeatureState st, boolean doCallback) { 142000d183885b54de433e43118d3032340f40cac8c0Chris Banes if (doCallback && st.featureId == FEATURE_OPTIONS_PANEL && 142100d183885b54de433e43118d3032340f40cac8c0Chris Banes mDecorContentParent != null && mDecorContentParent.isOverflowMenuShowing()) { 142200d183885b54de433e43118d3032340f40cac8c0Chris Banes checkCloseActionMenu(st.menu); 142300d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 142400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 142500d183885b54de433e43118d3032340f40cac8c0Chris Banes 1426436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes final WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); 14274d95686e7ade79bfb1081047e90de4bf2affbbcaChris Banes if (wm != null && st.isOpen && st.decorView != null) { 1428436e191f80e197712dd1a7f1f7c61acfff8b1f04Chris Banes wm.removeView(st.decorView); 14294d95686e7ade79bfb1081047e90de4bf2affbbcaChris Banes 14304d95686e7ade79bfb1081047e90de4bf2affbbcaChris Banes if (doCallback) { 14314d95686e7ade79bfb1081047e90de4bf2affbbcaChris Banes callOnPanelClosed(st.featureId, st, null); 14324d95686e7ade79bfb1081047e90de4bf2affbbcaChris Banes } 143300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 143400d183885b54de433e43118d3032340f40cac8c0Chris Banes 143500d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isPrepared = false; 143600d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isHandled = false; 143700d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isOpen = false; 143800d183885b54de433e43118d3032340f40cac8c0Chris Banes 143900d183885b54de433e43118d3032340f40cac8c0Chris Banes // This view is no longer shown, so null it out 144000d183885b54de433e43118d3032340f40cac8c0Chris Banes st.shownPanelView = null; 144100d183885b54de433e43118d3032340f40cac8c0Chris Banes 144200d183885b54de433e43118d3032340f40cac8c0Chris Banes // Next time the menu opens, it should not be in expanded mode, so 144300d183885b54de433e43118d3032340f40cac8c0Chris Banes // force a refresh of the decor 144400d183885b54de433e43118d3032340f40cac8c0Chris Banes st.refreshDecorView = true; 144500d183885b54de433e43118d3032340f40cac8c0Chris Banes 144600d183885b54de433e43118d3032340f40cac8c0Chris Banes if (mPreparedPanel == st) { 144700d183885b54de433e43118d3032340f40cac8c0Chris Banes mPreparedPanel = null; 144803fc11b659da1645507062bddda450136e13af35Chris Banes } 144903fc11b659da1645507062bddda450136e13af35Chris Banes } 145003fc11b659da1645507062bddda450136e13af35Chris Banes 145146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes private boolean onKeyDownPanel(int featureId, KeyEvent event) { 145246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (event.getRepeatCount() == 0) { 145346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes PanelFeatureState st = getPanelState(featureId, true); 145446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (!st.isOpen) { 145546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return preparePanel(st, event); 145646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 145746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 145846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 145946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return false; 146046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 146146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 1462559fa14454cc053127b3b96c0e63c48c06937e38Chris Banes private boolean onKeyUpPanel(int featureId, KeyEvent event) { 146346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (mActionMode != null) { 1464559fa14454cc053127b3b96c0e63c48c06937e38Chris Banes return false; 146546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 146646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 1467559fa14454cc053127b3b96c0e63c48c06937e38Chris Banes boolean handled = false; 146846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes final PanelFeatureState st = getPanelState(featureId, true); 146946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (featureId == FEATURE_OPTIONS_PANEL && mDecorContentParent != null && 147046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes mDecorContentParent.canShowOverflowMenu() && 147116e8d4dd91083260223c007c797e46bc8f631055Chris Banes !ViewConfigurationCompat.hasPermanentMenuKey(ViewConfiguration.get(mContext))) { 147246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (!mDecorContentParent.isOverflowMenuShowing()) { 147346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (!isDestroyed() && preparePanel(st, event)) { 1474559fa14454cc053127b3b96c0e63c48c06937e38Chris Banes handled = mDecorContentParent.showOverflowMenu(); 147546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 147646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } else { 1477559fa14454cc053127b3b96c0e63c48c06937e38Chris Banes handled = mDecorContentParent.hideOverflowMenu(); 147846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 147946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } else { 148046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (st.isOpen || st.isHandled) { 148146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Play the sound effect if the user closed an open menu (and not if 148246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // they just released a menu shortcut) 1483559fa14454cc053127b3b96c0e63c48c06937e38Chris Banes handled = st.isOpen; 148446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Close menu 148546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes closePanel(st, true); 148646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } else if (st.isPrepared) { 148746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes boolean show = true; 148846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (st.refreshMenuContent) { 148946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Something may have invalidated the menu since we prepared it. 149046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Re-prepare it to refresh. 149146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes st.isPrepared = false; 149246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes show = preparePanel(st, event); 149346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 149446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 149546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (show) { 149646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes // Show menu 149746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes openPanel(st, event); 1498559fa14454cc053127b3b96c0e63c48c06937e38Chris Banes handled = true; 149946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 150046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 150146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 150246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 1503559fa14454cc053127b3b96c0e63c48c06937e38Chris Banes if (handled) { 150416e8d4dd91083260223c007c797e46bc8f631055Chris Banes AudioManager audioManager = (AudioManager) mContext.getSystemService( 150546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes Context.AUDIO_SERVICE); 150646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (audioManager != null) { 150746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK); 150846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } else { 150946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes Log.w(TAG, "Couldn't get audio manager"); 151046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 151146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 1512559fa14454cc053127b3b96c0e63c48c06937e38Chris Banes return handled; 151346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 151446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 151500d183885b54de433e43118d3032340f40cac8c0Chris Banes private void callOnPanelClosed(int featureId, PanelFeatureState panel, Menu menu) { 151600d183885b54de433e43118d3032340f40cac8c0Chris Banes // Try to get a menu 151700d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu == null) { 151800d183885b54de433e43118d3032340f40cac8c0Chris Banes // Need a panel to grab the menu, so try to get that 151900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (panel == null) { 152000d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((featureId >= 0) && (featureId < mPanels.length)) { 152100d183885b54de433e43118d3032340f40cac8c0Chris Banes panel = mPanels[featureId]; 152200d183885b54de433e43118d3032340f40cac8c0Chris Banes } 152300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 152400d183885b54de433e43118d3032340f40cac8c0Chris Banes 152500d183885b54de433e43118d3032340f40cac8c0Chris Banes if (panel != null) { 152600d183885b54de433e43118d3032340f40cac8c0Chris Banes // menu still may be null, which is okay--we tried our best 152700d183885b54de433e43118d3032340f40cac8c0Chris Banes menu = panel.menu; 152800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 152900d183885b54de433e43118d3032340f40cac8c0Chris Banes } 153000d183885b54de433e43118d3032340f40cac8c0Chris Banes 153100d183885b54de433e43118d3032340f40cac8c0Chris Banes // If the panel is not open, do not callback 153200d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((panel != null) && (!panel.isOpen)) 153300d183885b54de433e43118d3032340f40cac8c0Chris Banes return; 153400d183885b54de433e43118d3032340f40cac8c0Chris Banes 1535d2f8851a0a27ea6a2ddf5a88097f3d10eed38485Chris Banes if (!isDestroyed()) { 1536d2f8851a0a27ea6a2ddf5a88097f3d10eed38485Chris Banes // We need to be careful which callback we dispatch the call to. We can not dispatch 1537d2f8851a0a27ea6a2ddf5a88097f3d10eed38485Chris Banes // this to the Window's callback since that will call back into this method and cause a 1538d2f8851a0a27ea6a2ddf5a88097f3d10eed38485Chris Banes // crash. Instead we need to dispatch down to the original Activity/Dialog/etc. 1539d2f8851a0a27ea6a2ddf5a88097f3d10eed38485Chris Banes mOriginalWindowCallback.onPanelClosed(featureId, menu); 1540f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 154100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 154200d183885b54de433e43118d3032340f40cac8c0Chris Banes 154300d183885b54de433e43118d3032340f40cac8c0Chris Banes private PanelFeatureState findMenuPanel(Menu menu) { 154400d183885b54de433e43118d3032340f40cac8c0Chris Banes final PanelFeatureState[] panels = mPanels; 154500d183885b54de433e43118d3032340f40cac8c0Chris Banes final int N = panels != null ? panels.length : 0; 154600d183885b54de433e43118d3032340f40cac8c0Chris Banes for (int i = 0; i < N; i++) { 154700d183885b54de433e43118d3032340f40cac8c0Chris Banes final PanelFeatureState panel = panels[i]; 154800d183885b54de433e43118d3032340f40cac8c0Chris Banes if (panel != null && panel.menu == menu) { 154900d183885b54de433e43118d3032340f40cac8c0Chris Banes return panel; 155000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 155100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 155200d183885b54de433e43118d3032340f40cac8c0Chris Banes return null; 155300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 155400d183885b54de433e43118d3032340f40cac8c0Chris Banes 155585035fae2e7f292a529dc70e8d41cebc799e7d4fChris Banes protected PanelFeatureState getPanelState(int featureId, boolean required) { 155600d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState[] ar; 155700d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((ar = mPanels) == null || ar.length <= featureId) { 155800d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState[] nar = new PanelFeatureState[featureId + 1]; 155900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (ar != null) { 156000d183885b54de433e43118d3032340f40cac8c0Chris Banes System.arraycopy(ar, 0, nar, 0, ar.length); 156100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 156200d183885b54de433e43118d3032340f40cac8c0Chris Banes mPanels = ar = nar; 156303fc11b659da1645507062bddda450136e13af35Chris Banes } 156400d183885b54de433e43118d3032340f40cac8c0Chris Banes 156500d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState st = ar[featureId]; 156600d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st == null) { 156700d183885b54de433e43118d3032340f40cac8c0Chris Banes ar[featureId] = st = new PanelFeatureState(featureId); 156800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 156900d183885b54de433e43118d3032340f40cac8c0Chris Banes return st; 157003fc11b659da1645507062bddda450136e13af35Chris Banes } 157103fc11b659da1645507062bddda450136e13af35Chris Banes 1572f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes private boolean performPanelShortcut(PanelFeatureState st, int keyCode, KeyEvent event, 157300d183885b54de433e43118d3032340f40cac8c0Chris Banes int flags) { 1574dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes if (event.isSystem()) { 1575dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes return false; 1576dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 1577dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 1578dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes boolean handled = false; 1579dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 1580dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // Only try to perform menu shortcuts if preparePanel returned true (possible false 1581dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // return value from application not wanting to show the menu). 158200d183885b54de433e43118d3032340f40cac8c0Chris Banes if ((st.isPrepared || preparePanel(st, event)) && st.menu != null) { 1583dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // The menu is prepared now, perform the shortcut on it 158400d183885b54de433e43118d3032340f40cac8c0Chris Banes handled = st.menu.performShortcut(keyCode, event, flags); 1585dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 1586dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 1587dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes if (handled) { 1588dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes // Only close down the menu if we don't have an action bar keeping it open. 1589dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes if ((flags & Menu.FLAG_PERFORM_NO_CLOSE) == 0 && mDecorContentParent == null) { 159000d183885b54de433e43118d3032340f40cac8c0Chris Banes closePanel(st, true); 1591dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 1592dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 1593dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 1594dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes return handled; 1595dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes } 1596dea1122145ed85590d298a3a9d88ba9f9e2f5f46Chris Banes 159700d183885b54de433e43118d3032340f40cac8c0Chris Banes private void invalidatePanelMenu(int featureId) { 159800d183885b54de433e43118d3032340f40cac8c0Chris Banes mInvalidatePanelMenuFeatures |= 1 << featureId; 159900d183885b54de433e43118d3032340f40cac8c0Chris Banes 1600ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes if (!mInvalidatePanelMenuPosted) { 1601ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes ViewCompat.postOnAnimation(mWindow.getDecorView(), mInvalidatePanelMenuRunnable); 160200d183885b54de433e43118d3032340f40cac8c0Chris Banes mInvalidatePanelMenuPosted = true; 160300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 160400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 160500d183885b54de433e43118d3032340f40cac8c0Chris Banes 160600d183885b54de433e43118d3032340f40cac8c0Chris Banes private void doInvalidatePanelMenu(int featureId) { 160700d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState st = getPanelState(featureId, true); 160800d183885b54de433e43118d3032340f40cac8c0Chris Banes Bundle savedActionViewStates = null; 160900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st.menu != null) { 161000d183885b54de433e43118d3032340f40cac8c0Chris Banes savedActionViewStates = new Bundle(); 161100d183885b54de433e43118d3032340f40cac8c0Chris Banes st.menu.saveActionViewStates(savedActionViewStates); 161200d183885b54de433e43118d3032340f40cac8c0Chris Banes if (savedActionViewStates.size() > 0) { 161300d183885b54de433e43118d3032340f40cac8c0Chris Banes st.frozenActionViewState = savedActionViewStates; 161400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 161500d183885b54de433e43118d3032340f40cac8c0Chris Banes // This will be started again when the panel is prepared. 161600d183885b54de433e43118d3032340f40cac8c0Chris Banes st.menu.stopDispatchingItemsChanged(); 161700d183885b54de433e43118d3032340f40cac8c0Chris Banes st.menu.clear(); 161800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 161900d183885b54de433e43118d3032340f40cac8c0Chris Banes st.refreshMenuContent = true; 162000d183885b54de433e43118d3032340f40cac8c0Chris Banes st.refreshDecorView = true; 162100d183885b54de433e43118d3032340f40cac8c0Chris Banes 162200d183885b54de433e43118d3032340f40cac8c0Chris Banes // Prepare the options panel if we have an action bar 1623d25af35061a9f20d59b25329d613c62c20184dadChris Banes if ((featureId == FEATURE_SUPPORT_ACTION_BAR || featureId == FEATURE_OPTIONS_PANEL) 162400d183885b54de433e43118d3032340f40cac8c0Chris Banes && mDecorContentParent != null) { 162500d183885b54de433e43118d3032340f40cac8c0Chris Banes st = getPanelState(Window.FEATURE_OPTIONS_PANEL, false); 162600d183885b54de433e43118d3032340f40cac8c0Chris Banes if (st != null) { 162700d183885b54de433e43118d3032340f40cac8c0Chris Banes st.isPrepared = false; 162800d183885b54de433e43118d3032340f40cac8c0Chris Banes preparePanel(st, null); 162900d183885b54de433e43118d3032340f40cac8c0Chris Banes } 163000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 163100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 163200d183885b54de433e43118d3032340f40cac8c0Chris Banes 1633ea4f700ac38424954c56df5138ff794def50b019Chris Banes /** 1634ea4f700ac38424954c56df5138ff794def50b019Chris Banes * Updates the status bar guard 1635ea4f700ac38424954c56df5138ff794def50b019Chris Banes * 1636ea4f700ac38424954c56df5138ff794def50b019Chris Banes * @param insetTop the current top system window inset 1637ea4f700ac38424954c56df5138ff794def50b019Chris Banes * @return the new top system window inset 1638ea4f700ac38424954c56df5138ff794def50b019Chris Banes */ 1639ea4f700ac38424954c56df5138ff794def50b019Chris Banes private int updateStatusGuard(int insetTop) { 1640ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes boolean showStatusGuard = false; 1641ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes // Show the status guard when the non-overlay contextual action bar is showing 1642ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mActionModeView != null) { 1643ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mActionModeView.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { 1644ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) 1645ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mActionModeView.getLayoutParams(); 1646ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes boolean mlpChanged = false; 1647ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes 1648ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mActionModeView.isShown()) { 16497efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell if (mTempRect1 == null) { 16507efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell mTempRect1 = new Rect(); 16517efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell mTempRect2 = new Rect(); 16527efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell } 16537efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell final Rect insets = mTempRect1; 16547efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell final Rect localInsets = mTempRect2; 16557efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell insets.set(0, insetTop, 0, 0); 16567efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell 16577efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell ViewUtils.computeFitSystemWindows(mSubDecor, insets, localInsets); 16587efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell final int newMargin = localInsets.top == 0 ? insetTop : 0; 16597efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell if (mlp.topMargin != newMargin) { 16607efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell mlpChanged = true; 16617efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell mlp.topMargin = insetTop; 16627efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell 1663ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mStatusGuard == null) { 166416e8d4dd91083260223c007c797e46bc8f631055Chris Banes mStatusGuard = new View(mContext); 166516e8d4dd91083260223c007c797e46bc8f631055Chris Banes mStatusGuard.setBackgroundColor(mContext.getResources() 1666ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes .getColor(R.color.abc_input_method_navigation_guard)); 16677efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell mSubDecor.addView(mStatusGuard, -1, 1668ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1669ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes insetTop)); 1670ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } else { 1671ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes ViewGroup.LayoutParams lp = mStatusGuard.getLayoutParams(); 1672ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (lp.height != insetTop) { 1673ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes lp.height = insetTop; 1674ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mStatusGuard.setLayoutParams(lp); 1675ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1676ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1677ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1678ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes 1679bbb50c78cc6ee24677c79bd4548fa38fcdc41d92Adam Powell // The action mode's theme may differ from the app, so 1680bbb50c78cc6ee24677c79bd4548fa38fcdc41d92Adam Powell // always show the status guard above it. 1681bbb50c78cc6ee24677c79bd4548fa38fcdc41d92Adam Powell showStatusGuard = mStatusGuard != null; 1682bbb50c78cc6ee24677c79bd4548fa38fcdc41d92Adam Powell 16837efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell // We only need to consume the insets if the action 16847efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell // mode is overlaid on the app content (e.g. it's 16857efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell // sitting in a FrameLayout, see 16867efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell // screen_simple_overlay_action_mode.xml). 1687bbb50c78cc6ee24677c79bd4548fa38fcdc41d92Adam Powell if (!mOverlayActionMode && showStatusGuard) { 16887efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell insetTop = 0; 16897efc56b68ff933dfeeac81dd2d8a32096b90f0f4Adam Powell } 1690ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } else { 1691ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes // reset top margin 1692ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mlp.topMargin != 0) { 1693ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mlpChanged = true; 1694ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mlp.topMargin = 0; 1695ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1696ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1697ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mlpChanged) { 1698ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mActionModeView.setLayoutParams(mlp); 1699ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1700ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1701ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1702ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes if (mStatusGuard != null) { 1703ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes mStatusGuard.setVisibility(showStatusGuard ? View.VISIBLE : View.GONE); 1704ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1705ea4f700ac38424954c56df5138ff794def50b019Chris Banes 1706ea4f700ac38424954c56df5138ff794def50b019Chris Banes return insetTop; 1707ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes } 1708ec3f49d21a507835c1f50ce5600000b587a2af08Chris Banes 1709cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes private void throwFeatureRequestIfSubDecorInstalled() { 1710cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes if (mSubDecorInstalled) { 1711cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes throw new AndroidRuntimeException( 1712f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes "Window feature must be requested before adding content"); 1713cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes } 1714cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes } 1715cc7aada3ee922cfb38eeb36ee696cc73dcbae0a4Chris Banes 17168122ad54f129c2214631fad86cabda82815cc0d8Chris Banes private int sanitizeWindowFeatureId(int featureId) { 17178122ad54f129c2214631fad86cabda82815cc0d8Chris Banes if (featureId == WindowCompat.FEATURE_ACTION_BAR) { 17188122ad54f129c2214631fad86cabda82815cc0d8Chris Banes Log.i(TAG, "You should now use the AppCompatDelegate.FEATURE_SUPPORT_ACTION_BAR" 17198122ad54f129c2214631fad86cabda82815cc0d8Chris Banes + " id when requesting this feature."); 17208122ad54f129c2214631fad86cabda82815cc0d8Chris Banes return FEATURE_SUPPORT_ACTION_BAR; 17218122ad54f129c2214631fad86cabda82815cc0d8Chris Banes } else if (featureId == WindowCompat.FEATURE_ACTION_BAR_OVERLAY) { 17228122ad54f129c2214631fad86cabda82815cc0d8Chris Banes Log.i(TAG, "You should now use the AppCompatDelegate.FEATURE_SUPPORT_ACTION_BAR_OVERLAY" 17238122ad54f129c2214631fad86cabda82815cc0d8Chris Banes + " id when requesting this feature."); 17248122ad54f129c2214631fad86cabda82815cc0d8Chris Banes return FEATURE_SUPPORT_ACTION_BAR_OVERLAY; 17258122ad54f129c2214631fad86cabda82815cc0d8Chris Banes } 17268122ad54f129c2214631fad86cabda82815cc0d8Chris Banes // Else we'll just return the original id 17278122ad54f129c2214631fad86cabda82815cc0d8Chris Banes return featureId; 17288122ad54f129c2214631fad86cabda82815cc0d8Chris Banes } 17298122ad54f129c2214631fad86cabda82815cc0d8Chris Banes 173016e8d4dd91083260223c007c797e46bc8f631055Chris Banes ViewGroup getSubDecor() { 173116e8d4dd91083260223c007c797e46bc8f631055Chris Banes return mSubDecor; 173216e8d4dd91083260223c007c797e46bc8f631055Chris Banes } 173316e8d4dd91083260223c007c797e46bc8f631055Chris Banes 1734b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes private void dismissPopups() { 1735b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes if (mDecorContentParent != null) { 1736b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes mDecorContentParent.dismissPopups(); 1737b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes } 1738b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes 1739b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes if (mActionModePopup != null) { 1740ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes mWindow.getDecorView().removeCallbacks(mShowActionModePopup); 1741b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes if (mActionModePopup.isShowing()) { 1742d3a70c7dfb3292c72f9bee4cd47a632fc01d5231Chris Banes try { 1743d3a70c7dfb3292c72f9bee4cd47a632fc01d5231Chris Banes mActionModePopup.dismiss(); 1744d3a70c7dfb3292c72f9bee4cd47a632fc01d5231Chris Banes } catch (IllegalArgumentException e) { 1745d3a70c7dfb3292c72f9bee4cd47a632fc01d5231Chris Banes // Pre-v18, there are times when the Window will remove the popup before us. 1746d3a70c7dfb3292c72f9bee4cd47a632fc01d5231Chris Banes // In these cases we need to swallow the resulting exception. 1747d3a70c7dfb3292c72f9bee4cd47a632fc01d5231Chris Banes } 1748b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes } 1749b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes mActionModePopup = null; 1750b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes } 1751b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes endOnGoingFadeAnimation(); 1752b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes 1753b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false); 1754b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes if (st != null && st.menu != null) { 1755b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes st.menu.close(); 1756b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes } 1757b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes } 1758b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes 1759ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 1760d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes * Clears out internal reference when the action mode is destroyed. 1761d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes */ 1762547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes class ActionModeCallbackWrapperV7 implements ActionMode.Callback { 1763d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes private ActionMode.Callback mWrapped; 1764d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 1765547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes public ActionModeCallbackWrapperV7(ActionMode.Callback wrapped) { 1766d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes mWrapped = wrapped; 1767d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 1768d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 1769d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes public boolean onCreateActionMode(ActionMode mode, Menu menu) { 1770d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes return mWrapped.onCreateActionMode(mode, menu); 1771d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 1772d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 1773d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes public boolean onPrepareActionMode(ActionMode mode, Menu menu) { 17749addcff1698f71fb4145f39dacaf33a9c1fef24fChris Banes return mWrapped.onPrepareActionMode(mode, menu); 1775d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 1776d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 1777d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes public boolean onActionItemClicked(ActionMode mode, MenuItem item) { 1778d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes return mWrapped.onActionItemClicked(mode, item); 1779d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 1780d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 1781d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes public void onDestroyActionMode(ActionMode mode) { 1782d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes mWrapped.onDestroyActionMode(mode); 17834c2a95906254748cb9a843b061288265d6e185a9Chris Banes if (mActionModePopup != null) { 178416e8d4dd91083260223c007c797e46bc8f631055Chris Banes mWindow.getDecorView().removeCallbacks(mShowActionModePopup); 17854c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 1786c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu 17874c2a95906254748cb9a843b061288265d6e185a9Chris Banes if (mActionModeView != null) { 1788c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu endOnGoingFadeAnimation(); 1789c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu mFadeAnim = ViewCompat.animate(mActionModeView).alpha(0f); 1790c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu mFadeAnim.setListener(new ViewPropertyAnimatorListenerAdapter() { 1791c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu @Override 1792c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu public void onAnimationEnd(View view) { 1793c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu mActionModeView.setVisibility(View.GONE); 1794c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu if (mActionModePopup != null) { 1795c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu mActionModePopup.dismiss(); 1796c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu } else if (mActionModeView.getParent() instanceof View) { 1797c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu ViewCompat.requestApplyInsets((View) mActionModeView.getParent()); 1798c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu } 1799c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu mActionModeView.removeAllViews(); 1800c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu mFadeAnim.setListener(null); 1801c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu mFadeAnim = null; 1802c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu } 1803c04ae73a9793cdad7784fd543f3b7ad32cc8dbedDoris Liu }); 18044c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 1805f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes if (mAppCompatCallback != null) { 1806f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes mAppCompatCallback.onSupportActionModeFinished(mActionMode); 18074c2a95906254748cb9a843b061288265d6e185a9Chris Banes } 1808d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes mActionMode = null; 1809d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 1810d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes } 1811d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes 181203fc11b659da1645507062bddda450136e13af35Chris Banes private final class PanelMenuPresenterCallback implements MenuPresenter.Callback { 181303fc11b659da1645507062bddda450136e13af35Chris Banes @Override 181400d183885b54de433e43118d3032340f40cac8c0Chris Banes public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 181500d183885b54de433e43118d3032340f40cac8c0Chris Banes final Menu parentMenu = menu.getRootMenu(); 181600d183885b54de433e43118d3032340f40cac8c0Chris Banes final boolean isSubMenu = parentMenu != menu; 181700d183885b54de433e43118d3032340f40cac8c0Chris Banes final PanelFeatureState panel = findMenuPanel(isSubMenu ? parentMenu : menu); 181800d183885b54de433e43118d3032340f40cac8c0Chris Banes if (panel != null) { 181900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (isSubMenu) { 182000d183885b54de433e43118d3032340f40cac8c0Chris Banes callOnPanelClosed(panel.featureId, panel, parentMenu); 182100d183885b54de433e43118d3032340f40cac8c0Chris Banes closePanel(panel, true); 182200d183885b54de433e43118d3032340f40cac8c0Chris Banes } else { 182300d183885b54de433e43118d3032340f40cac8c0Chris Banes // Close the panel and only do the callback if the menu is being 182400d183885b54de433e43118d3032340f40cac8c0Chris Banes // closed completely, not if opening a sub menu 182500d183885b54de433e43118d3032340f40cac8c0Chris Banes closePanel(panel, allMenusAreClosing); 182600d183885b54de433e43118d3032340f40cac8c0Chris Banes } 182700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 182803fc11b659da1645507062bddda450136e13af35Chris Banes } 182903fc11b659da1645507062bddda450136e13af35Chris Banes 183003fc11b659da1645507062bddda450136e13af35Chris Banes @Override 183100d183885b54de433e43118d3032340f40cac8c0Chris Banes public boolean onOpenSubMenu(MenuBuilder subMenu) { 183200d183885b54de433e43118d3032340f40cac8c0Chris Banes if (subMenu == null && mHasActionBar) { 1833f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes Window.Callback cb = getWindowCallback(); 18349b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes if (cb != null && !isDestroyed()) { 1835d25af35061a9f20d59b25329d613c62c20184dadChris Banes cb.onMenuOpened(FEATURE_SUPPORT_ACTION_BAR, subMenu); 183600d183885b54de433e43118d3032340f40cac8c0Chris Banes } 183700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 183800d183885b54de433e43118d3032340f40cac8c0Chris Banes return true; 183903fc11b659da1645507062bddda450136e13af35Chris Banes } 184003fc11b659da1645507062bddda450136e13af35Chris Banes } 184103fc11b659da1645507062bddda450136e13af35Chris Banes 184203fc11b659da1645507062bddda450136e13af35Chris Banes private final class ActionMenuPresenterCallback implements MenuPresenter.Callback { 184303fc11b659da1645507062bddda450136e13af35Chris Banes @Override 184403fc11b659da1645507062bddda450136e13af35Chris Banes public boolean onOpenSubMenu(MenuBuilder subMenu) { 1845f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes Window.Callback cb = getWindowCallback(); 184600d183885b54de433e43118d3032340f40cac8c0Chris Banes if (cb != null) { 1847d25af35061a9f20d59b25329d613c62c20184dadChris Banes cb.onMenuOpened(FEATURE_SUPPORT_ACTION_BAR, subMenu); 184800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 184900d183885b54de433e43118d3032340f40cac8c0Chris Banes return true; 185003fc11b659da1645507062bddda450136e13af35Chris Banes } 185103fc11b659da1645507062bddda450136e13af35Chris Banes 185203fc11b659da1645507062bddda450136e13af35Chris Banes @Override 185303fc11b659da1645507062bddda450136e13af35Chris Banes public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 185400d183885b54de433e43118d3032340f40cac8c0Chris Banes checkCloseActionMenu(menu); 185500d183885b54de433e43118d3032340f40cac8c0Chris Banes } 185600d183885b54de433e43118d3032340f40cac8c0Chris Banes } 185700d183885b54de433e43118d3032340f40cac8c0Chris Banes 185885035fae2e7f292a529dc70e8d41cebc799e7d4fChris Banes protected static final class PanelFeatureState { 18599b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes 186000d183885b54de433e43118d3032340f40cac8c0Chris Banes /** Feature ID for this panel. */ 186100d183885b54de433e43118d3032340f40cac8c0Chris Banes int featureId; 186200d183885b54de433e43118d3032340f40cac8c0Chris Banes 186346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes int background; 186446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 186546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes int gravity; 186646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 186746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes int x; 186846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 186946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes int y; 187046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 187146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes int windowAnimations; 187246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 187300d183885b54de433e43118d3032340f40cac8c0Chris Banes /** Dynamic state of the panel. */ 187400d183885b54de433e43118d3032340f40cac8c0Chris Banes ViewGroup decorView; 187500d183885b54de433e43118d3032340f40cac8c0Chris Banes 187600d183885b54de433e43118d3032340f40cac8c0Chris Banes /** The panel that we are actually showing. */ 187700d183885b54de433e43118d3032340f40cac8c0Chris Banes View shownPanelView; 187800d183885b54de433e43118d3032340f40cac8c0Chris Banes 187946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes /** The panel that was returned by onCreatePanelView(). */ 188046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes View createdPanelView; 188146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 188200d183885b54de433e43118d3032340f40cac8c0Chris Banes /** Use {@link #setMenu} to set this. */ 188300d183885b54de433e43118d3032340f40cac8c0Chris Banes MenuBuilder menu; 188400d183885b54de433e43118d3032340f40cac8c0Chris Banes 188500d183885b54de433e43118d3032340f40cac8c0Chris Banes ListMenuPresenter listMenuPresenter; 188600d183885b54de433e43118d3032340f40cac8c0Chris Banes 188757c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes Context listPresenterContext; 188800d183885b54de433e43118d3032340f40cac8c0Chris Banes 188900d183885b54de433e43118d3032340f40cac8c0Chris Banes /** 189000d183885b54de433e43118d3032340f40cac8c0Chris Banes * Whether the panel has been prepared (see 18919b1b5bfac6abfda6c7543fc1b57050649b04f41bChris Banes * {@link #preparePanel}). 189200d183885b54de433e43118d3032340f40cac8c0Chris Banes */ 189300d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean isPrepared; 189400d183885b54de433e43118d3032340f40cac8c0Chris Banes 189500d183885b54de433e43118d3032340f40cac8c0Chris Banes /** 189600d183885b54de433e43118d3032340f40cac8c0Chris Banes * Whether an item's action has been performed. This happens in obvious 189700d183885b54de433e43118d3032340f40cac8c0Chris Banes * scenarios (user clicks on menu item), but can also happen with 189800d183885b54de433e43118d3032340f40cac8c0Chris Banes * chording menu+(shortcut key). 189900d183885b54de433e43118d3032340f40cac8c0Chris Banes */ 190000d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean isHandled; 190100d183885b54de433e43118d3032340f40cac8c0Chris Banes 190200d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean isOpen; 190300d183885b54de433e43118d3032340f40cac8c0Chris Banes 190400d183885b54de433e43118d3032340f40cac8c0Chris Banes public boolean qwertyMode; 190500d183885b54de433e43118d3032340f40cac8c0Chris Banes 190600d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean refreshDecorView; 190700d183885b54de433e43118d3032340f40cac8c0Chris Banes 190800d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean refreshMenuContent; 190900d183885b54de433e43118d3032340f40cac8c0Chris Banes 191000d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean wasLastOpen; 191100d183885b54de433e43118d3032340f40cac8c0Chris Banes 191200d183885b54de433e43118d3032340f40cac8c0Chris Banes /** 191300d183885b54de433e43118d3032340f40cac8c0Chris Banes * Contains the state of the menu when told to freeze. 191400d183885b54de433e43118d3032340f40cac8c0Chris Banes */ 191500d183885b54de433e43118d3032340f40cac8c0Chris Banes Bundle frozenMenuState; 191600d183885b54de433e43118d3032340f40cac8c0Chris Banes 191700d183885b54de433e43118d3032340f40cac8c0Chris Banes /** 191800d183885b54de433e43118d3032340f40cac8c0Chris Banes * Contains the state of associated action views when told to freeze. 191900d183885b54de433e43118d3032340f40cac8c0Chris Banes * These are saved across invalidations. 192000d183885b54de433e43118d3032340f40cac8c0Chris Banes */ 192100d183885b54de433e43118d3032340f40cac8c0Chris Banes Bundle frozenActionViewState; 192200d183885b54de433e43118d3032340f40cac8c0Chris Banes 192300d183885b54de433e43118d3032340f40cac8c0Chris Banes PanelFeatureState(int featureId) { 192400d183885b54de433e43118d3032340f40cac8c0Chris Banes this.featureId = featureId; 192500d183885b54de433e43118d3032340f40cac8c0Chris Banes 192600d183885b54de433e43118d3032340f40cac8c0Chris Banes refreshDecorView = false; 192700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 192800d183885b54de433e43118d3032340f40cac8c0Chris Banes 192900d183885b54de433e43118d3032340f40cac8c0Chris Banes public boolean hasPanelItems() { 193000d183885b54de433e43118d3032340f40cac8c0Chris Banes if (shownPanelView == null) return false; 193146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (createdPanelView != null) return true; 193200d183885b54de433e43118d3032340f40cac8c0Chris Banes 193300d183885b54de433e43118d3032340f40cac8c0Chris Banes return listMenuPresenter.getAdapter().getCount() > 0; 193400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 193500d183885b54de433e43118d3032340f40cac8c0Chris Banes 193600d183885b54de433e43118d3032340f40cac8c0Chris Banes /** 193700d183885b54de433e43118d3032340f40cac8c0Chris Banes * Unregister and free attached MenuPresenters. They will be recreated as needed. 193800d183885b54de433e43118d3032340f40cac8c0Chris Banes */ 193900d183885b54de433e43118d3032340f40cac8c0Chris Banes public void clearMenuPresenters() { 194000d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu != null) { 194100d183885b54de433e43118d3032340f40cac8c0Chris Banes menu.removeMenuPresenter(listMenuPresenter); 194200d183885b54de433e43118d3032340f40cac8c0Chris Banes } 194300d183885b54de433e43118d3032340f40cac8c0Chris Banes listMenuPresenter = null; 194400d183885b54de433e43118d3032340f40cac8c0Chris Banes } 194500d183885b54de433e43118d3032340f40cac8c0Chris Banes 194600d183885b54de433e43118d3032340f40cac8c0Chris Banes void setStyle(Context context) { 194757c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes final TypedValue outValue = new TypedValue(); 194857c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes final Resources.Theme widgetTheme = context.getResources().newTheme(); 194957c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes widgetTheme.setTo(context.getTheme()); 195057c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes 195157c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes // First apply the actionBarPopupTheme 195257c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes widgetTheme.resolveAttribute(R.attr.actionBarPopupTheme, outValue, true); 195357c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes if (outValue.resourceId != 0) { 195457c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes widgetTheme.applyStyle(outValue.resourceId, true); 195557c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes } 195657c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes 195757c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes // Now apply the panelMenuListTheme 195857c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes widgetTheme.resolveAttribute(R.attr.panelMenuListTheme, outValue, true); 195957c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes if (outValue.resourceId != 0) { 196057c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes widgetTheme.applyStyle(outValue.resourceId, true); 196157c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes } else { 196257c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes widgetTheme.applyStyle(R.style.Theme_AppCompat_CompactMenu, true); 196357c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes } 196457c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes 196557c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes context = new ContextThemeWrapper(context, 0); 196657c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes context.getTheme().setTo(widgetTheme); 196757c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes 196857c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes listPresenterContext = context; 196946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 1970a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes TypedArray a = context.obtainStyledAttributes(R.styleable.AppCompatTheme); 197146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes background = a.getResourceId( 1972a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes R.styleable.AppCompatTheme_panelBackground, 0); 197346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes windowAnimations = a.getResourceId( 1974a777694569b333a4459606db6bc94a9e80fd25f3Chris Banes R.styleable.AppCompatTheme_android_windowAnimationStyle, 0); 197546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes a.recycle(); 197600d183885b54de433e43118d3032340f40cac8c0Chris Banes } 197700d183885b54de433e43118d3032340f40cac8c0Chris Banes 197800d183885b54de433e43118d3032340f40cac8c0Chris Banes void setMenu(MenuBuilder menu) { 197900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu == this.menu) return; 198000d183885b54de433e43118d3032340f40cac8c0Chris Banes 198100d183885b54de433e43118d3032340f40cac8c0Chris Banes if (this.menu != null) { 198200d183885b54de433e43118d3032340f40cac8c0Chris Banes this.menu.removeMenuPresenter(listMenuPresenter); 198300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 198400d183885b54de433e43118d3032340f40cac8c0Chris Banes this.menu = menu; 198500d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu != null) { 198600d183885b54de433e43118d3032340f40cac8c0Chris Banes if (listMenuPresenter != null) menu.addMenuPresenter(listMenuPresenter); 198700d183885b54de433e43118d3032340f40cac8c0Chris Banes } 198800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 198900d183885b54de433e43118d3032340f40cac8c0Chris Banes 199057c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes MenuView getListMenuView(MenuPresenter.Callback cb) { 199100d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu == null) return null; 199200d183885b54de433e43118d3032340f40cac8c0Chris Banes 199300d183885b54de433e43118d3032340f40cac8c0Chris Banes if (listMenuPresenter == null) { 199457c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes listMenuPresenter = new ListMenuPresenter(listPresenterContext, 199557c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes R.layout.abc_list_menu_item_layout); 199600d183885b54de433e43118d3032340f40cac8c0Chris Banes listMenuPresenter.setCallback(cb); 199700d183885b54de433e43118d3032340f40cac8c0Chris Banes menu.addMenuPresenter(listMenuPresenter); 199800d183885b54de433e43118d3032340f40cac8c0Chris Banes } 199900d183885b54de433e43118d3032340f40cac8c0Chris Banes 200000d183885b54de433e43118d3032340f40cac8c0Chris Banes MenuView result = listMenuPresenter.getMenuView(decorView); 200100d183885b54de433e43118d3032340f40cac8c0Chris Banes 200200d183885b54de433e43118d3032340f40cac8c0Chris Banes return result; 200300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 200400d183885b54de433e43118d3032340f40cac8c0Chris Banes 200500d183885b54de433e43118d3032340f40cac8c0Chris Banes Parcelable onSaveInstanceState() { 200600d183885b54de433e43118d3032340f40cac8c0Chris Banes SavedState savedState = new SavedState(); 200700d183885b54de433e43118d3032340f40cac8c0Chris Banes savedState.featureId = featureId; 200800d183885b54de433e43118d3032340f40cac8c0Chris Banes savedState.isOpen = isOpen; 200900d183885b54de433e43118d3032340f40cac8c0Chris Banes 201000d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu != null) { 201100d183885b54de433e43118d3032340f40cac8c0Chris Banes savedState.menuState = new Bundle(); 201200d183885b54de433e43118d3032340f40cac8c0Chris Banes menu.savePresenterStates(savedState.menuState); 201300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 201400d183885b54de433e43118d3032340f40cac8c0Chris Banes 201500d183885b54de433e43118d3032340f40cac8c0Chris Banes return savedState; 201600d183885b54de433e43118d3032340f40cac8c0Chris Banes } 201700d183885b54de433e43118d3032340f40cac8c0Chris Banes 201800d183885b54de433e43118d3032340f40cac8c0Chris Banes void onRestoreInstanceState(Parcelable state) { 201900d183885b54de433e43118d3032340f40cac8c0Chris Banes SavedState savedState = (SavedState) state; 202000d183885b54de433e43118d3032340f40cac8c0Chris Banes featureId = savedState.featureId; 202100d183885b54de433e43118d3032340f40cac8c0Chris Banes wasLastOpen = savedState.isOpen; 202200d183885b54de433e43118d3032340f40cac8c0Chris Banes frozenMenuState = savedState.menuState; 202300d183885b54de433e43118d3032340f40cac8c0Chris Banes 202400d183885b54de433e43118d3032340f40cac8c0Chris Banes shownPanelView = null; 202500d183885b54de433e43118d3032340f40cac8c0Chris Banes decorView = null; 202600d183885b54de433e43118d3032340f40cac8c0Chris Banes } 202700d183885b54de433e43118d3032340f40cac8c0Chris Banes 202800d183885b54de433e43118d3032340f40cac8c0Chris Banes void applyFrozenState() { 202900d183885b54de433e43118d3032340f40cac8c0Chris Banes if (menu != null && frozenMenuState != null) { 203000d183885b54de433e43118d3032340f40cac8c0Chris Banes menu.restorePresenterStates(frozenMenuState); 203100d183885b54de433e43118d3032340f40cac8c0Chris Banes frozenMenuState = null; 203200d183885b54de433e43118d3032340f40cac8c0Chris Banes } 203300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 203400d183885b54de433e43118d3032340f40cac8c0Chris Banes 203500d183885b54de433e43118d3032340f40cac8c0Chris Banes private static class SavedState implements Parcelable { 203600d183885b54de433e43118d3032340f40cac8c0Chris Banes int featureId; 203700d183885b54de433e43118d3032340f40cac8c0Chris Banes boolean isOpen; 203800d183885b54de433e43118d3032340f40cac8c0Chris Banes Bundle menuState; 203900d183885b54de433e43118d3032340f40cac8c0Chris Banes 204000d183885b54de433e43118d3032340f40cac8c0Chris Banes public int describeContents() { 204100d183885b54de433e43118d3032340f40cac8c0Chris Banes return 0; 204200d183885b54de433e43118d3032340f40cac8c0Chris Banes } 204300d183885b54de433e43118d3032340f40cac8c0Chris Banes 204400d183885b54de433e43118d3032340f40cac8c0Chris Banes public void writeToParcel(Parcel dest, int flags) { 204500d183885b54de433e43118d3032340f40cac8c0Chris Banes dest.writeInt(featureId); 204600d183885b54de433e43118d3032340f40cac8c0Chris Banes dest.writeInt(isOpen ? 1 : 0); 204700d183885b54de433e43118d3032340f40cac8c0Chris Banes 204800d183885b54de433e43118d3032340f40cac8c0Chris Banes if (isOpen) { 204900d183885b54de433e43118d3032340f40cac8c0Chris Banes dest.writeBundle(menuState); 205000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 205100d183885b54de433e43118d3032340f40cac8c0Chris Banes } 205200d183885b54de433e43118d3032340f40cac8c0Chris Banes 205362ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes private static SavedState readFromParcel(Parcel source, ClassLoader loader) { 205400d183885b54de433e43118d3032340f40cac8c0Chris Banes SavedState savedState = new SavedState(); 205500d183885b54de433e43118d3032340f40cac8c0Chris Banes savedState.featureId = source.readInt(); 205600d183885b54de433e43118d3032340f40cac8c0Chris Banes savedState.isOpen = source.readInt() == 1; 205700d183885b54de433e43118d3032340f40cac8c0Chris Banes 205800d183885b54de433e43118d3032340f40cac8c0Chris Banes if (savedState.isOpen) { 205962ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes savedState.menuState = source.readBundle(loader); 206000d183885b54de433e43118d3032340f40cac8c0Chris Banes } 206100d183885b54de433e43118d3032340f40cac8c0Chris Banes 206200d183885b54de433e43118d3032340f40cac8c0Chris Banes return savedState; 206300d183885b54de433e43118d3032340f40cac8c0Chris Banes } 206400d183885b54de433e43118d3032340f40cac8c0Chris Banes 206500d183885b54de433e43118d3032340f40cac8c0Chris Banes public static final Parcelable.Creator<SavedState> CREATOR 206662ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes = ParcelableCompat.newCreator( 206762ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes new ParcelableCompatCreatorCallbacks<SavedState>() { 206862ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes @Override 206962ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes public SavedState createFromParcel(Parcel in, ClassLoader loader) { 207062ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes return readFromParcel(in, loader); 207162ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes } 207200d183885b54de433e43118d3032340f40cac8c0Chris Banes 207362ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes @Override 207462ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes public SavedState[] newArray(int size) { 207562ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes return new SavedState[size]; 207662ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes } 207762ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes }); 207803fc11b659da1645507062bddda450136e13af35Chris Banes } 207903fc11b659da1645507062bddda450136e13af35Chris Banes } 208003fc11b659da1645507062bddda450136e13af35Chris Banes 2081b034e4ad40bff78a848d9ed91754e3f9f3492f11Chris Banes private class ListMenuDecorView extends ContentFrameLayout { 208246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes public ListMenuDecorView(Context context) { 208346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes super(context); 208446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 208546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 208646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes @Override 208746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes public boolean dispatchKeyEvent(KeyEvent event) { 20881d0e76a0ba8bfc5e280203a56e10be95dd959a51Chris Banes return AppCompatDelegateImplV7.this.dispatchKeyEvent(event) 20891d0e76a0ba8bfc5e280203a56e10be95dd959a51Chris Banes || super.dispatchKeyEvent(event); 209046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 209146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 209246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes @Override 209346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes public boolean onInterceptTouchEvent(MotionEvent event) { 209446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes int action = event.getAction(); 209546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (action == MotionEvent.ACTION_DOWN) { 209646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes int x = (int) event.getX(); 209746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes int y = (int) event.getY(); 209846dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes if (isOutOfBounds(x, y)) { 209946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes closePanel(Window.FEATURE_OPTIONS_PANEL); 210046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return true; 210146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 210246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 210346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return super.onInterceptTouchEvent(event); 210446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 210546dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 210646dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes @Override 210746dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes public void setBackgroundResource(int resid) { 21087e4e8b664820f773bc96e37ee1d2bbf500d64e69Chris Banes setBackgroundDrawable(AppCompatDrawableManager.get().getDrawable(getContext(), resid)); 210946dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 211046dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes 211146dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes private boolean isOutOfBounds(int x, int y) { 211246dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes return x < -5 || y < -5 || x > (getWidth() + 5) || y > (getHeight() + 5); 211346dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 211446dfe0c53492ef0cb59873123ca141906fbb7dccChris Banes } 21156386aac7ea9be44d23dcea28d9a02110c174e988Chris Banes} 2116