emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/android 2634765bc38: Improve context menus on old versions of An


From: Po Lu
Subject: feature/android 2634765bc38: Improve context menus on old versions of Android
Date: Sat, 4 Mar 2023 02:57:21 -0500 (EST)

branch: feature/android
commit 2634765bc382c27e2d11dc14174ca80d9cf41e15
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Improve context menus on old versions of Android
    
    * java/org/gnu/emacs/EmacsActivity.java (EmacsActivity): New
    field `lastClosedMenu'.
    (onContextMenuClosed): Don't send event if a menu is closed
    twice in a row.  Also, clear wasSubmenuSelected immediately.
    * java/org/gnu/emacs/EmacsContextMenu.java: Display submenus
    manually in Android 6.0 and earlier.
    * java/org/gnu/emacs/EmacsView.java (onCreateContextMenu)
    (popupMenu): Adjust accordingly.
---
 java/org/gnu/emacs/EmacsActivity.java    | 17 ++++++-
 java/org/gnu/emacs/EmacsContextMenu.java | 81 ++++++++++++++++++++++----------
 java/org/gnu/emacs/EmacsView.java        |  9 ++--
 3 files changed, 76 insertions(+), 31 deletions(-)

diff --git a/java/org/gnu/emacs/EmacsActivity.java 
b/java/org/gnu/emacs/EmacsActivity.java
index 62bef33fab3..13002d5d0e5 100644
--- a/java/org/gnu/emacs/EmacsActivity.java
+++ b/java/org/gnu/emacs/EmacsActivity.java
@@ -65,6 +65,9 @@ public class EmacsActivity extends Activity
   /* Whether or not this activity is fullscreen.  */
   private boolean isFullscreen;
 
+  /* The last context menu to be closed.  */
+  private Menu lastClosedMenu;
+
   static
   {
     focusedActivities = new ArrayList<EmacsActivity> ();
@@ -308,9 +311,19 @@ public class EmacsActivity extends Activity
     Log.d (TAG, "onContextMenuClosed: " + menu);
 
     /* See the comment inside onMenuItemClick.  */
+
     if (EmacsContextMenu.wasSubmenuSelected
-       && menu.toString ().contains ("ContextMenuBuilder"))
-      return;
+       || menu == lastClosedMenu)
+      {
+       EmacsContextMenu.wasSubmenuSelected = false;
+       lastClosedMenu = menu;
+       return;
+      }
+
+    /* lastClosedMenu is set because Android apparently calls this
+       function twice.  */
+
+    lastClosedMenu = null;
 
     /* Send a context menu event given that no menu item has already
        been selected.  */
diff --git a/java/org/gnu/emacs/EmacsContextMenu.java 
b/java/org/gnu/emacs/EmacsContextMenu.java
index a1bca98daa0..d1a624e68d9 100644
--- a/java/org/gnu/emacs/EmacsContextMenu.java
+++ b/java/org/gnu/emacs/EmacsContextMenu.java
@@ -58,6 +58,7 @@ public final class EmacsContextMenu
     public String itemName, tooltip;
     public EmacsContextMenu subMenu;
     public boolean isEnabled, isCheckable, isChecked;
+    public EmacsView inflatedView;
 
     @Override
     public boolean
@@ -67,6 +68,34 @@ public final class EmacsContextMenu
 
       if (subMenu != null)
        {
+         /* Android 6.0 and earlier don't support nested submenus
+            properly, so display the submenu popup by hand.  */
+
+         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
+           {
+             Log.d (TAG, "onMenuItemClick: displaying submenu " + subMenu);
+
+             /* Still set wasSubmenuSelected -- if not set, the
+                dismissal of this context menu will result in a
+                context menu event being sent.  */
+             wasSubmenuSelected = true;
+
+             /* Running a popup menu from inside a click handler
+                doesn't work, so make sure it is displayed
+                outside.  */
+
+             inflatedView.post (new Runnable () {
+                 @Override
+                 public void
+                 run ()
+                 {
+                   inflatedView.popupMenu (subMenu, 0, 0, true);
+                 }
+               });
+
+             return true;
+           }
+
          /* After opening a submenu within a submenu, Android will
             send onContextMenuClosed for a ContextMenuBuilder.  This
             will normally confuse Emacs into thinking that the
@@ -164,10 +193,11 @@ public final class EmacsContextMenu
     return item.subMenu;
   }
 
-  /* Add the contents of this menu to MENU.  */
+  /* Add the contents of this menu to MENU.  Assume MENU will be
+     displayed in INFLATEDVIEW.  */
 
   private void
-  inflateMenuItems (Menu menu)
+  inflateMenuItems (Menu menu, EmacsView inflatedView)
   {
     Intent intent;
     MenuItem menuItem;
@@ -177,26 +207,26 @@ public final class EmacsContextMenu
       {
        if (item.subMenu != null)
          {
-           try
+           /* This is a submenu.  On versions of Android which
+              support doing so, create the submenu and add the
+              contents of the menu to it.
+
+              Note that Android 4.0 and later technically supports
+              having multiple layers of nested submenus, but if they
+              are used, onContextMenuClosed becomes unreliable.  */
+
+           if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
              {
-               /* This is a submenu.  On versions of Android which
-                  support doing so, create the submenu and add the
-                  contents of the menu to it.  */
                submenu = menu.addSubMenu (item.itemName);
-               item.subMenu.inflateMenuItems (submenu);
-             }
-           catch (UnsupportedOperationException exception)
-             {
-               /* This version of Android has a restriction
-                  preventing submenus from being added to submenus.
-                  Inflate everything into the parent menu
-                  instead.  */
-               item.subMenu.inflateMenuItems (menu);
-               continue;
+               item.subMenu.inflateMenuItems (submenu, inflatedView);
+
+               /* This is still needed to set wasSubmenuSelected.  */
+               menuItem = submenu.getItem ();
              }
+           else
+             menuItem = menu.add (item.itemName);
 
-           /* This is still needed to set wasSubmenuSelected.  */
-           menuItem = submenu.getItem ();
+           item.inflatedView = inflatedView;
            menuItem.setOnMenuItemClickListener (item);
          }
        else
@@ -227,16 +257,14 @@ public final class EmacsContextMenu
       }
   }
 
-  /* Enter the items in this context menu to MENU.  Create each menu
-     item with an Intent containing a Bundle, where the key
-     "emacs:menu_item_hi" maps to the high 16 bits of the
-     corresponding item ID, and the key "emacs:menu_item_low" maps to
-     the low 16 bits of the item ID.  */
+  /* Enter the items in this context menu to MENU.
+     Assume that MENU will be displayed in VIEW; this may lead to
+     popupMenu being called on VIEW if a submenu is selected.  */
 
   public void
-  expandTo (Menu menu)
+  expandTo (Menu menu, EmacsView view)
   {
-    inflateMenuItems (menu);
+    inflateMenuItems (menu, view);
   }
 
   /* Return the parent or NULL.  */
@@ -260,7 +288,8 @@ public final class EmacsContextMenu
     /* No submenu has been selected yet.  */
     wasSubmenuSelected = false;
 
-    return window.view.popupMenu (this, xPosition, yPosition);
+    return window.view.popupMenu (this, xPosition, yPosition,
+                                 false);
   }
 
   /* Display this context menu on WINDOW, at xPosition and
diff --git a/java/org/gnu/emacs/EmacsView.java 
b/java/org/gnu/emacs/EmacsView.java
index d2330494bc7..617836d8811 100644
--- a/java/org/gnu/emacs/EmacsView.java
+++ b/java/org/gnu/emacs/EmacsView.java
@@ -464,19 +464,22 @@ public final class EmacsView extends ViewGroup
     if (contextMenu == null)
       return;
 
-    contextMenu.expandTo (menu);
+    contextMenu.expandTo (menu, this);
   }
 
   public boolean
   popupMenu (EmacsContextMenu menu, int xPosition,
-            int yPosition)
+            int yPosition, boolean force)
   {
-    if (popupActive)
+    if (popupActive && !force)
       return false;
 
     contextMenu = menu;
     popupActive = true;
 
+    Log.d (TAG, "popupMenu: " + menu + " @" + xPosition
+          + ", " + yPosition + " " + force);
+
     /* Use showContextMenu (float, float) on N to get actual popup
        behavior.  */
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]