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

Commit 16b7f78d authored by Vadim Tryshev's avatar Vadim Tryshev
Browse files

Closing popup menus on rotation.

On rotation, popup menu move to a strange location at the side of the screen.
Now, I'm just closing popup on rotation.

We may want to close the menu (async process) during any stage of creating a
menu (async process too). To take all race conditions into account, I've made
some changes in menu creation, and openness detection logic.

Bug: 20024603
Change-Id: I152d293d992fcd71ffa6e8c4909b9de2b8080eb8
parent b16e7469
Loading
Loading
Loading
Loading
+28 −9
Original line number Diff line number Diff line
@@ -120,6 +120,13 @@ class NavigationBarApps extends LinearLayout {
    // has a child that will be moved to make the menu to appear where we need it.
    private final ViewGroup mPopupAnchor;
    private final PopupMenu mPopupMenu;

    /**
     * True if popup menu code is busy with a popup operation.
     * Attempting  to show a popup menu or to add menu items while it's returning true will
     * corrupt/crash the app.
     */
    private boolean mIsPopupInUse = false;
    private final int [] mClickedIconLocation = new int[2];

    public NavigationBarApps(Context context, AttributeSet attrs) {
@@ -287,6 +294,15 @@ class NavigationBarApps extends LinearLayout {
        mAppPackageMonitor.unregister();
    }

    @Override
    protected void onVisibilityChanged(View changedView, int visibility) {
        super.onVisibilityChanged(changedView, visibility);
        if (mIsPopupInUse && !isShown()) {
            // Hide the popup if current view became invisible.
            shutdownPopupMenu();
        }
    }

    private void addAppButton(AppButtonData appButtonData) {
        ImageView button = createAppButton(appButtonData);
        addView(button);
@@ -671,14 +687,12 @@ class NavigationBarApps extends LinearLayout {
    }

    /**
     * Returns true if popup menu code is busy with a popup operation.
     * Attempting  to show a popup menu or to add menu items while it's returning true will
     * corrupt/crash the app.
     * Brings the menu popup to closed state.
     * Can be called at any stage of the asynchronous process of showing a menu.
     */
    boolean isPopupInUse() {
        // mPopupAnchor's parent will be set to non-null/null by mWindowManager.add/RemoveView
        // correspondingly.
        return mPopupAnchor.getParent() != null;
    private void shutdownPopupMenu() {
        mWindowManager.removeView(mPopupAnchor);
        mPopupMenu.dismiss();
    }

    /**
@@ -712,14 +726,19 @@ class NavigationBarApps extends LinearLayout {
        mPopupMenu.setOnDismissListener(new PopupMenu.OnDismissListener() {
            @Override
            public void onDismiss(PopupMenu menu) {
                // FYU: thorough testing for closing menu either by the user or via
                // shutdownPopupMenu() called at various moments of the menu creation, revealed that
                // 'onDismiss' is guaranteed to be called after each invocation of showPopupMenu.
                mWindowManager.removeView(mPopupAnchor);
                anchorButton.removeOnAttachStateChangeListener(onAttachStateChangeListener);
                mPopupMenu.setOnDismissListener(null);
                mPopupMenu.getMenu().clear();
                mIsPopupInUse = false;
            }
        });

        mWindowManager.addView(mPopupAnchor, mPopupAnchorLayoutParams);
        mIsPopupInUse = true;
    }

    private void activateTask(int taskPersistentId) {
@@ -758,7 +777,7 @@ class NavigationBarApps extends LinearLayout {
     * tasks.
     */
    void maybeShowLaunchMenu(ImageView appIcon) {
        if (isPopupInUse()) return;
        if (mIsPopupInUse) return;
        AppButtonData appButtonData = (AppButtonData) appIcon.getTag();
        if (appButtonData.getTaskCount() <= 1) return;

@@ -889,7 +908,7 @@ class NavigationBarApps extends LinearLayout {

        @Override
        public boolean onContextClick(View v) {
            if (isPopupInUse()) return true;
            if (mIsPopupInUse) return true;
            ImageView appIcon = (ImageView) v;
            populateContextMenu(appIcon);
            showPopupMenu(appIcon);