| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.ui.base; | 5 package org.chromium.ui.base; |
| 6 | 6 |
| 7 import android.animation.Animator; | 7 import android.animation.Animator; |
| 8 import android.animation.AnimatorListenerAdapter; | 8 import android.animation.AnimatorListenerAdapter; |
| 9 import android.annotation.SuppressLint; | 9 import android.annotation.SuppressLint; |
| 10 import android.annotation.TargetApi; |
| 10 import android.app.Activity; | 11 import android.app.Activity; |
| 11 import android.app.PendingIntent; | 12 import android.app.PendingIntent; |
| 12 import android.content.ContentResolver; | 13 import android.content.ContentResolver; |
| 13 import android.content.Context; | 14 import android.content.Context; |
| 14 import android.content.Intent; | 15 import android.content.Intent; |
| 16 import android.os.Build; |
| 15 import android.os.Bundle; | 17 import android.os.Bundle; |
| 16 import android.util.Log; | 18 import android.util.Log; |
| 17 import android.util.SparseArray; | 19 import android.util.SparseArray; |
| 18 import android.view.View; | 20 import android.view.View; |
| 19 import android.view.ViewGroup; | 21 import android.view.ViewGroup; |
| 22 import android.view.accessibility.AccessibilityManager; |
| 20 import android.widget.Toast; | 23 import android.widget.Toast; |
| 21 | 24 |
| 22 import org.chromium.base.CalledByNative; | 25 import org.chromium.base.CalledByNative; |
| 23 import org.chromium.base.JNINamespace; | 26 import org.chromium.base.JNINamespace; |
| 24 import org.chromium.ui.VSyncMonitor; | 27 import org.chromium.ui.VSyncMonitor; |
| 25 | 28 |
| 26 import java.lang.ref.WeakReference; | 29 import java.lang.ref.WeakReference; |
| 27 import java.util.HashMap; | 30 import java.util.HashMap; |
| 28 import java.util.HashSet; | 31 import java.util.HashSet; |
| 29 import java.util.LinkedList; | 32 import java.util.LinkedList; |
| 30 | 33 |
| 31 /** | 34 /** |
| 32 * The window base class that has the minimum functionality. | 35 * The window base class that has the minimum functionality. |
| 33 */ | 36 */ |
| 34 @JNINamespace("ui") | 37 @JNINamespace("ui") |
| 35 public class WindowAndroid { | 38 public class WindowAndroid { |
| 36 private static final String TAG = "WindowAndroid"; | 39 private static final String TAG = "WindowAndroid"; |
| 37 | 40 |
| 41 @TargetApi(Build.VERSION_CODES.KITKAT) |
| 42 private class TouchExplorationMonitor { |
| 43 // Listener that tells us when touch exploration is enabled or disabled. |
| 44 private AccessibilityManager.TouchExplorationStateChangeListener mTouchE
xplorationListener; |
| 45 |
| 46 TouchExplorationMonitor() { |
| 47 mTouchExplorationListener = |
| 48 new AccessibilityManager.TouchExplorationStateChangeListener
() { |
| 49 public void onTouchExplorationStateChanged(boolean enabled) { |
| 50 mIsTouchExplorationEnabled = |
| 51 mAccessibilityManager.isTouchExplorationEnabled(); |
| 52 refreshWillNotDraw(); |
| 53 } |
| 54 }; |
| 55 mAccessibilityManager.addTouchExplorationStateChangeListener(mTouchE
xplorationListener); |
| 56 } |
| 57 |
| 58 void destroy() { |
| 59 mAccessibilityManager.removeTouchExplorationStateChangeListener( |
| 60 mTouchExplorationListener); |
| 61 } |
| 62 } |
| 63 |
| 38 // Native pointer to the c++ WindowAndroid object. | 64 // Native pointer to the c++ WindowAndroid object. |
| 39 private long mNativeWindowAndroid = 0; | 65 private long mNativeWindowAndroid = 0; |
| 40 private final VSyncMonitor mVSyncMonitor; | 66 private final VSyncMonitor mVSyncMonitor; |
| 41 | 67 |
| 42 // A string used as a key to store intent errors in a bundle | 68 // A string used as a key to store intent errors in a bundle |
| 43 static final String WINDOW_CALLBACK_ERRORS = "window_callback_errors"; | 69 static final String WINDOW_CALLBACK_ERRORS = "window_callback_errors"; |
| 44 | 70 |
| 45 // Error code returned when an Intent fails to start an Activity. | 71 // Error code returned when an Intent fails to start an Activity. |
| 46 public static final int START_INTENT_FAILURE = -1; | 72 public static final int START_INTENT_FAILURE = -1; |
| 47 | 73 |
| 48 protected Context mApplicationContext; | 74 protected Context mApplicationContext; |
| 49 protected SparseArray<IntentCallback> mOutstandingIntents; | 75 protected SparseArray<IntentCallback> mOutstandingIntents; |
| 50 | 76 |
| 51 // Ideally, this would be a SparseArray<String>, but there's no easy way to
store a | 77 // Ideally, this would be a SparseArray<String>, but there's no easy way to
store a |
| 52 // SparseArray<String> in a bundle during saveInstanceState(). So we use a H
ashMap and suppress | 78 // SparseArray<String> in a bundle during saveInstanceState(). So we use a H
ashMap and suppress |
| 53 // the Android lint warning "UseSparseArrays". | 79 // the Android lint warning "UseSparseArrays". |
| 54 protected HashMap<Integer, String> mIntentErrors; | 80 protected HashMap<Integer, String> mIntentErrors; |
| 55 | 81 |
| 56 // We track all animations over content and provide a drawing placeholder fo
r them. | 82 // We track all animations over content and provide a drawing placeholder fo
r them. |
| 57 private HashSet<Animator> mAnimationsOverContent = new HashSet<Animator>(); | 83 private HashSet<Animator> mAnimationsOverContent = new HashSet<Animator>(); |
| 58 private View mAnimationPlaceholderView; | 84 private View mAnimationPlaceholderView; |
| 59 | 85 |
| 60 private ViewGroup mKeyboardAccessoryView; | 86 private ViewGroup mKeyboardAccessoryView; |
| 61 | 87 |
| 62 private boolean mIsKeyboardShowing = false; | 88 private boolean mIsKeyboardShowing = false; |
| 63 | 89 |
| 90 // System accessibility service. |
| 91 private final AccessibilityManager mAccessibilityManager; |
| 92 |
| 93 // Whether touch exploration is enabled. |
| 94 private boolean mIsTouchExplorationEnabled; |
| 95 |
| 96 // On KitKat and higher, a class that monitors the touch exploration state. |
| 97 private TouchExplorationMonitor mTouchExplorationMonitor; |
| 98 |
| 64 /** | 99 /** |
| 65 * An interface to notify listeners of changes in the soft keyboard's visibi
lity. | 100 * An interface to notify listeners of changes in the soft keyboard's visibi
lity. |
| 66 */ | 101 */ |
| 67 public interface KeyboardVisibilityListener { | 102 public interface KeyboardVisibilityListener { |
| 68 public void keyboardVisibilityChanged(boolean isShowing); | 103 public void keyboardVisibilityChanged(boolean isShowing); |
| 69 } | 104 } |
| 70 private LinkedList<KeyboardVisibilityListener> mKeyboardVisibilityListeners
= | 105 private LinkedList<KeyboardVisibilityListener> mKeyboardVisibilityListeners
= |
| 71 new LinkedList<KeyboardVisibilityListener>(); | 106 new LinkedList<KeyboardVisibilityListener>(); |
| 72 | 107 |
| 73 private final VSyncMonitor.Listener mVSyncListener = new VSyncMonitor.Listen
er() { | 108 private final VSyncMonitor.Listener mVSyncListener = new VSyncMonitor.Listen
er() { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 92 /** | 127 /** |
| 93 * @param context The application context. | 128 * @param context The application context. |
| 94 */ | 129 */ |
| 95 @SuppressLint("UseSparseArrays") | 130 @SuppressLint("UseSparseArrays") |
| 96 public WindowAndroid(Context context) { | 131 public WindowAndroid(Context context) { |
| 97 assert context == context.getApplicationContext(); | 132 assert context == context.getApplicationContext(); |
| 98 mApplicationContext = context; | 133 mApplicationContext = context; |
| 99 mOutstandingIntents = new SparseArray<IntentCallback>(); | 134 mOutstandingIntents = new SparseArray<IntentCallback>(); |
| 100 mIntentErrors = new HashMap<Integer, String>(); | 135 mIntentErrors = new HashMap<Integer, String>(); |
| 101 mVSyncMonitor = new VSyncMonitor(context, mVSyncListener); | 136 mVSyncMonitor = new VSyncMonitor(context, mVSyncListener); |
| 137 mAccessibilityManager = (AccessibilityManager) |
| 138 context.getSystemService(Context.ACCESSIBILITY_SERVICE); |
| 102 } | 139 } |
| 103 | 140 |
| 104 /** | 141 /** |
| 105 * Shows an intent and returns the results to the callback object. | 142 * Shows an intent and returns the results to the callback object. |
| 106 * @param intent The PendingIntent that needs to be shown. | 143 * @param intent The PendingIntent that needs to be shown. |
| 107 * @param callback The object that will receive the results for the intent. | 144 * @param callback The object that will receive the results for the intent. |
| 108 * @param errorId The ID of error string to be show if activity is paused b
efore intent | 145 * @param errorId The ID of error string to be show if activity is paused b
efore intent |
| 109 * results, or null if no message is required. | 146 * results, or null if no message is required. |
| 110 * @return Whether the intent was shown. | 147 * @return Whether the intent was shown. |
| 111 */ | 148 */ |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 } | 347 } |
| 311 | 348 |
| 312 /** | 349 /** |
| 313 * Destroys the c++ WindowAndroid object if one has been created. | 350 * Destroys the c++ WindowAndroid object if one has been created. |
| 314 */ | 351 */ |
| 315 public void destroy() { | 352 public void destroy() { |
| 316 if (mNativeWindowAndroid != 0) { | 353 if (mNativeWindowAndroid != 0) { |
| 317 nativeDestroy(mNativeWindowAndroid); | 354 nativeDestroy(mNativeWindowAndroid); |
| 318 mNativeWindowAndroid = 0; | 355 mNativeWindowAndroid = 0; |
| 319 } | 356 } |
| 357 |
| 358 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { |
| 359 if (mTouchExplorationMonitor != null) mTouchExplorationMonitor.destr
oy(); |
| 360 } |
| 320 } | 361 } |
| 321 | 362 |
| 322 /** | 363 /** |
| 323 * Returns a pointer to the c++ AndroidWindow object and calls the initializ
er if | 364 * Returns a pointer to the c++ AndroidWindow object and calls the initializ
er if |
| 324 * the object has not been previously initialized. | 365 * the object has not been previously initialized. |
| 325 * @return A pointer to the c++ AndroidWindow. | 366 * @return A pointer to the c++ AndroidWindow. |
| 326 */ | 367 */ |
| 327 public long getNativePointer() { | 368 public long getNativePointer() { |
| 328 if (mNativeWindowAndroid == 0) { | 369 if (mNativeWindowAndroid == 0) { |
| 329 mNativeWindowAndroid = nativeInit(); | 370 mNativeWindowAndroid = nativeInit(); |
| 330 } | 371 } |
| 331 return mNativeWindowAndroid; | 372 return mNativeWindowAndroid; |
| 332 } | 373 } |
| 333 | 374 |
| 334 /** | 375 /** |
| 335 * Set the animation placeholder view, which we set to 'draw' during animati
ons, such that | 376 * Set the animation placeholder view, which we set to 'draw' during animati
ons, such that |
| 336 * animations aren't clipped by the SurfaceView 'hole'. This can be the Surf
aceView itself | 377 * animations aren't clipped by the SurfaceView 'hole'. This can be the Surf
aceView itself |
| 337 * or a view directly on top of it. This could be extended to many views if
we ever need it. | 378 * or a view directly on top of it. This could be extended to many views if
we ever need it. |
| 338 */ | 379 */ |
| 339 public void setAnimationPlaceholderView(View view) { | 380 public void setAnimationPlaceholderView(View view) { |
| 340 mAnimationPlaceholderView = view; | 381 mAnimationPlaceholderView = view; |
| 382 |
| 383 // The accessibility focus ring also gets clipped by the SurfaceView 'ho
le', so |
| 384 // make sure the animation placeholder view is in place if touch explora
tion is on. |
| 385 mIsTouchExplorationEnabled = mAccessibilityManager.isTouchExplorationEna
bled(); |
| 386 refreshWillNotDraw(); |
| 387 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { |
| 388 mTouchExplorationMonitor = new TouchExplorationMonitor(); |
| 389 } |
| 341 } | 390 } |
| 342 | 391 |
| 343 /** | 392 /** |
| 344 * Sets the keyboard accessory view. | 393 * Sets the keyboard accessory view. |
| 345 * @param view This view sits at the bottom of the content area and pushes t
he content up rather | 394 * @param view This view sits at the bottom of the content area and pushes t
he content up rather |
| 346 * than overlaying it. Currently used as a container for Autofil
l suggestions. | 395 * than overlaying it. Currently used as a container for Autofil
l suggestions. |
| 347 */ | 396 */ |
| 348 public void setKeyboardAccessoryView(ViewGroup view) { | 397 public void setKeyboardAccessoryView(ViewGroup view) { |
| 349 mKeyboardAccessoryView = view; | 398 mKeyboardAccessoryView = view; |
| 350 } | 399 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 if (animation.isStarted()) throw new IllegalArgumentException("Already s
tarted."); | 452 if (animation.isStarted()) throw new IllegalArgumentException("Already s
tarted."); |
| 404 boolean added = mAnimationsOverContent.add(animation); | 453 boolean added = mAnimationsOverContent.add(animation); |
| 405 if (!added) throw new IllegalArgumentException("Already Added."); | 454 if (!added) throw new IllegalArgumentException("Already Added."); |
| 406 | 455 |
| 407 // We start the animation in this method to help guarantee that we never
get stuck in this | 456 // We start the animation in this method to help guarantee that we never
get stuck in this |
| 408 // state or leak objects into the set. Starting the animation here shoul
d guarantee that we | 457 // state or leak objects into the set. Starting the animation here shoul
d guarantee that we |
| 409 // get an onAnimationEnd callback, and remove this animation. | 458 // get an onAnimationEnd callback, and remove this animation. |
| 410 animation.start(); | 459 animation.start(); |
| 411 | 460 |
| 412 // When the first animation starts, make the placeholder 'draw' itself. | 461 // When the first animation starts, make the placeholder 'draw' itself. |
| 413 if (mAnimationPlaceholderView.willNotDraw()) { | 462 refreshWillNotDraw(); |
| 414 mAnimationPlaceholderView.setWillNotDraw(false); | |
| 415 } | |
| 416 | 463 |
| 417 // When the last animation ends, remove the placeholder view, | 464 // When the last animation ends, remove the placeholder view, |
| 418 // returning to the default optimized state. | 465 // returning to the default optimized state. |
| 419 animation.addListener(new AnimatorListenerAdapter() { | 466 animation.addListener(new AnimatorListenerAdapter() { |
| 420 @Override | 467 @Override |
| 421 public void onAnimationEnd(Animator animation) { | 468 public void onAnimationEnd(Animator animation) { |
| 422 animation.removeListener(this); | 469 animation.removeListener(this); |
| 423 mAnimationsOverContent.remove(animation); | 470 mAnimationsOverContent.remove(animation); |
| 424 if (mAnimationsOverContent.isEmpty()) { | 471 refreshWillNotDraw(); |
| 425 mAnimationPlaceholderView.setWillNotDraw(true); | |
| 426 } | |
| 427 } | 472 } |
| 428 }); | 473 }); |
| 429 } | 474 } |
| 430 | 475 |
| 476 /** |
| 477 * Update whether the placeholder is 'drawn' based on whether an animation i
s running |
| 478 * or touch exploration is enabled - if either of those are true, we call |
| 479 * setWillNotDraw(false) to ensure that the animation is drawn over the Surf
aceView, |
| 480 * and otherwise we call setWillNotDraw(true). |
| 481 */ |
| 482 private void refreshWillNotDraw() { |
| 483 boolean willNotDraw = !mIsTouchExplorationEnabled && mAnimationsOverCont
ent.isEmpty(); |
| 484 if (mAnimationPlaceholderView.willNotDraw() != willNotDraw) { |
| 485 mAnimationPlaceholderView.setWillNotDraw(willNotDraw); |
| 486 } |
| 487 } |
| 488 |
| 431 private native long nativeInit(); | 489 private native long nativeInit(); |
| 432 private native void nativeOnVSync(long nativeWindowAndroid, | 490 private native void nativeOnVSync(long nativeWindowAndroid, |
| 433 long vsyncTimeMicros, | 491 long vsyncTimeMicros, |
| 434 long vsyncPeriodMicros); | 492 long vsyncPeriodMicros); |
| 435 private native void nativeOnActivityPaused(long nativeWindowAndroid); | 493 private native void nativeOnActivityPaused(long nativeWindowAndroid); |
| 436 private native void nativeOnActivityResumed(long nativeWindowAndroid); | 494 private native void nativeOnActivityResumed(long nativeWindowAndroid); |
| 437 private native void nativeDestroy(long nativeWindowAndroid); | 495 private native void nativeDestroy(long nativeWindowAndroid); |
| 438 | 496 |
| 439 } | 497 } |
| OLD | NEW |