diff options
| author | Po Lu | 2023-03-09 16:30:02 +0800 |
|---|---|---|
| committer | Po Lu | 2023-03-09 16:30:02 +0800 |
| commit | e859a14bee7a84a3aaed45770c89ef60c68b3e08 (patch) | |
| tree | 5f875640bc70b3726ad1a3d2f41732ecc54fbcdf /java/org | |
| parent | 745890de5204850bb4173c19ceb79c698acb7a20 (diff) | |
| download | emacs-e859a14bee7a84a3aaed45770c89ef60c68b3e08.tar.gz emacs-e859a14bee7a84a3aaed45770c89ef60c68b3e08.zip | |
Fix menu and popup race conditions on Android
* java/org/gnu/emacs/EmacsActivity.java (onContextMenuClosed):
* java/org/gnu/emacs/EmacsContextMenu.java (EmacsContextMenu)
(onMenuItemClick, run):
* java/org/gnu/emacs/EmacsDialog.java (EmacsDialog, onClick)
(createDialog, onDismiss): Take menu event serial, and pass it
along in context menu events.
* java/org/gnu/emacs/EmacsNative.java (sendContextMenu): New
argument.
* src/android.c (sendContextMenu): Pass serial number in event.
* src/androidgui.h (struct android_menu_event): New field
`menu_event_serial'.
* src/androidmenu.c (FIND_METHOD_STATIC)
(android_init_emacs_context_menu): Adjust method declarations.
(android_menu_show, android_dialog_show):
* src/androidterm.c (handle_one_android_event): Expect serial in
context menu events.
* src/androidterm.h: Update prototypes.
Diffstat (limited to 'java/org')
| -rw-r--r-- | java/org/gnu/emacs/EmacsActivity.java | 8 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsContextMenu.java | 14 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsDialog.java | 15 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsNative.java | 3 |
4 files changed, 29 insertions, 11 deletions
diff --git a/java/org/gnu/emacs/EmacsActivity.java b/java/org/gnu/emacs/EmacsActivity.java index 692d8a14e22..735a464be8e 100644 --- a/java/org/gnu/emacs/EmacsActivity.java +++ b/java/org/gnu/emacs/EmacsActivity.java | |||
| @@ -315,6 +315,8 @@ public class EmacsActivity extends Activity | |||
| 315 | public final void | 315 | public final void |
| 316 | onContextMenuClosed (Menu menu) | 316 | onContextMenuClosed (Menu menu) |
| 317 | { | 317 | { |
| 318 | int serial; | ||
| 319 | |||
| 318 | Log.d (TAG, "onContextMenuClosed: " + menu); | 320 | Log.d (TAG, "onContextMenuClosed: " + menu); |
| 319 | 321 | ||
| 320 | /* See the comment inside onMenuItemClick. */ | 322 | /* See the comment inside onMenuItemClick. */ |
| @@ -335,7 +337,11 @@ public class EmacsActivity extends Activity | |||
| 335 | /* Send a context menu event given that no menu item has already | 337 | /* Send a context menu event given that no menu item has already |
| 336 | been selected. */ | 338 | been selected. */ |
| 337 | if (!EmacsContextMenu.itemAlreadySelected) | 339 | if (!EmacsContextMenu.itemAlreadySelected) |
| 338 | EmacsNative.sendContextMenu ((short) 0, 0); | 340 | { |
| 341 | serial = EmacsContextMenu.lastMenuEventSerial; | ||
| 342 | EmacsNative.sendContextMenu ((short) 0, 0, | ||
| 343 | serial); | ||
| 344 | } | ||
| 339 | 345 | ||
| 340 | super.onContextMenuClosed (menu); | 346 | super.onContextMenuClosed (menu); |
| 341 | } | 347 | } |
diff --git a/java/org/gnu/emacs/EmacsContextMenu.java b/java/org/gnu/emacs/EmacsContextMenu.java index 0553ff9d4a3..abc1869ac6a 100644 --- a/java/org/gnu/emacs/EmacsContextMenu.java +++ b/java/org/gnu/emacs/EmacsContextMenu.java | |||
| @@ -49,6 +49,9 @@ public final class EmacsContextMenu | |||
| 49 | /* Whether or not a submenu was selected. */ | 49 | /* Whether or not a submenu was selected. */ |
| 50 | public static boolean wasSubmenuSelected; | 50 | public static boolean wasSubmenuSelected; |
| 51 | 51 | ||
| 52 | /* The serial ID of the last context menu to be displayed. */ | ||
| 53 | public static int lastMenuEventSerial; | ||
| 54 | |||
| 52 | private static class Item implements MenuItem.OnMenuItemClickListener | 55 | private static class Item implements MenuItem.OnMenuItemClickListener |
| 53 | { | 56 | { |
| 54 | public int itemID; | 57 | public int itemID; |
| @@ -106,7 +109,8 @@ public final class EmacsContextMenu | |||
| 106 | } | 109 | } |
| 107 | 110 | ||
| 108 | /* Send a context menu event. */ | 111 | /* Send a context menu event. */ |
| 109 | EmacsNative.sendContextMenu ((short) 0, itemID); | 112 | EmacsNative.sendContextMenu ((short) 0, itemID, |
| 113 | lastMenuEventSerial); | ||
| 110 | 114 | ||
| 111 | /* Say that an item has already been selected. */ | 115 | /* Say that an item has already been selected. */ |
| 112 | itemAlreadySelected = true; | 116 | itemAlreadySelected = true; |
| @@ -293,12 +297,13 @@ public final class EmacsContextMenu | |||
| 293 | false); | 297 | false); |
| 294 | } | 298 | } |
| 295 | 299 | ||
| 296 | /* Display this context menu on WINDOW, at xPosition and | 300 | /* Display this context menu on WINDOW, at xPosition and yPosition. |
| 297 | yPosition. */ | 301 | SERIAL is a number that will be returned in any menu event |
| 302 | generated to identify this context menu. */ | ||
| 298 | 303 | ||
| 299 | public boolean | 304 | public boolean |
| 300 | display (final EmacsWindow window, final int xPosition, | 305 | display (final EmacsWindow window, final int xPosition, |
| 301 | final int yPosition) | 306 | final int yPosition, final int serial) |
| 302 | { | 307 | { |
| 303 | Runnable runnable; | 308 | Runnable runnable; |
| 304 | final Holder<Boolean> rc; | 309 | final Holder<Boolean> rc; |
| @@ -312,6 +317,7 @@ public final class EmacsContextMenu | |||
| 312 | { | 317 | { |
| 313 | synchronized (this) | 318 | synchronized (this) |
| 314 | { | 319 | { |
| 320 | lastMenuEventSerial = serial; | ||
| 315 | rc.thing = display1 (window, xPosition, yPosition); | 321 | rc.thing = display1 (window, xPosition, yPosition); |
| 316 | notify (); | 322 | notify (); |
| 317 | } | 323 | } |
diff --git a/java/org/gnu/emacs/EmacsDialog.java b/java/org/gnu/emacs/EmacsDialog.java index 80a5e5f7369..aed84de29e5 100644 --- a/java/org/gnu/emacs/EmacsDialog.java +++ b/java/org/gnu/emacs/EmacsDialog.java | |||
| @@ -57,6 +57,9 @@ public final class EmacsDialog implements DialogInterface.OnDismissListener | |||
| 57 | /* Dialog to dismiss after click. */ | 57 | /* Dialog to dismiss after click. */ |
| 58 | private AlertDialog dismissDialog; | 58 | private AlertDialog dismissDialog; |
| 59 | 59 | ||
| 60 | /* The menu serial associated with this dialog box. */ | ||
| 61 | private int menuEventSerial; | ||
| 62 | |||
| 60 | private class EmacsButton implements View.OnClickListener, | 63 | private class EmacsButton implements View.OnClickListener, |
| 61 | DialogInterface.OnClickListener | 64 | DialogInterface.OnClickListener |
| 62 | { | 65 | { |
| @@ -76,7 +79,7 @@ public final class EmacsDialog implements DialogInterface.OnDismissListener | |||
| 76 | Log.d (TAG, "onClicked " + this); | 79 | Log.d (TAG, "onClicked " + this); |
| 77 | 80 | ||
| 78 | wasButtonClicked = true; | 81 | wasButtonClicked = true; |
| 79 | EmacsNative.sendContextMenu ((short) 0, id); | 82 | EmacsNative.sendContextMenu ((short) 0, id, menuEventSerial); |
| 80 | dismissDialog.dismiss (); | 83 | dismissDialog.dismiss (); |
| 81 | } | 84 | } |
| 82 | 85 | ||
| @@ -87,15 +90,16 @@ public final class EmacsDialog implements DialogInterface.OnDismissListener | |||
| 87 | Log.d (TAG, "onClicked " + this); | 90 | Log.d (TAG, "onClicked " + this); |
| 88 | 91 | ||
| 89 | wasButtonClicked = true; | 92 | wasButtonClicked = true; |
| 90 | EmacsNative.sendContextMenu ((short) 0, id); | 93 | EmacsNative.sendContextMenu ((short) 0, id, menuEventSerial); |
| 91 | } | 94 | } |
| 92 | }; | 95 | }; |
| 93 | 96 | ||
| 94 | /* Create a popup dialog with the title TITLE and the text TEXT. | 97 | /* Create a popup dialog with the title TITLE and the text TEXT. |
| 95 | TITLE may be NULL. */ | 98 | TITLE may be NULL. MENUEVENTSERIAL is a number which will |
| 99 | identify this popup dialog inside events it sends. */ | ||
| 96 | 100 | ||
| 97 | public static EmacsDialog | 101 | public static EmacsDialog |
| 98 | createDialog (String title, String text) | 102 | createDialog (String title, String text, int menuEventSerial) |
| 99 | { | 103 | { |
| 100 | EmacsDialog dialog; | 104 | EmacsDialog dialog; |
| 101 | 105 | ||
| @@ -103,6 +107,7 @@ public final class EmacsDialog implements DialogInterface.OnDismissListener | |||
| 103 | dialog.buttons = new ArrayList<EmacsButton> (); | 107 | dialog.buttons = new ArrayList<EmacsButton> (); |
| 104 | dialog.title = title; | 108 | dialog.title = title; |
| 105 | dialog.text = text; | 109 | dialog.text = text; |
| 110 | dialog.menuEventSerial = menuEventSerial; | ||
| 106 | 111 | ||
| 107 | return dialog; | 112 | return dialog; |
| 108 | } | 113 | } |
| @@ -330,6 +335,6 @@ public final class EmacsDialog implements DialogInterface.OnDismissListener | |||
| 330 | if (wasButtonClicked) | 335 | if (wasButtonClicked) |
| 331 | return; | 336 | return; |
| 332 | 337 | ||
| 333 | EmacsNative.sendContextMenu ((short) 0, 0); | 338 | EmacsNative.sendContextMenu ((short) 0, 0, menuEventSerial); |
| 334 | } | 339 | } |
| 335 | }; | 340 | }; |
diff --git a/java/org/gnu/emacs/EmacsNative.java b/java/org/gnu/emacs/EmacsNative.java index 8e626b9534b..11da5db8746 100644 --- a/java/org/gnu/emacs/EmacsNative.java +++ b/java/org/gnu/emacs/EmacsNative.java | |||
| @@ -155,7 +155,8 @@ public final class EmacsNative | |||
| 155 | public static native long sendDeiconified (short window); | 155 | public static native long sendDeiconified (short window); |
| 156 | 156 | ||
| 157 | /* Send an ANDROID_CONTEXT_MENU event. */ | 157 | /* Send an ANDROID_CONTEXT_MENU event. */ |
| 158 | public static native long sendContextMenu (short window, int menuEventID); | 158 | public static native long sendContextMenu (short window, int menuEventID, |
| 159 | int menuEventSerial); | ||
| 159 | 160 | ||
| 160 | /* Send an ANDROID_EXPOSE event. */ | 161 | /* Send an ANDROID_EXPOSE event. */ |
| 161 | public static native long sendExpose (short window, int x, int y, | 162 | public static native long sendExpose (short window, int x, int y, |