aboutsummaryrefslogtreecommitdiffstats
path: root/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/PopupWindowCompat.java
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/PopupWindowCompat.java')
-rw-r--r--libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/PopupWindowCompat.java178
1 files changed, 0 insertions, 178 deletions
diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/PopupWindowCompat.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/PopupWindowCompat.java
deleted file mode 100644
index 4c6e3720c..000000000
--- a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/PopupWindowCompat.java
+++ /dev/null
@@ -1,178 +0,0 @@
-
-package com.actionbarsherlock.internal.widget;
-
-import java.lang.reflect.Field;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewTreeObserver;
-import android.view.ViewTreeObserver.OnScrollChangedListener;
-import android.widget.PopupWindow;
-
-/**
- * Works around bugs in the handling of {@link ViewTreeObserver} by
- * {@link PopupWindow}.
- * <p>
- * <code>PopupWindow</code> registers an {@link OnScrollChangedListener} with
- * {@link ViewTreeObserver}, but does not keep a reference to the observer
- * instance that it has registers on. This is problematic when the anchor view
- * used by <code>PopupWindow</code> to access the observer is detached from the
- * window, as it will revert from the shared <code>ViewTreeObserver</code> owned
- * by the <code>ViewRoot</code> to a floating one, meaning
- * <code>PopupWindow</code> cannot unregister it's listener anymore and has
- * leaked it into the global observer.
- * <p>
- * This class works around this issue by
- * <ul>
- * <li>replacing <code>PopupWindow.mOnScrollChangedListener</code> with a no-op
- * listener so that any registration or unregistration performed by
- * <code>PopupWindow</code> itself has no effect and causes no leaks.
- * <li>registering the real listener only with the shared
- * <code>ViewTreeObserver</code> and keeping a reference to it to facilitate
- * correct unregistration. The reason for not registering on a floating observer
- * (before a view is attached) is that there is no safe way to get a reference
- * to the shared observer that the floating one will be merged into. This would
- * again cause the listener to leak.
- * </ul>
- */
-public class PopupWindowCompat extends PopupWindow {
-
- private static final Field superListenerField;
- static {
- Field f = null;
- try {
- f = PopupWindow.class.getDeclaredField("mOnScrollChangedListener");
- f.setAccessible(true);
- } catch (NoSuchFieldException e) {
- /* ignored */
- }
- superListenerField = f;
- }
-
- private static final OnScrollChangedListener NOP = new OnScrollChangedListener() {
- @Override
- public void onScrollChanged() {
- /* do nothing */
- }
- };
-
- private OnScrollChangedListener mSuperScrollListener;
- private ViewTreeObserver mViewTreeObserver;
-
- public PopupWindowCompat() {
- super();
- init();
- }
-
- public PopupWindowCompat(Context context) {
- super(context);
- init();
- }
-
- public PopupWindowCompat(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
-
- public PopupWindowCompat(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init();
- }
-
- // @TargetApi(Build.VERSION_CODES.HONEYCOMB)
- public PopupWindowCompat(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- init();
- }
-
- public PopupWindowCompat(int width, int height) {
- super(width, height);
- init();
- }
-
- public PopupWindowCompat(View contentView) {
- super(contentView);
- init();
- }
-
- public PopupWindowCompat(View contentView, int width, int height, boolean focusable) {
- super(contentView, width, height, focusable);
- init();
- }
-
- public PopupWindowCompat(View contentView, int width, int height) {
- super(contentView, width, height);
- init();
- }
-
- private void init() {
- if (superListenerField != null) {
- try {
- mSuperScrollListener = (OnScrollChangedListener) superListenerField.get(this);
- superListenerField.set(this, NOP);
- } catch (Exception e) {
- mSuperScrollListener = null;
- }
- }
- }
-
- private void unregisterListener() {
- // Don't do anything if we haven't managed to patch the super listener
- if (mSuperScrollListener != null && mViewTreeObserver != null) {
- if (mViewTreeObserver.isAlive()) {
- mViewTreeObserver.removeOnScrollChangedListener(mSuperScrollListener);
- }
- mViewTreeObserver = null;
- }
- }
-
- private void registerListener(View anchor) {
- // Don't do anything if we haven't managed to patch the super listener.
- // And don't bother attaching the listener if the anchor view isn't
- // attached. This means we'll only have to deal with the real VTO owned
- // by the ViewRoot.
- if (mSuperScrollListener != null) {
- ViewTreeObserver vto = (anchor.getWindowToken() != null) ? anchor.getViewTreeObserver()
- : null;
- if (vto != mViewTreeObserver) {
- if (mViewTreeObserver != null && mViewTreeObserver.isAlive()) {
- mViewTreeObserver.removeOnScrollChangedListener(mSuperScrollListener);
- }
- if ((mViewTreeObserver = vto) != null) {
- vto.addOnScrollChangedListener(mSuperScrollListener);
- }
- }
- }
- }
-
- @Override
- public void showAsDropDown(View anchor, int xoff, int yoff) {
- super.showAsDropDown(anchor, xoff, yoff);
- registerListener(anchor);
- }
-
- @Override
- public void update(View anchor, int xoff, int yoff, int width, int height) {
- super.update(anchor, xoff, yoff, width, height);
- registerListener(anchor);
- }
-
- @Override
- public void update(View anchor, int width, int height) {
- super.update(anchor, width, height);
- registerListener(anchor);
- }
-
- @Override
- public void showAtLocation(View parent, int gravity, int x, int y) {
- super.showAtLocation(parent, gravity, x, y);
- unregisterListener();
- }
-
- @Override
- public void dismiss() {
- super.dismiss();
- unregisterListener();
- }
-}