[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)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- feature/android 2634765bc38: Improve context menus on old versions of Android,
Po Lu <=