1f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes/* 2f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes * Copyright (C) 2013 The Android Open Source Project 3f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes * 4f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes * Licensed under the Apache License, Version 2.0 (the "License"); 5f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes * you may not use this file except in compliance with the License. 6f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes * You may obtain a copy of the License at 7f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes * 8f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes * http://www.apache.org/licenses/LICENSE-2.0 9f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes * 10f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes * Unless required by applicable law or agreed to in writing, software 11f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes * distributed under the License is distributed on an "AS IS" BASIS, 12f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes * See the License for the specific language governing permissions and 14f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes * limitations under the License. 15f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes */ 16f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 17f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banespackage android.support.v7.app; 18f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 19f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.app.Activity; 20f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.content.Context; 2119ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banesimport android.content.res.Resources; 22f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.graphics.drawable.Drawable; 2319ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banesimport android.os.Build; 24ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banesimport android.os.Bundle; 258f886fe8c7e23fe6ccb8734167c960c2ed3429c3Alan Viveretteimport android.support.annotation.RequiresApi; 26f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.support.v7.appcompat.R; 27f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.support.v7.view.ActionMode; 2866698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v7.view.SupportMenuInflater; 2966698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v7.view.WindowCallbackWrapper; 3066698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v7.view.menu.MenuBuilder; 3166698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v7.widget.TintTypedArray; 32f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.view.KeyEvent; 33f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.view.Menu; 34f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.view.MenuInflater; 35f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.view.View; 36f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.view.Window; 37f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 38d38b36c6370fe2aa448b7b824e8fb399fb3f0b97Alan Viverette@RequiresApi(14) 39f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesabstract class AppCompatDelegateImplBase extends AppCompatDelegate { 40f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 4112acd8f6d6926aaa5cc16543386e0aeee64716edChris Banes static final boolean DEBUG = false; 4212acd8f6d6926aaa5cc16543386e0aeee64716edChris Banes 4319ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes private static boolean sInstalledExceptionHandler; 4419ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes private static final boolean SHOULD_INSTALL_EXCEPTION_HANDLER = Build.VERSION.SDK_INT < 21; 4519ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes 462c1bad7ecd5879bf0f29ce2ce1bc5bd67a3f4682Aurimas Liutikas static final String EXCEPTION_HANDLER_MESSAGE_SUFFIX= ". If the resource you are" 4719ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes + " trying to use is a vector resource, you may be referencing it in an unsupported" 4819ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes + " way. See AppCompatDelegate.setCompatVectorFromResourcesEnabled() for more info."; 4919ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes 5019ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes static { 5119ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes if (SHOULD_INSTALL_EXCEPTION_HANDLER && !sInstalledExceptionHandler) { 5219ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes final Thread.UncaughtExceptionHandler defHandler 5319ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes = Thread.getDefaultUncaughtExceptionHandler(); 5419ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes 5519ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 5619ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes @Override 5719ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes public void uncaughtException(Thread thread, final Throwable thowable) { 5819ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes if (shouldWrapException(thowable)) { 5919ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes // Now wrap the throwable, but append some extra information to the message 6019ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes final Throwable wrapped = new Resources.NotFoundException( 6119ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes thowable.getMessage() + EXCEPTION_HANDLER_MESSAGE_SUFFIX); 6219ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes wrapped.initCause(thowable.getCause()); 6319ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes wrapped.setStackTrace(thowable.getStackTrace()); 6419ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes defHandler.uncaughtException(thread, wrapped); 6519ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes } else { 6619ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes defHandler.uncaughtException(thread, thowable); 6719ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes } 6819ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes } 6919ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes 7019ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes private boolean shouldWrapException(Throwable throwable) { 7119ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes if (throwable instanceof Resources.NotFoundException) { 7219ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes final String message = throwable.getMessage(); 7319ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes return message != null && (message.contains("drawable") 7419ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes || message.contains("Drawable")); 7519ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes } 7619ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes return false; 7719ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes } 7819ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes }); 7919ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes 8019ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes sInstalledExceptionHandler = true; 8119ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes } 8219ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes } 8319ef8b22fccfd1649ac27cec9fe74933265f5745Chris Banes 84593d8bcc82c01a559f737dfcbc6e806005300a64Chris Banes private static final int[] sWindowBackgroundStyleable = {android.R.attr.windowBackground}; 85593d8bcc82c01a559f737dfcbc6e806005300a64Chris Banes 8616e8d4dd91083260223c007c797e46bc8f631055Chris Banes final Context mContext; 8716e8d4dd91083260223c007c797e46bc8f631055Chris Banes final Window mWindow; 8816e8d4dd91083260223c007c797e46bc8f631055Chris Banes final Window.Callback mOriginalWindowCallback; 898d4765883ff24f0f79bf64fea23d4687d50cec85Chris Banes final Window.Callback mAppCompatWindowCallback; 9016e8d4dd91083260223c007c797e46bc8f631055Chris Banes final AppCompatCallback mAppCompatCallback; 91f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 928122ad54f129c2214631fad86cabda82815cc0d8Chris Banes ActionBar mActionBar; 935ecdb2c5042da49d36d7cda3fa08f1d9151a1fbdChris Banes MenuInflater mMenuInflater; 94f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 95f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes // true if this activity has an action bar. 96f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes boolean mHasActionBar; 97f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes // true if this activity's action bar overlays other activity content. 98f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes boolean mOverlayActionBar; 99f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes // true if this any action modes should overlay the activity content 100f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes boolean mOverlayActionMode; 101f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes // true if this activity is floating (e.g. Dialog) 102f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes boolean mIsFloating; 1030f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes // true if this activity has no title 1040f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes boolean mWindowNoTitle; 105f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 10616e8d4dd91083260223c007c797e46bc8f631055Chris Banes private CharSequence mTitle; 10716e8d4dd91083260223c007c797e46bc8f631055Chris Banes 10812acd8f6d6926aaa5cc16543386e0aeee64716edChris Banes private boolean mIsStarted; 109f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes private boolean mIsDestroyed; 1108a6d3a17d966d841ff7a02521ca2783d896d696dEvan Rosky private boolean mEatKeyUpEvent; 111f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 11216e8d4dd91083260223c007c797e46bc8f631055Chris Banes AppCompatDelegateImplBase(Context context, Window window, AppCompatCallback callback) { 11316e8d4dd91083260223c007c797e46bc8f631055Chris Banes mContext = context; 11416e8d4dd91083260223c007c797e46bc8f631055Chris Banes mWindow = window; 115f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes mAppCompatCallback = callback; 11616e8d4dd91083260223c007c797e46bc8f631055Chris Banes 11716e8d4dd91083260223c007c797e46bc8f631055Chris Banes mOriginalWindowCallback = mWindow.getCallback(); 118547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes if (mOriginalWindowCallback instanceof AppCompatWindowCallbackBase) { 11916e8d4dd91083260223c007c797e46bc8f631055Chris Banes throw new IllegalStateException( 12016e8d4dd91083260223c007c797e46bc8f631055Chris Banes "AppCompat has already installed itself into the Window"); 12116e8d4dd91083260223c007c797e46bc8f631055Chris Banes } 1228d4765883ff24f0f79bf64fea23d4687d50cec85Chris Banes mAppCompatWindowCallback = wrapWindowCallback(mOriginalWindowCallback); 12316e8d4dd91083260223c007c797e46bc8f631055Chris Banes // Now install the new callback 1248d4765883ff24f0f79bf64fea23d4687d50cec85Chris Banes mWindow.setCallback(mAppCompatWindowCallback); 125593d8bcc82c01a559f737dfcbc6e806005300a64Chris Banes 126593d8bcc82c01a559f737dfcbc6e806005300a64Chris Banes final TintTypedArray a = TintTypedArray.obtainStyledAttributes( 127593d8bcc82c01a559f737dfcbc6e806005300a64Chris Banes context, null, sWindowBackgroundStyleable); 128593d8bcc82c01a559f737dfcbc6e806005300a64Chris Banes final Drawable winBg = a.getDrawableIfKnown(0); 129593d8bcc82c01a559f737dfcbc6e806005300a64Chris Banes if (winBg != null) { 130593d8bcc82c01a559f737dfcbc6e806005300a64Chris Banes mWindow.setBackgroundDrawable(winBg); 131593d8bcc82c01a559f737dfcbc6e806005300a64Chris Banes } 132593d8bcc82c01a559f737dfcbc6e806005300a64Chris Banes a.recycle(); 133f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 134f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 1358122ad54f129c2214631fad86cabda82815cc0d8Chris Banes abstract void initWindowDecorActionBar(); 136f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 137547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes Window.Callback wrapWindowCallback(Window.Callback callback) { 138547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes return new AppCompatWindowCallbackBase(callback); 139547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } 140547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes 141f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes @Override 142f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public ActionBar getSupportActionBar() { 143f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes // The Action Bar should be lazily created as hasActionBar 144f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes // could change after onCreate 1458122ad54f129c2214631fad86cabda82815cc0d8Chris Banes initWindowDecorActionBar(); 146f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes return mActionBar; 147f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 148f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 149f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes final ActionBar peekSupportActionBar() { 150f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes return mActionBar; 151f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 152f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 153f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes @Override 154f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public MenuInflater getMenuInflater() { 1555ecdb2c5042da49d36d7cda3fa08f1d9151a1fbdChris Banes // Make sure that action views can get an appropriate theme. 156f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes if (mMenuInflater == null) { 1575ecdb2c5042da49d36d7cda3fa08f1d9151a1fbdChris Banes initWindowDecorActionBar(); 1585ecdb2c5042da49d36d7cda3fa08f1d9151a1fbdChris Banes mMenuInflater = new SupportMenuInflater( 1595ecdb2c5042da49d36d7cda3fa08f1d9151a1fbdChris Banes mActionBar != null ? mActionBar.getThemedContext() : mContext); 160f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 161f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes return mMenuInflater; 162f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 163f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 164f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes // Methods used to create and respond to options menu 165d25af35061a9f20d59b25329d613c62c20184dadChris Banes abstract void onPanelClosed(int featureId, Menu menu); 166f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 167f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes abstract boolean onMenuOpened(int featureId, Menu menu); 168f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 169f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes abstract boolean dispatchKeyEvent(KeyEvent event); 170f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 171f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes abstract boolean onKeyShortcut(int keyCode, KeyEvent event); 172f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 173f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes @Override 174ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes public void setLocalNightMode(@NightMode int mode) { 175ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes // no-op 176ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes } 177ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes 178ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes @Override 179f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public final ActionBarDrawerToggle.Delegate getDrawerToggleDelegate() { 180f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes return new ActionBarDrawableToggleImpl(); 181f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 182f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 183f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes final Context getActionBarThemedContext() { 184f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes Context context = null; 185f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 186f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes // If we have an action bar, let it return a themed context 187f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes ActionBar ab = getSupportActionBar(); 188f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes if (ab != null) { 189f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes context = ab.getThemedContext(); 190f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 191f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 192f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes if (context == null) { 19316e8d4dd91083260223c007c797e46bc8f631055Chris Banes context = mContext; 194f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 195f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes return context; 196f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 197f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 198f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes private class ActionBarDrawableToggleImpl implements ActionBarDrawerToggle.Delegate { 1992c1bad7ecd5879bf0f29ce2ce1bc5bd67a3f4682Aurimas Liutikas ActionBarDrawableToggleImpl() { 2002c1bad7ecd5879bf0f29ce2ce1bc5bd67a3f4682Aurimas Liutikas } 2012c1bad7ecd5879bf0f29ce2ce1bc5bd67a3f4682Aurimas Liutikas 202f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes @Override 203f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public Drawable getThemeUpIndicator() { 204f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes final TintTypedArray a = TintTypedArray.obtainStyledAttributes( 205f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes getActionBarThemedContext(), null, new int[]{ R.attr.homeAsUpIndicator }); 206f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes final Drawable result = a.getDrawable(0); 207f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes a.recycle(); 208f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes return result; 209f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 210f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 211f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes @Override 212f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public Context getActionBarThemedContext() { 213f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes return AppCompatDelegateImplBase.this.getActionBarThemedContext(); 214f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 215f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 216f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes @Override 217f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public boolean isNavigationVisible() { 218f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes final ActionBar ab = getSupportActionBar(); 219f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes return ab != null && (ab.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0; 220f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 221f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 222f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes @Override 223f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public void setActionBarUpIndicator(Drawable upDrawable, int contentDescRes) { 224f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes ActionBar ab = getSupportActionBar(); 225f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes if (ab != null) { 226f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes ab.setHomeAsUpIndicator(upDrawable); 227f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes ab.setHomeActionContentDescription(contentDescRes); 228f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 229f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 230f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 231f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes @Override 232f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public void setActionBarDescription(int contentDescRes) { 233f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes ActionBar ab = getSupportActionBar(); 234f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes if (ab != null) { 235f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes ab.setHomeActionContentDescription(contentDescRes); 236f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 237f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 238f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 239f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 240f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes abstract ActionMode startSupportActionModeFromWindow(ActionMode.Callback callback); 241f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 242f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes @Override 24312acd8f6d6926aaa5cc16543386e0aeee64716edChris Banes public void onStart() { 24412acd8f6d6926aaa5cc16543386e0aeee64716edChris Banes mIsStarted = true; 24512acd8f6d6926aaa5cc16543386e0aeee64716edChris Banes } 24612acd8f6d6926aaa5cc16543386e0aeee64716edChris Banes 24712acd8f6d6926aaa5cc16543386e0aeee64716edChris Banes @Override 24812acd8f6d6926aaa5cc16543386e0aeee64716edChris Banes public void onStop() { 24912acd8f6d6926aaa5cc16543386e0aeee64716edChris Banes mIsStarted = false; 25012acd8f6d6926aaa5cc16543386e0aeee64716edChris Banes } 25112acd8f6d6926aaa5cc16543386e0aeee64716edChris Banes 25212acd8f6d6926aaa5cc16543386e0aeee64716edChris Banes @Override 253733d0b2acb07ede7455b9d020901a10586053923Chris Banes public void onDestroy() { 254f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes mIsDestroyed = true; 255f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 256f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 257547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes @Override 258547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes public void setHandleNativeActionModesEnabled(boolean enabled) { 259547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes // no-op pre-v14 260547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } 261547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes 262547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes @Override 263547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes public boolean isHandleNativeActionModesEnabled() { 264547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes // Always false pre-v14 265547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes return false; 266547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes } 267547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes 268ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes @Override 269ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes public boolean applyDayNight() { 270ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes // no-op on v7 271ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes return false; 272ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes } 273ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes 274f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes final boolean isDestroyed() { 275f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes return mIsDestroyed; 276f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 277f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 27812acd8f6d6926aaa5cc16543386e0aeee64716edChris Banes final boolean isStarted() { 27912acd8f6d6926aaa5cc16543386e0aeee64716edChris Banes return mIsStarted; 28012acd8f6d6926aaa5cc16543386e0aeee64716edChris Banes } 28112acd8f6d6926aaa5cc16543386e0aeee64716edChris Banes 282f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes final Window.Callback getWindowCallback() { 28316e8d4dd91083260223c007c797e46bc8f631055Chris Banes return mWindow.getCallback(); 284f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 285f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 28616e8d4dd91083260223c007c797e46bc8f631055Chris Banes @Override 28716e8d4dd91083260223c007c797e46bc8f631055Chris Banes public final void setTitle(CharSequence title) { 28816e8d4dd91083260223c007c797e46bc8f631055Chris Banes mTitle = title; 28916e8d4dd91083260223c007c797e46bc8f631055Chris Banes onTitleChanged(title); 29016e8d4dd91083260223c007c797e46bc8f631055Chris Banes } 291f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 292ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes @Override 293ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes public void onSaveInstanceState(Bundle outState) { 294ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes // no-op 295ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes } 296ff7f258a9b0781de5c6325358c7075128bf05a91Chris Banes 29716e8d4dd91083260223c007c797e46bc8f631055Chris Banes abstract void onTitleChanged(CharSequence title); 298f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 29916e8d4dd91083260223c007c797e46bc8f631055Chris Banes final CharSequence getTitle() { 30044ece5ceaaee232f9139ccbde40ac4a5e642bdeeChristophe Beyls // If the original window callback is an Activity, we'll use its title 30116e8d4dd91083260223c007c797e46bc8f631055Chris Banes if (mOriginalWindowCallback instanceof Activity) { 30216e8d4dd91083260223c007c797e46bc8f631055Chris Banes return ((Activity) mOriginalWindowCallback).getTitle(); 30316e8d4dd91083260223c007c797e46bc8f631055Chris Banes } 30416e8d4dd91083260223c007c797e46bc8f631055Chris Banes // Else, we'll return the title we have recorded ourselves 30516e8d4dd91083260223c007c797e46bc8f631055Chris Banes return mTitle; 306f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 307f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 308547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes class AppCompatWindowCallbackBase extends WindowCallbackWrapper { 309547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes AppCompatWindowCallbackBase(Window.Callback callback) { 310f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes super(callback); 311f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 312f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 313f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes @Override 314f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public boolean dispatchKeyEvent(KeyEvent event) { 315559fa14454cc053127b3b96c0e63c48c06937e38Chris Banes return AppCompatDelegateImplBase.this.dispatchKeyEvent(event) 316559fa14454cc053127b3b96c0e63c48c06937e38Chris Banes || super.dispatchKeyEvent(event); 317d25af35061a9f20d59b25329d613c62c20184dadChris Banes } 318d25af35061a9f20d59b25329d613c62c20184dadChris Banes 319d25af35061a9f20d59b25329d613c62c20184dadChris Banes @Override 320d25af35061a9f20d59b25329d613c62c20184dadChris Banes public boolean dispatchKeyShortcutEvent(KeyEvent event) { 321d25af35061a9f20d59b25329d613c62c20184dadChris Banes return super.dispatchKeyShortcutEvent(event) 322d25af35061a9f20d59b25329d613c62c20184dadChris Banes || AppCompatDelegateImplBase.this.onKeyShortcut(event.getKeyCode(), event); 323f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 324f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 325f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes @Override 326f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public boolean onCreatePanelMenu(int featureId, Menu menu) { 327f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes if (featureId == Window.FEATURE_OPTIONS_PANEL && !(menu instanceof MenuBuilder)) { 328f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes // If this is an options menu but it's not an AppCompat menu, we eat the event 329f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes // and return false 330f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes return false; 331f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 332f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes return super.onCreatePanelMenu(featureId, menu); 333f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 334f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 335f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes @Override 336d25af35061a9f20d59b25329d613c62c20184dadChris Banes public void onContentChanged() { 337d25af35061a9f20d59b25329d613c62c20184dadChris Banes // We purposely do not propagate this call as this is called when we install 338d25af35061a9f20d59b25329d613c62c20184dadChris Banes // our sub-decor rather than the user's content 339d25af35061a9f20d59b25329d613c62c20184dadChris Banes } 340d25af35061a9f20d59b25329d613c62c20184dadChris Banes 341d25af35061a9f20d59b25329d613c62c20184dadChris Banes @Override 342f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public boolean onPreparePanel(int featureId, View view, Menu menu) { 3434e411251159c965caccb3bf3727c2921d74f06c1Chris Banes final MenuBuilder mb = menu instanceof MenuBuilder ? (MenuBuilder) menu : null; 3444e411251159c965caccb3bf3727c2921d74f06c1Chris Banes 3454e411251159c965caccb3bf3727c2921d74f06c1Chris Banes if (featureId == Window.FEATURE_OPTIONS_PANEL && mb == null) { 346f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes // If this is an options menu but it's not an AppCompat menu, we eat the event 347f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes // and return false 348f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes return false; 349f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 350f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 3514e411251159c965caccb3bf3727c2921d74f06c1Chris Banes // On ICS and below devices, onPreparePanel calls menu.hasVisibleItems() to determine 3524e411251159c965caccb3bf3727c2921d74f06c1Chris Banes // if a panel is prepared. This interferes with any initially invisible items, which 3534e411251159c965caccb3bf3727c2921d74f06c1Chris Banes // are later made visible. We workaround it by making hasVisibleItems() always 3544e411251159c965caccb3bf3727c2921d74f06c1Chris Banes // return true during the onPreparePanel call. 3554e411251159c965caccb3bf3727c2921d74f06c1Chris Banes if (mb != null) { 3564e411251159c965caccb3bf3727c2921d74f06c1Chris Banes mb.setOverrideVisibleItems(true); 3574e411251159c965caccb3bf3727c2921d74f06c1Chris Banes } 3584e411251159c965caccb3bf3727c2921d74f06c1Chris Banes 3594e411251159c965caccb3bf3727c2921d74f06c1Chris Banes final boolean handled = super.onPreparePanel(featureId, view, menu); 3604e411251159c965caccb3bf3727c2921d74f06c1Chris Banes 3614e411251159c965caccb3bf3727c2921d74f06c1Chris Banes if (mb != null) { 3624e411251159c965caccb3bf3727c2921d74f06c1Chris Banes mb.setOverrideVisibleItems(false); 363f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 364f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 3654e411251159c965caccb3bf3727c2921d74f06c1Chris Banes return handled; 366f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 367f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 368f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes @Override 369f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public boolean onMenuOpened(int featureId, Menu menu) { 370ef45ec823d39029e03ff29eb618eaa5a78839470Chris Banes super.onMenuOpened(featureId, menu); 371ef45ec823d39029e03ff29eb618eaa5a78839470Chris Banes AppCompatDelegateImplBase.this.onMenuOpened(featureId, menu); 372ef45ec823d39029e03ff29eb618eaa5a78839470Chris Banes return true; 373f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 374f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes 375f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes @Override 376f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes public void onPanelClosed(int featureId, Menu menu) { 377f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes super.onPanelClosed(featureId, menu); 378d25af35061a9f20d59b25329d613c62c20184dadChris Banes AppCompatDelegateImplBase.this.onPanelClosed(featureId, menu); 379f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 380f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes } 381f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes} 382