| Index: base/android/java/src/org/chromium/base/BaseChromiumApplication.java
|
| diff --git a/base/android/java/src/org/chromium/base/BaseChromiumApplication.java b/base/android/java/src/org/chromium/base/BaseChromiumApplication.java
|
| index 2946f6fb0004ad2da54e4e5985f4f75029ff2901..c87d02d7d33e8fbee7b44f87472af8af74d8973e 100644
|
| --- a/base/android/java/src/org/chromium/base/BaseChromiumApplication.java
|
| +++ b/base/android/java/src/org/chromium/base/BaseChromiumApplication.java
|
| @@ -11,6 +11,10 @@ import android.os.Bundle;
|
| import android.view.KeyEvent;
|
| import android.view.Window;
|
|
|
| +import java.lang.reflect.InvocationHandler;
|
| +import java.lang.reflect.Method;
|
| +import java.lang.reflect.Proxy;
|
| +
|
| /**
|
| * Basic application functionality that should be shared among all browser applications.
|
| */
|
| @@ -30,66 +34,94 @@ public class BaseChromiumApplication extends Application {
|
| private ObserverList<WindowFocusChangedListener> mWindowFocusListeners =
|
| new ObserverList<WindowFocusChangedListener>();
|
|
|
| + /**
|
| + * Intercepts calls to an existing Window.Callback. Most invocations are passed on directly
|
| + * to the composed Window.Callback but enables intercepting/manipulating others.
|
| + *
|
| + * This is used to relay window focus changes throughout the app and remedy a bug in the
|
| + * appcompat library.
|
| + */
|
| + private class WindowCallbackProxy implements InvocationHandler {
|
| + private final Window.Callback mCallback;
|
| + private final Activity mActivity;
|
| +
|
| + public WindowCallbackProxy(Activity activity, Window.Callback callback) {
|
| + mCallback = callback;
|
| + mActivity = activity;
|
| + }
|
| +
|
| + @Override
|
| + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
| + if (method.getName().equals("onWindowFocusChanged") && args.length == 1
|
| + && args[0] instanceof Boolean) {
|
| + onWindowFocusChanged((boolean) args[0]);
|
| + return null;
|
| + } else if (method.getName().equals("dispatchKeyEvent") && args.length == 1
|
| + && args[0] instanceof KeyEvent) {
|
| + return dispatchKeyEvent((KeyEvent) args[0]);
|
| + } else {
|
| + return method.invoke(mCallback, args);
|
| + }
|
| + }
|
| +
|
| + public void onWindowFocusChanged(boolean hasFocus) {
|
| + mCallback.onWindowFocusChanged(hasFocus);
|
| +
|
| + for (WindowFocusChangedListener listener : mWindowFocusListeners) {
|
| + listener.onWindowFocusChanged(mActivity, hasFocus);
|
| + }
|
| + }
|
| +
|
| + public boolean dispatchKeyEvent(KeyEvent event) {
|
| + // TODO(aurimas): remove this once AppCompatDelegateImpl no longer steals
|
| + // KEYCODE_MENU. (see b/20529185)
|
| + if (event.getKeyCode() == KeyEvent.KEYCODE_MENU && mActivity.dispatchKeyEvent(event)) {
|
| + return true;
|
| + }
|
| + return mCallback.dispatchKeyEvent(event);
|
| + }
|
| + }
|
| @Override
|
| public void onCreate() {
|
| super.onCreate();
|
| ApplicationStatus.initialize(this);
|
| -
|
| registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
|
| @Override
|
| public void onActivityCreated(final Activity activity, Bundle savedInstanceState) {
|
| Window.Callback callback = activity.getWindow().getCallback();
|
| - activity.getWindow().setCallback(new WindowCallbackWrapper(callback) {
|
| - @Override
|
| - public void onWindowFocusChanged(boolean hasFocus) {
|
| - super.onWindowFocusChanged(hasFocus);
|
| -
|
| - for (WindowFocusChangedListener listener : mWindowFocusListeners) {
|
| - listener.onWindowFocusChanged(activity, hasFocus);
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public boolean dispatchKeyEvent(KeyEvent event) {
|
| - // TODO(aurimas): remove this once AppCompatDelegateImpl no longer steals
|
| - // KEYCODE_MENU. (see b/20529185)
|
| - if (event.getKeyCode() == KeyEvent.KEYCODE_MENU
|
| - && activity.dispatchKeyEvent(event)) {
|
| - return true;
|
| - }
|
| - return super.dispatchKeyEvent(event);
|
| - }
|
| - });
|
| + activity.getWindow().setCallback((Window.Callback) Proxy.newProxyInstance(
|
| + Window.Callback.class.getClassLoader(), new Class[] {Window.Callback.class},
|
| + new WindowCallbackProxy(activity, callback)));
|
| }
|
|
|
| @Override
|
| public void onActivityDestroyed(Activity activity) {
|
| - assert activity.getWindow().getCallback() instanceof WindowCallbackWrapper;
|
| + assert Proxy.isProxyClass(activity.getWindow().getCallback().getClass());
|
| }
|
|
|
| @Override
|
| public void onActivityPaused(Activity activity) {
|
| - assert activity.getWindow().getCallback() instanceof WindowCallbackWrapper;
|
| + assert Proxy.isProxyClass(activity.getWindow().getCallback().getClass());
|
| }
|
|
|
| @Override
|
| public void onActivityResumed(Activity activity) {
|
| - assert activity.getWindow().getCallback() instanceof WindowCallbackWrapper;
|
| + assert Proxy.isProxyClass(activity.getWindow().getCallback().getClass());
|
| }
|
|
|
| @Override
|
| public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
|
| - assert activity.getWindow().getCallback() instanceof WindowCallbackWrapper;
|
| + assert Proxy.isProxyClass(activity.getWindow().getCallback().getClass());
|
| }
|
|
|
| @Override
|
| public void onActivityStarted(Activity activity) {
|
| - assert activity.getWindow().getCallback() instanceof WindowCallbackWrapper;
|
| + assert Proxy.isProxyClass(activity.getWindow().getCallback().getClass());
|
| }
|
|
|
| @Override
|
| public void onActivityStopped(Activity activity) {
|
| - assert activity.getWindow().getCallback() instanceof WindowCallbackWrapper;
|
| + assert Proxy.isProxyClass(activity.getWindow().getCallback().getClass());
|
| }
|
| });
|
| }
|
|
|