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;
21f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.content.res.TypedArray;
22f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.graphics.drawable.Drawable;
23f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.os.Bundle;
24f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.support.v7.appcompat.R;
25f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.support.v7.internal.view.SupportMenuInflater;
26f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.support.v7.internal.view.WindowCallbackWrapper;
27f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.support.v7.internal.view.menu.MenuBuilder;
28f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.support.v7.internal.widget.TintTypedArray;
29f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.support.v7.view.ActionMode;
30f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.view.KeyEvent;
31f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.view.Menu;
32f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.view.MenuInflater;
33f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.view.View;
34f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesimport android.view.Window;
35f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
36f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banesabstract class AppCompatDelegateImplBase extends AppCompatDelegate {
37f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
3816e8d4dd91083260223c007c797e46bc8f631055Chris Banes    final Context mContext;
3916e8d4dd91083260223c007c797e46bc8f631055Chris Banes    final Window mWindow;
4016e8d4dd91083260223c007c797e46bc8f631055Chris Banes    final Window.Callback mOriginalWindowCallback;
418d4765883ff24f0f79bf64fea23d4687d50cec85Chris Banes    final Window.Callback mAppCompatWindowCallback;
4216e8d4dd91083260223c007c797e46bc8f631055Chris Banes    final AppCompatCallback mAppCompatCallback;
43f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
448122ad54f129c2214631fad86cabda82815cc0d8Chris Banes    ActionBar mActionBar;
455ecdb2c5042da49d36d7cda3fa08f1d9151a1fbdChris Banes    MenuInflater mMenuInflater;
46f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
47f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    // true if this activity has an action bar.
48f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    boolean mHasActionBar;
49f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    // true if this activity's action bar overlays other activity content.
50f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    boolean mOverlayActionBar;
51f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    // true if this any action modes should overlay the activity content
52f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    boolean mOverlayActionMode;
53f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    // true if this activity is floating (e.g. Dialog)
54f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    boolean mIsFloating;
550f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes    // true if this activity has no title
560f58401dc72db8ea2a201e3c0220f6529f2a7b33Chris Banes    boolean mWindowNoTitle;
57f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
5816e8d4dd91083260223c007c797e46bc8f631055Chris Banes    private CharSequence mTitle;
5916e8d4dd91083260223c007c797e46bc8f631055Chris Banes
60f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    private boolean mIsDestroyed;
61f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
6216e8d4dd91083260223c007c797e46bc8f631055Chris Banes    AppCompatDelegateImplBase(Context context, Window window, AppCompatCallback callback) {
6316e8d4dd91083260223c007c797e46bc8f631055Chris Banes        mContext = context;
6416e8d4dd91083260223c007c797e46bc8f631055Chris Banes        mWindow = window;
65f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        mAppCompatCallback = callback;
6616e8d4dd91083260223c007c797e46bc8f631055Chris Banes
6716e8d4dd91083260223c007c797e46bc8f631055Chris Banes        mOriginalWindowCallback = mWindow.getCallback();
68547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes        if (mOriginalWindowCallback instanceof AppCompatWindowCallbackBase) {
6916e8d4dd91083260223c007c797e46bc8f631055Chris Banes            throw new IllegalStateException(
7016e8d4dd91083260223c007c797e46bc8f631055Chris Banes                    "AppCompat has already installed itself into the Window");
7116e8d4dd91083260223c007c797e46bc8f631055Chris Banes        }
728d4765883ff24f0f79bf64fea23d4687d50cec85Chris Banes        mAppCompatWindowCallback = wrapWindowCallback(mOriginalWindowCallback);
7316e8d4dd91083260223c007c797e46bc8f631055Chris Banes        // Now install the new callback
748d4765883ff24f0f79bf64fea23d4687d50cec85Chris Banes        mWindow.setCallback(mAppCompatWindowCallback);
75f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    }
76f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
778122ad54f129c2214631fad86cabda82815cc0d8Chris Banes    abstract void initWindowDecorActionBar();
78f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
79547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes    Window.Callback wrapWindowCallback(Window.Callback callback) {
80547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes        return new AppCompatWindowCallbackBase(callback);
81547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes    }
82547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes
83f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    @Override
84f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    public ActionBar getSupportActionBar() {
85f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        // The Action Bar should be lazily created as hasActionBar
86f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        // could change after onCreate
878122ad54f129c2214631fad86cabda82815cc0d8Chris Banes        initWindowDecorActionBar();
88f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        return mActionBar;
89f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    }
90f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
91f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    final ActionBar peekSupportActionBar() {
92f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        return mActionBar;
93f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    }
94f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
95f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    @Override
96f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    public MenuInflater getMenuInflater() {
975ecdb2c5042da49d36d7cda3fa08f1d9151a1fbdChris Banes        // Make sure that action views can get an appropriate theme.
98f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        if (mMenuInflater == null) {
995ecdb2c5042da49d36d7cda3fa08f1d9151a1fbdChris Banes            initWindowDecorActionBar();
1005ecdb2c5042da49d36d7cda3fa08f1d9151a1fbdChris Banes            mMenuInflater = new SupportMenuInflater(
1015ecdb2c5042da49d36d7cda3fa08f1d9151a1fbdChris Banes                    mActionBar != null ? mActionBar.getThemedContext() : mContext);
102f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        }
103f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        return mMenuInflater;
104f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    }
105f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
106f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    // Methods used to create and respond to options menu
107d25af35061a9f20d59b25329d613c62c20184dadChris Banes    abstract void onPanelClosed(int featureId, Menu menu);
108f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
109f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    abstract boolean onMenuOpened(int featureId, Menu menu);
110f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
111f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    abstract boolean dispatchKeyEvent(KeyEvent event);
112f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
113f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    abstract boolean onKeyShortcut(int keyCode, KeyEvent event);
114f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
115f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    @Override
116f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    public final ActionBarDrawerToggle.Delegate getDrawerToggleDelegate() {
117f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        return new ActionBarDrawableToggleImpl();
118f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    }
119f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
120f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    final Context getActionBarThemedContext() {
121f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        Context context = null;
122f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
123f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        // If we have an action bar, let it return a themed context
124f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        ActionBar ab = getSupportActionBar();
125f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        if (ab != null) {
126f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            context = ab.getThemedContext();
127f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        }
128f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
129f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        if (context == null) {
13016e8d4dd91083260223c007c797e46bc8f631055Chris Banes            context = mContext;
131f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        }
132f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        return context;
133f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    }
134f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
135f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    private class ActionBarDrawableToggleImpl implements ActionBarDrawerToggle.Delegate {
136f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        @Override
137f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        public Drawable getThemeUpIndicator() {
138f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            final TintTypedArray a = TintTypedArray.obtainStyledAttributes(
139f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes                    getActionBarThemedContext(), null, new int[]{ R.attr.homeAsUpIndicator });
140f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            final Drawable result = a.getDrawable(0);
141f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            a.recycle();
142f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            return result;
143f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        }
144f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
145f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        @Override
146f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        public Context getActionBarThemedContext() {
147f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            return AppCompatDelegateImplBase.this.getActionBarThemedContext();
148f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        }
149f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
150f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        @Override
151f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        public boolean isNavigationVisible() {
152f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            final ActionBar ab = getSupportActionBar();
153f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            return ab != null && (ab.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0;
154f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        }
155f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
156f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        @Override
157f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        public void setActionBarUpIndicator(Drawable upDrawable, int contentDescRes) {
158f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            ActionBar ab = getSupportActionBar();
159f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            if (ab != null) {
160f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes                ab.setHomeAsUpIndicator(upDrawable);
161f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes                ab.setHomeActionContentDescription(contentDescRes);
162f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            }
163f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        }
164f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
165f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        @Override
166f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        public void setActionBarDescription(int contentDescRes) {
167f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            ActionBar ab = getSupportActionBar();
168f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            if (ab != null) {
169f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes                ab.setHomeActionContentDescription(contentDescRes);
170f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            }
171f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        }
172f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    }
173f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
174f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    abstract ActionMode startSupportActionModeFromWindow(ActionMode.Callback callback);
175f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
176f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    @Override
177f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    public final void onDestroy() {
178f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        mIsDestroyed = true;
179f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    }
180f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
181547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes    @Override
182547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes    public void setHandleNativeActionModesEnabled(boolean enabled) {
183547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes        // no-op pre-v14
184547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes    }
185547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes
186547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes    @Override
187547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes    public boolean isHandleNativeActionModesEnabled() {
188547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes        // Always false pre-v14
189547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes        return false;
190547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes    }
191547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes
192f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    final boolean isDestroyed() {
193f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        return mIsDestroyed;
194f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    }
195f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
196f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    final Window.Callback getWindowCallback() {
19716e8d4dd91083260223c007c797e46bc8f631055Chris Banes        return mWindow.getCallback();
198f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    }
199f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
20016e8d4dd91083260223c007c797e46bc8f631055Chris Banes    @Override
20116e8d4dd91083260223c007c797e46bc8f631055Chris Banes    public final void setTitle(CharSequence title) {
20216e8d4dd91083260223c007c797e46bc8f631055Chris Banes        mTitle = title;
20316e8d4dd91083260223c007c797e46bc8f631055Chris Banes        onTitleChanged(title);
20416e8d4dd91083260223c007c797e46bc8f631055Chris Banes    }
205f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
20616e8d4dd91083260223c007c797e46bc8f631055Chris Banes    abstract void onTitleChanged(CharSequence title);
207f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
20816e8d4dd91083260223c007c797e46bc8f631055Chris Banes    final CharSequence getTitle() {
20916e8d4dd91083260223c007c797e46bc8f631055Chris Banes        // If the original window callback is an Activity, we'll use it's title
21016e8d4dd91083260223c007c797e46bc8f631055Chris Banes        if (mOriginalWindowCallback instanceof Activity) {
21116e8d4dd91083260223c007c797e46bc8f631055Chris Banes            return ((Activity) mOriginalWindowCallback).getTitle();
21216e8d4dd91083260223c007c797e46bc8f631055Chris Banes        }
21316e8d4dd91083260223c007c797e46bc8f631055Chris Banes        // Else, we'll return the title we have recorded ourselves
21416e8d4dd91083260223c007c797e46bc8f631055Chris Banes        return mTitle;
215f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    }
216f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
217547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes    class AppCompatWindowCallbackBase extends WindowCallbackWrapper {
218547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes        AppCompatWindowCallbackBase(Window.Callback callback) {
219f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            super(callback);
220f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        }
221f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
222f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        @Override
223f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        public boolean dispatchKeyEvent(KeyEvent event) {
224559fa14454cc053127b3b96c0e63c48c06937e38Chris Banes            return AppCompatDelegateImplBase.this.dispatchKeyEvent(event)
225559fa14454cc053127b3b96c0e63c48c06937e38Chris Banes                    || super.dispatchKeyEvent(event);
226d25af35061a9f20d59b25329d613c62c20184dadChris Banes        }
227d25af35061a9f20d59b25329d613c62c20184dadChris Banes
228d25af35061a9f20d59b25329d613c62c20184dadChris Banes        @Override
229d25af35061a9f20d59b25329d613c62c20184dadChris Banes        public boolean dispatchKeyShortcutEvent(KeyEvent event) {
230d25af35061a9f20d59b25329d613c62c20184dadChris Banes            return super.dispatchKeyShortcutEvent(event)
231d25af35061a9f20d59b25329d613c62c20184dadChris Banes                    || AppCompatDelegateImplBase.this.onKeyShortcut(event.getKeyCode(), event);
232f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        }
233f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
234f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        @Override
235f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        public boolean onCreatePanelMenu(int featureId, Menu menu) {
236f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            if (featureId == Window.FEATURE_OPTIONS_PANEL && !(menu instanceof MenuBuilder)) {
237f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes                // If this is an options menu but it's not an AppCompat menu, we eat the event
238f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes                // and return false
239f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes                return false;
240f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            }
241f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            return super.onCreatePanelMenu(featureId, menu);
242f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        }
243f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
244f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        @Override
245d25af35061a9f20d59b25329d613c62c20184dadChris Banes        public void onContentChanged() {
246d25af35061a9f20d59b25329d613c62c20184dadChris Banes            // We purposely do not propagate this call as this is called when we install
247d25af35061a9f20d59b25329d613c62c20184dadChris Banes            // our sub-decor rather than the user's content
248d25af35061a9f20d59b25329d613c62c20184dadChris Banes        }
249d25af35061a9f20d59b25329d613c62c20184dadChris Banes
250d25af35061a9f20d59b25329d613c62c20184dadChris Banes        @Override
251f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        public boolean onPreparePanel(int featureId, View view, Menu menu) {
2524e411251159c965caccb3bf3727c2921d74f06c1Chris Banes            final MenuBuilder mb = menu instanceof MenuBuilder ? (MenuBuilder) menu : null;
2534e411251159c965caccb3bf3727c2921d74f06c1Chris Banes
2544e411251159c965caccb3bf3727c2921d74f06c1Chris Banes            if (featureId == Window.FEATURE_OPTIONS_PANEL && mb == null) {
255f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes                // If this is an options menu but it's not an AppCompat menu, we eat the event
256f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes                // and return false
257f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes                return false;
258f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            }
259f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
2604e411251159c965caccb3bf3727c2921d74f06c1Chris Banes            // On ICS and below devices, onPreparePanel calls menu.hasVisibleItems() to determine
2614e411251159c965caccb3bf3727c2921d74f06c1Chris Banes            // if a panel is prepared. This interferes with any initially invisible items, which
2624e411251159c965caccb3bf3727c2921d74f06c1Chris Banes            // are later made visible. We workaround it by making hasVisibleItems() always
2634e411251159c965caccb3bf3727c2921d74f06c1Chris Banes            // return true during the onPreparePanel call.
2644e411251159c965caccb3bf3727c2921d74f06c1Chris Banes            if (mb != null) {
2654e411251159c965caccb3bf3727c2921d74f06c1Chris Banes                mb.setOverrideVisibleItems(true);
2664e411251159c965caccb3bf3727c2921d74f06c1Chris Banes            }
2674e411251159c965caccb3bf3727c2921d74f06c1Chris Banes
2684e411251159c965caccb3bf3727c2921d74f06c1Chris Banes            final boolean handled = super.onPreparePanel(featureId, view, menu);
2694e411251159c965caccb3bf3727c2921d74f06c1Chris Banes
2704e411251159c965caccb3bf3727c2921d74f06c1Chris Banes            if (mb != null) {
2714e411251159c965caccb3bf3727c2921d74f06c1Chris Banes                mb.setOverrideVisibleItems(false);
272f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            }
273f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
2744e411251159c965caccb3bf3727c2921d74f06c1Chris Banes            return handled;
275f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        }
276f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
277f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        @Override
278f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        public boolean onMenuOpened(int featureId, Menu menu) {
279d25af35061a9f20d59b25329d613c62c20184dadChris Banes            return super.onMenuOpened(featureId, menu)
280d25af35061a9f20d59b25329d613c62c20184dadChris Banes                    || AppCompatDelegateImplBase.this.onMenuOpened(featureId, menu);
281f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        }
282f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes
283f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        @Override
284f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        public void onPanelClosed(int featureId, Menu menu) {
285f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes            super.onPanelClosed(featureId, menu);
286d25af35061a9f20d59b25329d613c62c20184dadChris Banes            AppCompatDelegateImplBase.this.onPanelClosed(featureId, menu);
287f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes        }
288f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes    }
289f3ad1351d8b40ec5defe35e79d3430ad3c384b6dChris Banes}
290