aboutsummaryrefslogtreecommitdiffstats
path: root/src/androidmenu.c
diff options
context:
space:
mode:
authorPo Lu2023-01-15 11:57:10 +0800
committerPo Lu2023-01-15 11:57:10 +0800
commit6e2bc91d924fbeb0ad5728e0424eabc905c0d366 (patch)
treef2835948a308d9d0898b9ef868893560048f6812 /src/androidmenu.c
parentc02a7b2ff48746fab891db16f58ccdc11d161745 (diff)
downloademacs-6e2bc91d924fbeb0ad5728e0424eabc905c0d366.tar.gz
emacs-6e2bc91d924fbeb0ad5728e0424eabc905c0d366.zip
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.
Diffstat (limited to 'src/androidmenu.c')
-rw-r--r--src/androidmenu.c114
1 files changed, 108 insertions, 6 deletions
diff --git a/src/androidmenu.c b/src/androidmenu.c
index 0f0c6f4ef1f..7522f9c5a52 100644
--- a/src/androidmenu.c
+++ b/src/androidmenu.c
@@ -54,6 +54,7 @@ struct android_emacs_context_menu
54 jmethodID add_pane; 54 jmethodID add_pane;
55 jmethodID parent; 55 jmethodID parent;
56 jmethodID display; 56 jmethodID display;
57 jmethodID dismiss;
57}; 58};
58 59
59/* Identifiers associated with the EmacsContextMenu class. */ 60/* Identifiers associated with the EmacsContextMenu class. */
@@ -101,6 +102,7 @@ android_init_emacs_context_menu (void)
101 FIND_METHOD (add_pane, "addPane", "(Ljava/lang/String;)V"); 102 FIND_METHOD (add_pane, "addPane", "(Ljava/lang/String;)V");
102 FIND_METHOD (parent, "parent", "()Lorg/gnu/emacs/EmacsContextMenu;"); 103 FIND_METHOD (parent, "parent", "()Lorg/gnu/emacs/EmacsContextMenu;");
103 FIND_METHOD (display, "display", "(Lorg/gnu/emacs/EmacsWindow;II)Z"); 104 FIND_METHOD (display, "display", "(Lorg/gnu/emacs/EmacsWindow;II)Z");
105 FIND_METHOD (dismiss, "dismiss", "(Lorg/gnu/emacs/EmacsWindow;)V");
104 106
105#undef FIND_METHOD 107#undef FIND_METHOD
106#undef FIND_METHOD_STATIC 108#undef FIND_METHOD_STATIC
@@ -130,6 +132,62 @@ android_push_local_frame (void)
130 record_unwind_protect_void (android_unwind_local_frame); 132 record_unwind_protect_void (android_unwind_local_frame);
131} 133}
132 134
135/* Data for android_dismiss_menu. */
136
137struct android_dismiss_menu_data
138{
139 /* The menu object. */
140 jobject menu;
141
142 /* The window object. */
143 jobject window;
144};
145
146/* Cancel the context menu passed in POINTER. Also, clear
147 popup_activated_flag. */
148
149static void
150android_dismiss_menu (void *pointer)
151{
152 struct android_dismiss_menu_data *data;
153
154 data = pointer;
155 (*android_java_env)->CallVoidMethod (android_java_env,
156 data->menu,
157 menu_class.dismiss,
158 data->window);
159 popup_activated_flag = 0;
160}
161
162/* Recursively process events until a ANDROID_CONTEXT_MENU event
163 arrives. Then, return the item ID specified in the event in
164 *ID. */
165
166static void
167android_process_events_for_menu (int *id)
168{
169 /* Set menu_event_id to -1; handle_one_android_event will set it to
170 the event ID upon receiving a context menu event. This can cause
171 a non-local exit. */
172 x_display_list->menu_event_id = -1;
173
174 /* Now wait for the menu event ID to change. */
175 while (x_display_list->menu_event_id == -1)
176 {
177 /* Wait for events to become available. */
178 android_wait_event ();
179
180 /* Process pending signals. */
181 process_pending_signals ();
182
183 /* Maybe quit. */
184 maybe_quit ();
185 }
186
187 /* Return the ID. */
188 *id = x_display_list->menu_event_id;
189}
190
133Lisp_Object 191Lisp_Object
134android_menu_show (struct frame *f, int x, int y, int menuflags, 192android_menu_show (struct frame *f, int x, int y, int menuflags,
135 Lisp_Object title, const char **error_name) 193 Lisp_Object title, const char **error_name)
@@ -140,11 +198,13 @@ android_menu_show (struct frame *f, int x, int y, int menuflags,
140 Lisp_Object pane_name, prefix; 198 Lisp_Object pane_name, prefix;
141 const char *pane_string; 199 const char *pane_string;
142 specpdl_ref count, count1; 200 specpdl_ref count, count1;
143 Lisp_Object item_name, enable, def; 201 Lisp_Object item_name, enable, def, tem;
144 jmethodID method; 202 jmethodID method;
145 jobject store; 203 jobject store;
146 bool rc; 204 bool rc;
147 jobject window; 205 jobject window;
206 int id, item_id;
207 struct android_dismiss_menu_data data;
148 208
149 count = SPECPDL_INDEX (); 209 count = SPECPDL_INDEX ();
150 210
@@ -266,6 +326,12 @@ android_menu_show (struct frame *f, int x, int y, int menuflags,
266 ; 326 ;
267 else 327 else
268 { 328 {
329 /* Compute the item ID. This is the index of value.
330 Make sure it doesn't overflow. */
331
332 if (!INT_ADD_OK (0, i + MENU_ITEMS_ITEM_VALUE, &item_id))
333 memory_full (i + MENU_ITEMS_ITEM_VALUE * sizeof (Lisp_Object));
334
269 /* Add this menu item with the appropriate state. */ 335 /* Add this menu item with the appropriate state. */
270 336
271 title_string = (!NILP (item_name) 337 title_string = (!NILP (item_name)
@@ -274,7 +340,7 @@ android_menu_show (struct frame *f, int x, int y, int menuflags,
274 (*android_java_env)->CallVoidMethod (android_java_env, 340 (*android_java_env)->CallVoidMethod (android_java_env,
275 current_context_menu, 341 current_context_menu,
276 menu_class.add_item, 342 menu_class.add_item,
277 (jint) 1, 343 (jint) item_id,
278 title_string, 344 title_string,
279 (jboolean) !NILP (enable)); 345 (jboolean) !NILP (enable));
280 android_exception_check (); 346 android_exception_check ();
@@ -295,6 +361,7 @@ android_menu_show (struct frame *f, int x, int y, int menuflags,
295 ANDROID_HANDLE_WINDOW); 361 ANDROID_HANDLE_WINDOW);
296 rc = (*android_java_env)->CallBooleanMethod (android_java_env, 362 rc = (*android_java_env)->CallBooleanMethod (android_java_env,
297 context_menu, 363 context_menu,
364 menu_class.display,
298 window, (jint) x, 365 window, (jint) x,
299 (jint) y); 366 (jint) y);
300 android_exception_check (); 367 android_exception_check ();
@@ -303,25 +370,54 @@ android_menu_show (struct frame *f, int x, int y, int menuflags,
303 /* This means displaying the menu failed. */ 370 /* This means displaying the menu failed. */
304 goto finish; 371 goto finish;
305 372
306#if 0 373 /* Make sure the context menu is always dismissed. */
307 record_unwind_protect_ptr (android_dismiss_menu, &context_menu); 374 data.menu = context_menu;
375 data.window = window;
376 record_unwind_protect_ptr (android_dismiss_menu, &data);
308 377
309 /* Otherwise, loop waiting for the menu event to arrive. */ 378 /* Next, process events waiting for something to be selected. */
379 popup_activated_flag = 1;
380 unblock_input ();
310 android_process_events_for_menu (&id); 381 android_process_events_for_menu (&id);
382 block_input ();
311 383
312 if (!id) 384 if (!id)
313 /* This means no menu item was selected. */ 385 /* This means no menu item was selected. */
314 goto finish; 386 goto finish;
315 387
316#endif 388 /* id is an index into menu_items. Check that it remains
389 valid. */
390 if (id >= ASIZE (menu_items))
391 goto finish;
392
393 /* Now return the menu item at that location. */
394 tem = AREF (menu_items, id);
395 unblock_input ();
396 return unbind_to (count, tem);
317 397
318 finish: 398 finish:
319 unblock_input (); 399 unblock_input ();
320 return unbind_to (count, Qnil); 400 return unbind_to (count, Qnil);
321} 401}
322 402
403#else
404
405int
406popup_activated (void)
407{
408 return 0;
409}
410
323#endif 411#endif
324 412
413DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p,
414 Smenu_or_popup_active_p, 0, 0, 0,
415 doc: /* SKIP: real doc in xfns.c. */)
416 (void)
417{
418 return (popup_activated ()) ? Qt : Qnil;
419}
420
325void 421void
326init_androidmenu (void) 422init_androidmenu (void)
327{ 423{
@@ -329,3 +425,9 @@ init_androidmenu (void)
329 android_init_emacs_context_menu (); 425 android_init_emacs_context_menu ();
330#endif 426#endif
331} 427}
428
429void
430syms_of_androidmenu (void)
431{
432 defsubr (&Smenu_or_popup_active_p);
433}