Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f444b5c3 authored by Abodunrinwa Toki's avatar Abodunrinwa Toki
Browse files

Fix floating toolbar flickers.

-Flicker was a side effect the delay in hiding the toolbar when
there is a down press on a TextView handle. The timing clashed
with the time it takes for the FloatingActionMode to release a
hide lock on a changing content rect. Extra flickers also happened
if the ActionMode happened to be invalidated at about the same time.
Since there was no longer a hide lock, the toolbar refreshed, getting
rid of the "Select all" menu item.
FIX. I believe we don't need the delayed hide on down press on a
TextView handle. I've removed this.

-I've also updated FloatingActionMode to ensure that hide locks
overlap one another if necessary. The toolbar can only be visible if
all locks are off.

Bug: 21793687
Change-Id: I290ea45ab17d5862b453cb319afb4c8ffe084cd0
parent 6161c5b4
Loading
Loading
Loading
Loading
+1 −13
Original line number Original line Diff line number Diff line
@@ -244,15 +244,6 @@ public class Editor {


    final CursorAnchorInfoNotifier mCursorAnchorInfoNotifier = new CursorAnchorInfoNotifier();
    final CursorAnchorInfoNotifier mCursorAnchorInfoNotifier = new CursorAnchorInfoNotifier();


    private final Runnable mHideFloatingToolbar = new Runnable() {
        @Override
        public void run() {
            if (mTextActionMode != null) {
                mTextActionMode.hide(ActionMode.DEFAULT_HIDE_DURATION);
            }
        }
    };

    private final Runnable mShowFloatingToolbar = new Runnable() {
    private final Runnable mShowFloatingToolbar = new Runnable() {
        @Override
        @Override
        public void run() {
        public void run() {
@@ -389,7 +380,6 @@ public class Editor {
            mTextView.removeCallbacks(mInsertionActionModeRunnable);
            mTextView.removeCallbacks(mInsertionActionModeRunnable);
        }
        }


        mTextView.removeCallbacks(mHideFloatingToolbar);
        mTextView.removeCallbacks(mShowFloatingToolbar);
        mTextView.removeCallbacks(mShowFloatingToolbar);


        destroyDisplayListsData();
        destroyDisplayListsData();
@@ -1248,14 +1238,12 @@ public class Editor {
    private void hideFloatingToolbar() {
    private void hideFloatingToolbar() {
        if (mTextActionMode != null) {
        if (mTextActionMode != null) {
            mTextView.removeCallbacks(mShowFloatingToolbar);
            mTextView.removeCallbacks(mShowFloatingToolbar);
            // Delay the "hide" a little bit just in case a "show" will happen almost immediately.
            mTextActionMode.hide(ActionMode.DEFAULT_HIDE_DURATION);
            mTextView.postDelayed(mHideFloatingToolbar, 100);
        }
        }
    }
    }


    private void showFloatingToolbar() {
    private void showFloatingToolbar() {
        if (mTextActionMode != null) {
        if (mTextActionMode != null) {
            mTextView.removeCallbacks(mHideFloatingToolbar);
            // Delay "show" so it doesn't interfere with click confirmations
            // Delay "show" so it doesn't interfere with click confirmations
            // or double-clicks that could "dismiss" the floating toolbar.
            // or double-clicks that could "dismiss" the floating toolbar.
            int delay = ViewConfiguration.getDoubleTapTimeout();
            int delay = ViewConfiguration.getDoubleTapTimeout();
+57 −38
Original line number Original line Diff line number Diff line
@@ -48,12 +48,14 @@ public class FloatingActionMode extends ActionMode {
    private final Runnable mMovingOff = new Runnable() {
    private final Runnable mMovingOff = new Runnable() {
        public void run() {
        public void run() {
            mFloatingToolbarVisibilityHelper.setMoving(false);
            mFloatingToolbarVisibilityHelper.setMoving(false);
            mFloatingToolbarVisibilityHelper.updateToolbarVisibility();
        }
        }
    };
    };


    private final Runnable mHideOff = new Runnable() {
    private final Runnable mHideOff = new Runnable() {
        public void run() {
        public void run() {
            mFloatingToolbarVisibilityHelper.setHideRequested(false);
            mFloatingToolbarVisibilityHelper.setHideRequested(false);
            mFloatingToolbarVisibilityHelper.updateToolbarVisibility();
        }
        }
    };
    };


@@ -87,6 +89,7 @@ public class FloatingActionMode extends ActionMode {
                    }
                    }
                });
                });
        mFloatingToolbarVisibilityHelper = new FloatingToolbarVisibilityHelper(mFloatingToolbar);
        mFloatingToolbarVisibilityHelper = new FloatingToolbarVisibilityHelper(mFloatingToolbar);
        mFloatingToolbarVisibilityHelper.activate();
    }
    }


    @Override
    @Override
@@ -108,8 +111,7 @@ public class FloatingActionMode extends ActionMode {
    public void invalidate() {
    public void invalidate() {
        checkToolbarInitialized();
        checkToolbarInitialized();
        mCallback.onPrepareActionMode(this, mMenu);
        mCallback.onPrepareActionMode(this, mMenu);
        mFloatingToolbar.updateLayout();
        invalidateContentRect();  // Will re-layout and show the toolbar if necessary.
        invalidateContentRect();
    }
    }


    @Override
    @Override
@@ -131,6 +133,9 @@ public class FloatingActionMode extends ActionMode {


        mContentRectOnWindow.set(mContentRect);
        mContentRectOnWindow.set(mContentRect);
        mContentRectOnWindow.offset(mViewPosition[0], mViewPosition[1]);
        mContentRectOnWindow.offset(mViewPosition[0], mViewPosition[1]);

        if (isContentRectWithinBounds()) {
            mFloatingToolbarVisibilityHelper.setOutOfBounds(false);
            // Make sure that content rect is not out of the view's visible bounds.
            // Make sure that content rect is not out of the view's visible bounds.
            mContentRectOnWindow.set(
            mContentRectOnWindow.set(
                    Math.max(mContentRectOnWindow.left, mViewRect.left),
                    Math.max(mContentRectOnWindow.left, mViewRect.left),
@@ -139,19 +144,21 @@ public class FloatingActionMode extends ActionMode {
                    Math.min(mContentRectOnWindow.bottom, mViewRect.bottom));
                    Math.min(mContentRectOnWindow.bottom, mViewRect.bottom));


            if (!mContentRectOnWindow.equals(mPreviousContentRectOnWindow)) {
            if (!mContentRectOnWindow.equals(mPreviousContentRectOnWindow)) {
            if (!mPreviousContentRectOnWindow.isEmpty()) {
                // Content rect is moving.
                notifyContentRectMoving();
                mOriginatingView.removeCallbacks(mMovingOff);
            }
                mFloatingToolbarVisibilityHelper.setMoving(true);
                mOriginatingView.postDelayed(mMovingOff, MOVING_HIDE_DELAY);

                mFloatingToolbar.setContentRect(mContentRectOnWindow);
                mFloatingToolbar.setContentRect(mContentRectOnWindow);
                mFloatingToolbar.updateLayout();
                mFloatingToolbar.updateLayout();
            }
            }
        mPreviousContentRectOnWindow.set(mContentRectOnWindow);

        if (isContentRectWithinBounds()) {
            mFloatingToolbarVisibilityHelper.setOutOfBounds(false);
        } else {
        } else {
            mFloatingToolbarVisibilityHelper.setOutOfBounds(true);
            mFloatingToolbarVisibilityHelper.setOutOfBounds(true);
            mContentRectOnWindow.setEmpty();
        }
        }
        mFloatingToolbarVisibilityHelper.updateToolbarVisibility();

        mPreviousContentRectOnWindow.set(mContentRectOnWindow);
    }
    }


    private boolean isContentRectWithinBounds() {
    private boolean isContentRectWithinBounds() {
@@ -165,12 +172,6 @@ public class FloatingActionMode extends ActionMode {
            && Rect.intersects(mContentRectOnWindow, mViewRect);
            && Rect.intersects(mContentRectOnWindow, mViewRect);
    }
    }


    private void notifyContentRectMoving() {
        mOriginatingView.removeCallbacks(mMovingOff);
        mFloatingToolbarVisibilityHelper.setMoving(true);
        mOriginatingView.postDelayed(mMovingOff, MOVING_HIDE_DELAY);
    }

    @Override
    @Override
    public void hide(long duration) {
    public void hide(long duration) {
        checkToolbarInitialized();
        checkToolbarInitialized();
@@ -184,6 +185,7 @@ public class FloatingActionMode extends ActionMode {
            mHideOff.run();
            mHideOff.run();
        } else {
        } else {
            mFloatingToolbarVisibilityHelper.setHideRequested(true);
            mFloatingToolbarVisibilityHelper.setHideRequested(true);
            mFloatingToolbarVisibilityHelper.updateToolbarVisibility();
            mOriginatingView.postDelayed(mHideOff, duration);
            mOriginatingView.postDelayed(mHideOff, duration);
        }
        }
    }
    }
@@ -221,7 +223,7 @@ public class FloatingActionMode extends ActionMode {
    }
    }


    /**
    /**
     * @throws IlllegalStateException
     * @throws IllegalStateException
     */
     */
    private void checkToolbarInitialized() {
    private void checkToolbarInitialized() {
        Preconditions.checkState(mFloatingToolbar != null);
        Preconditions.checkState(mFloatingToolbar != null);
@@ -229,13 +231,14 @@ public class FloatingActionMode extends ActionMode {
    }
    }


    private void reset() {
    private void reset() {
        mFloatingToolbarVisibilityHelper.deactivate();
        mOriginatingView.removeCallbacks(mMovingOff);
        mOriginatingView.removeCallbacks(mMovingOff);
        mOriginatingView.removeCallbacks(mHideOff);
        mOriginatingView.removeCallbacks(mHideOff);
    }
    }




    /**
    /**
     * A helper that shows/hides the floating toolbar depending on certain states.
     * A helper for showing/hiding the floating toolbar depending on certain states.
     */
     */
    private static final class FloatingToolbarVisibilityHelper {
    private static final class FloatingToolbarVisibilityHelper {


@@ -245,29 +248,45 @@ public class FloatingActionMode extends ActionMode {
        private boolean mMoving;
        private boolean mMoving;
        private boolean mOutOfBounds;
        private boolean mOutOfBounds;


        private boolean mActive;

        public FloatingToolbarVisibilityHelper(FloatingToolbar toolbar) {
        public FloatingToolbarVisibilityHelper(FloatingToolbar toolbar) {
            mToolbar = Preconditions.checkNotNull(toolbar);
            mToolbar = Preconditions.checkNotNull(toolbar);
        }
        }


        public void activate() {
            mHideRequested = false;
            mMoving = false;
            mOutOfBounds = false;

            mActive = true;
        }

        public void deactivate() {
            mActive = false;
            mToolbar.dismiss();
        }

        public void setHideRequested(boolean hide) {
        public void setHideRequested(boolean hide) {
            mHideRequested = hide;
            mHideRequested = hide;
            updateToolbarVisibility();
        }
        }


        public void setMoving(boolean moving) {
        public void setMoving(boolean moving) {
            mMoving = moving;
            mMoving = moving;
            updateToolbarVisibility();
        }
        }


        public void setOutOfBounds(boolean outOfBounds) {
        public void setOutOfBounds(boolean outOfBounds) {
            mOutOfBounds = outOfBounds;
            mOutOfBounds = outOfBounds;
            updateToolbarVisibility();
        }
        }


        private void updateToolbarVisibility() {
        public void updateToolbarVisibility() {
            if (!mActive) {
                return;
            }

            if (mHideRequested || mMoving || mOutOfBounds) {
            if (mHideRequested || mMoving || mOutOfBounds) {
                mToolbar.hide();
                mToolbar.hide();
            } else if (mToolbar.isHidden()) {
            } else {
                mToolbar.show();
                mToolbar.show();
            }
            }
        }
        }