From 6e2bc91d924fbeb0ad5728e0424eabc905c0d366 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 15 Jan 2023 11:57:10 +0800 Subject: Implement toolkit menus on Android * java/org/gnu/emacs/EmacsActivity.java (onContextMenuClosed): New function. * java/org/gnu/emacs/EmacsContextMenu.java (EmacsContextMenu): New field `itemAlreadySelected'. (onMenuItemClick): New function. (inflateMenuItems): Attach onClickListener as appropriate. (display1): Clear itemAlreadySelected. (display): Fix runnable synchronization. * java/org/gnu/emacs/EmacsNative.java (sendContextMenu): New function. * java/org/gnu/emacs/EmacsView.java (popupMenu): (cancelPopupMenu): Set popupactive correctly. * src/android.c (android_run_select_thread): Fix android_select again. (android_wait_event): New function. * src/android.h: Update prototypes. * src/androidgui.h (enum android_event_type): New `ANDROID_CONTEXT_MENU' event. (struct android_menu_event, union android_event): Add new event. * src/androidmenu.c (struct android_emacs_context_menu): New structure. (android_init_emacs_context_menu): Add `dismiss' method. (struct android_dismiss_menu_data): New structure. (android_dismiss_menu, android_process_events_for_menu): New functions. (android_menu_show): Set an actual item ID. (popup_activated): Define when stubify as well. (Fmenu_or_popup_active_p): New function. (syms_of_androidmenu): New function. * src/androidterm.c (handle_one_android_event): Handle context menu events. * src/androidterm.h (struct android_display_info): New field for menu item ID. * src/emacs.c (android_emacs_init): Call syms_of_androidmenu. * src/xdisp.c (note_mouse_highlight): Return if popup_activated on Android as well. --- java/org/gnu/emacs/EmacsActivity.java | 15 ++++++++ java/org/gnu/emacs/EmacsContextMenu.java | 64 ++++++++++++++++++++++++++++---- java/org/gnu/emacs/EmacsNative.java | 3 ++ java/org/gnu/emacs/EmacsView.java | 2 + 4 files changed, 77 insertions(+), 7 deletions(-) (limited to 'java') diff --git a/java/org/gnu/emacs/EmacsActivity.java b/java/org/gnu/emacs/EmacsActivity.java index 4cd286d1e89..4b96a376987 100644 --- a/java/org/gnu/emacs/EmacsActivity.java +++ b/java/org/gnu/emacs/EmacsActivity.java @@ -30,6 +30,7 @@ import android.os.Bundle; import android.util.Log; import android.widget.FrameLayout; import android.widget.FrameLayout.LayoutParams; +import android.view.Menu; public class EmacsActivity extends Activity implements EmacsWindowAttachmentManager.WindowConsumer @@ -227,4 +228,18 @@ public class EmacsActivity extends Activity EmacsWindowAttachmentManager.MANAGER.noticeDeiconified (this); super.onResume (); } + + @Override + public void + onContextMenuClosed (Menu menu) + { + Log.d (TAG, "onContextMenuClosed: " + menu); + + /* Send a context menu event given that no menu item has already + been selected. */ + if (!EmacsContextMenu.itemAlreadySelected) + EmacsNative.sendContextMenu ((short) 0, 0); + + super.onContextMenuClosed (menu); + } }; diff --git a/java/org/gnu/emacs/EmacsContextMenu.java b/java/org/gnu/emacs/EmacsContextMenu.java index 8d7ae08b257..02dd1c7efa9 100644 --- a/java/org/gnu/emacs/EmacsContextMenu.java +++ b/java/org/gnu/emacs/EmacsContextMenu.java @@ -31,6 +31,8 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.util.Log; + import android.widget.PopupMenu; /* Context menu implementation. This object is built from JNI and @@ -40,12 +42,31 @@ import android.widget.PopupMenu; public class EmacsContextMenu { - private class Item + private static final String TAG = "EmacsContextMenu"; + + /* Whether or not an item was selected. */ + public static boolean itemAlreadySelected; + + private class Item implements MenuItem.OnMenuItemClickListener { public int itemID; public String itemName; public EmacsContextMenu subMenu; public boolean isEnabled; + + @Override + public boolean + onMenuItemClick (MenuItem item) + { + Log.d (TAG, "onMenuItemClick: " + itemName + " (" + itemID + ")"); + + /* Send a context menu event. */ + EmacsNative.sendContextMenu ((short) 0, itemID); + + /* Say that an item has already been selected. */ + itemAlreadySelected = true; + return true; + } }; public List menuItems; @@ -137,6 +158,7 @@ public class EmacsContextMenu else { menuItem = menu.add (item.itemName); + menuItem.setOnMenuItemClickListener (item); /* If the item ID is zero, then disable the item. */ if (item.itemID == 0 || !item.isEnabled) @@ -171,6 +193,10 @@ public class EmacsContextMenu private boolean display1 (EmacsWindow window, int xPosition, int yPosition) { + /* Set this flag to false. It is used to decide whether or not to + send 0 in response to the context menu being closed. */ + itemAlreadySelected = false; + return window.view.popupMenu (this, xPosition, yPosition); } @@ -199,15 +225,39 @@ public class EmacsContextMenu } }; - try + synchronized (runnable) { - runnable.wait (); - } - catch (InterruptedException e) - { - EmacsNative.emacsAbort (); + EmacsService.SERVICE.runOnUiThread (runnable); + + try + { + runnable.wait (); + } + catch (InterruptedException e) + { + EmacsNative.emacsAbort (); + } } return rc.thing; } + + /* Dismiss this context menu. WINDOW is the window where the + context menu is being displayed. */ + + public void + dismiss (final EmacsWindow window) + { + Runnable runnable; + + EmacsService.SERVICE.runOnUiThread (new Runnable () { + @Override + public void + run () + { + window.view.cancelPopupMenu (); + itemAlreadySelected = false; + } + }); + } }; diff --git a/java/org/gnu/emacs/EmacsNative.java b/java/org/gnu/emacs/EmacsNative.java index a11e509cd7f..4a80f88edcf 100644 --- a/java/org/gnu/emacs/EmacsNative.java +++ b/java/org/gnu/emacs/EmacsNative.java @@ -124,6 +124,9 @@ public class EmacsNative /* Send an ANDROID_DEICONIFIED event. */ public static native void sendDeiconified (short window); + /* Send an ANDROID_CONTEXT_MENU event. */ + public static native void sendContextMenu (short window, int menuEventID); + static { System.loadLibrary ("emacs"); diff --git a/java/org/gnu/emacs/EmacsView.java b/java/org/gnu/emacs/EmacsView.java index 1391f630be0..445d8ffa023 100644 --- a/java/org/gnu/emacs/EmacsView.java +++ b/java/org/gnu/emacs/EmacsView.java @@ -453,6 +453,7 @@ public class EmacsView extends ViewGroup return false; contextMenu = menu; + popupActive = true; /* On API 21 or later, use showContextMenu (float, float). */ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) @@ -469,5 +470,6 @@ public class EmacsView extends ViewGroup + " popupActive set"); contextMenu = null; + popupActive = false; } }; -- cgit v1.2.1