Bug 1366352 - Ensure anchor is always set before trying to show tabs tray menu draft
authorAndrzej Hunt <ahunt@mozilla.com>
Fri, 19 May 2017 12:16:12 -0700
changeset 586576 0722d764665c9ee9d455e6b19e4fbca3a46628b3
parent 586536 39d5cc0fda5e16c49a59d29d4ca186a5534cc88b
child 586577 c12b8c5259431074c4193092dd2a3506e315b478
push id61472
push userahunt@mozilla.com
push dateTue, 30 May 2017 20:11:58 +0000
bugs1366352
milestone55.0a1
Bug 1366352 - Ensure anchor is always set before trying to show tabs tray menu MozReview-Commit-ID: 18KLMDlJUQe
mobile/android/base/java/org/mozilla/gecko/tabs/TabsPanel.java
--- a/mobile/android/base/java/org/mozilla/gecko/tabs/TabsPanel.java
+++ b/mobile/android/base/java/org/mozilla/gecko/tabs/TabsPanel.java
@@ -183,16 +183,21 @@ public class TabsPanel extends LinearLay
             public void onClick(View view) {
                 mActivity.onBackPressed();
             }
         });
     }
 
     public void showMenu() {
         final Menu menu = mPopupMenu.getMenu();
+        // Ensure we update the anchor here to absolutely guarantee there's an anchor
+        // We do set this during prepareToShow(), however only via a UI-thread callback. There are no
+        // guarantees that that callback will complete before a user clicks on the menu button, so
+        // we need to ensure we've set an anchor here.
+        mPopupMenu.setAnchor(mMenuButton);
 
         // Each panel has a "+" shortcut button, so don't show it for that panel.
         menu.findItem(R.id.new_tab).setVisible(mCurrentPanel != Panel.NORMAL_TABS);
         menu.findItem(R.id.new_private_tab).setVisible(mCurrentPanel != Panel.PRIVATE_TABS
                 && Restrictions.isAllowed(mContext, Restrictable.PRIVATE_BROWSING));
 
         // Only show "Clear * tabs" for current panel.
         menu.findItem(R.id.close_all_tabs).setVisible(mCurrentPanel == Panel.NORMAL_TABS);
@@ -379,22 +384,26 @@ public class TabsPanel extends LinearLay
             default:
                 throw new IllegalArgumentException("Unknown panel type " + panelToShow);
         }
         mPanel.show();
 
         mAddTab.setVisibility(View.VISIBLE);
 
         mMenuButton.setEnabled(true);
-        // If mPopupMenu is visible then setAnchor redisplays the menu on its new anchor - but we
-        // may have just been inflated, so give mMenuButton a chance to get its true measurements
-        // before mPopupMenu.setAnchor reads them to determine its offset from the anchor.
-        ThreadUtils.postToUiThread(new Runnable() {
+        mMenuButton.addOnLayoutChangeListener(new OnLayoutChangeListener() {
             @Override
-            public void run() {
+            public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                                       int oldLeft,
+                                       int oldTop, int oldRight, int oldBottom) {
+                // We also set the anchor in showMenu(), but we need to update it in case the menu
+                // is already showing.
+                // If mPopupMenu is visible then setAnchor redisplays the menu on its new anchor - but we
+                // may have just been inflated, so give mMenuButton a chance to get its true measurements
+                // before mPopupMenu.setAnchor reads them to determine its offset from the anchor.
                 mPopupMenu.setAnchor(mMenuButton);
             }
         });
     }
 
     public void hide() {
         mHeaderVisible = false;