aboutsummaryrefslogtreecommitdiffstats
path: root/src/android.c
diff options
context:
space:
mode:
authorPo Lu2023-01-14 22:12:16 +0800
committerPo Lu2023-01-14 22:12:16 +0800
commit2b87ab7b27163fbd7b6b64c5a44e26b0e692c00a (patch)
tree3ab31df90bd435009d2d42b636ce3baf33bd2b28 /src/android.c
parent28a9baccd4c8e997895d3adb3cfce4a11fa29896 (diff)
downloademacs-2b87ab7b27163fbd7b6b64c5a44e26b0e692c00a.tar.gz
emacs-2b87ab7b27163fbd7b6b64c5a44e26b0e692c00a.zip
Update Android port
* java/Makefile.in (clean): Fix distclean and bootstrap-clean rules. * java/debug.sh (jdb_port): (attach_existing): (num_pids): (line): Add new options to upload a gdbserver binary to the device. * java/org/gnu/emacs/EmacsActivity.java (EmacsActivity): Make focusedActivities public. * java/org/gnu/emacs/EmacsContextMenu.java (EmacsContextMenu): New class. * java/org/gnu/emacs/EmacsDrawRectangle.java (perform): Fix bounds computation. * java/org/gnu/emacs/EmacsGC.java (markDirty): Set stroke width explicitly. * java/org/gnu/emacs/EmacsService.java (EmacsService) (getLocationOnScreen, nameKeysym): New functions. * java/org/gnu/emacs/EmacsView.java (EmacsView): Disable focus highlight. (onCreateContextMenu, popupMenu, cancelPopupMenu): New functions. * java/org/gnu/emacs/EmacsWindow.java (EmacsWindow): Implement a kind of ``override redirect'' window for tooltips. * src/android.c (struct android_emacs_service): New method `name_keysym'. (android_run_select_thread, android_init_events): (android_select): Release select thread on semaphores instead of signals to avoid one nasty race on SIGUSR2 delivery. (android_init_emacs_service): Initialize new method. (android_create_window): Handle CW_OVERRIDE_REDIRECT. (android_move_resize_window, android_map_raised) (android_translate_coordinates, android_get_keysym_name) (android_build_string, android_exception_check): New functions. * src/android.h: Update prototypes. * src/androidfns.c (android_set_parent_frame, Fx_create_frame) (unwind_create_tip_frame, android_create_tip_frame) (android_hide_tip, compute_tip_xy, Fx_show_tip, Fx_hide_tip) (syms_of_androidfns): Implement tooltips and iconification reporting. * src/androidgui.h (enum android_window_value_mask): Add CWOverrideRedirect. (struct android_set_window_attributes): Add `override_redirect'. (ANDROID_IS_MODIFIER_KEY): Recognize Caps Lock. * src/androidmenu.c (struct android_emacs_context_menu): New struct. (android_init_emacs_context_menu, android_unwind_local_frame) (android_push_local_frame, android_menu_show, init_androidmenu): New functions. * src/androidterm.c (handle_one_android_event): Fix NULL pointer dereference. (android_fullscreen_hook): Handle fullscreen correctly. (android_draw_box_rect): Fix top line. (get_keysym_name): Implement function. (android_create_terminal): Remove scroll bar stubs and add menu hook. * src/androidterm.h: Update prototypes. * src/emacs.c (android_emacs_init): Initialize androidmenu.c. * xcompile/Makefile.in: Fix clean rules.
Diffstat (limited to 'src/android.c')
-rw-r--r--src/android.c169
1 files changed, 148 insertions, 21 deletions
diff --git a/src/android.c b/src/android.c
index fba43129ee3..e4022501f9d 100644
--- a/src/android.c
+++ b/src/android.c
@@ -87,6 +87,7 @@ struct android_emacs_service
87 jmethodID get_screen_width; 87 jmethodID get_screen_width;
88 jmethodID get_screen_height; 88 jmethodID get_screen_height;
89 jmethodID detect_mouse; 89 jmethodID detect_mouse;
90 jmethodID name_keysym;
90}; 91};
91 92
92struct android_emacs_pixmap 93struct android_emacs_pixmap
@@ -229,14 +230,14 @@ static volatile bool android_pselect_completed;
229/* The global event queue. */ 230/* The global event queue. */
230static struct android_event_queue event_queue; 231static struct android_event_queue event_queue;
231 232
232/* Semaphore used to signal select completion. */ 233/* Semaphores used to signal select completion and start. */
233static sem_t android_pselect_sem; 234static sem_t android_pselect_sem, android_pselect_start_sem;
234 235
235static void * 236static void *
236android_run_select_thread (void *data) 237android_run_select_thread (void *data)
237{ 238{
238 sigset_t signals; 239 sigset_t signals;
239 int sig, rc; 240 int rc;
240 241
241 sigfillset (&signals); 242 sigfillset (&signals);
242 243
@@ -245,23 +246,10 @@ android_run_select_thread (void *data)
245 "pthread_sigmask: %s", 246 "pthread_sigmask: %s",
246 strerror (errno)); 247 strerror (errno));
247 248
248 sigemptyset (&signals);
249 sigaddset (&signals, SIGUSR1);
250
251 if (pthread_sigmask (SIG_UNBLOCK, &signals, NULL))
252 __android_log_print (ANDROID_LOG_FATAL, __func__,
253 "pthread_sigmask: %s",
254 strerror (errno));
255
256 sigemptyset (&signals);
257 sigaddset (&signals, SIGUSR2);
258
259 while (true) 249 while (true)
260 { 250 {
261 /* Keep waiting for SIGUSR2, ignoring EINTR in the meantime. */ 251 /* Wait for the thread to be released. */
262 252 sem_wait (&android_pselect_start_sem);
263 while (sigwait (&signals, &sig))
264 /* Spin. */;
265 253
266 /* Get the select lock and call pselect. */ 254 /* Get the select lock and call pselect. */
267 pthread_mutex_lock (&event_queue.select_mutex); 255 pthread_mutex_lock (&event_queue.select_mutex);
@@ -322,6 +310,7 @@ android_init_events (void)
322 strerror (errno)); 310 strerror (errno));
323 311
324 sem_init (&android_pselect_sem, 0, 0); 312 sem_init (&android_pselect_sem, 0, 0);
313 sem_init (&android_pselect_start_sem, 0, 0);
325 314
326 event_queue.events.next = &event_queue.events; 315 event_queue.events.next = &event_queue.events;
327 event_queue.events.last = &event_queue.events; 316 event_queue.events.last = &event_queue.events;
@@ -444,7 +433,9 @@ android_select (int nfds, fd_set *readfds, fd_set *writefds,
444 android_pselect_sigset = sigset; 433 android_pselect_sigset = sigset;
445 pthread_mutex_unlock (&event_queue.select_mutex); 434 pthread_mutex_unlock (&event_queue.select_mutex);
446 435
447 pthread_kill (event_queue.select_thread, SIGUSR2); 436 /* Release the select thread. */
437 sem_post (&android_pselect_start_sem);
438
448 pthread_cond_wait (&event_queue.read_var, &event_queue.mutex); 439 pthread_cond_wait (&event_queue.read_var, &event_queue.mutex);
449 440
450 /* Interrupt the select thread now, in case it's still in 441 /* Interrupt the select thread now, in case it's still in
@@ -1058,6 +1049,7 @@ android_init_emacs_service (void)
1058 FIND_METHOD (get_screen_width, "getScreenWidth", "(Z)I"); 1049 FIND_METHOD (get_screen_width, "getScreenWidth", "(Z)I");
1059 FIND_METHOD (get_screen_height, "getScreenHeight", "(Z)I"); 1050 FIND_METHOD (get_screen_height, "getScreenHeight", "(Z)I");
1060 FIND_METHOD (detect_mouse, "detectMouse", "()Z"); 1051 FIND_METHOD (detect_mouse, "detectMouse", "()Z");
1052 FIND_METHOD (name_keysym, "nameKeysym", "(I)Ljava/lang/String;");
1061#undef FIND_METHOD 1053#undef FIND_METHOD
1062} 1054}
1063 1055
@@ -1678,6 +1670,7 @@ android_create_window (android_window parent, int x, int y,
1678 jobject object, parent_object, old; 1670 jobject object, parent_object, old;
1679 android_window window; 1671 android_window window;
1680 android_handle prev_max_handle; 1672 android_handle prev_max_handle;
1673 bool override_redirect;
1681 1674
1682 parent_object = android_resolve_handle (parent, ANDROID_HANDLE_WINDOW); 1675 parent_object = android_resolve_handle (parent, ANDROID_HANDLE_WINDOW);
1683 1676
@@ -1695,7 +1688,8 @@ android_create_window (android_window parent, int x, int y,
1695 1688
1696 constructor 1689 constructor
1697 = (*android_java_env)->GetMethodID (android_java_env, class, "<init>", 1690 = (*android_java_env)->GetMethodID (android_java_env, class, "<init>",
1698 "(SLorg/gnu/emacs/EmacsWindow;IIII)V"); 1691 "(SLorg/gnu/emacs/EmacsWindow;"
1692 "IIIIZ)V");
1699 assert (constructor != NULL); 1693 assert (constructor != NULL);
1700 1694
1701 old = class; 1695 old = class;
@@ -1707,10 +1701,17 @@ android_create_window (android_window parent, int x, int y,
1707 memory_full (0); 1701 memory_full (0);
1708 } 1702 }
1709 1703
1704 /* N.B. that ANDROID_CW_OVERRIDE_REDIRECT can only be set at window
1705 creation time. */
1706 override_redirect = ((value_mask
1707 & ANDROID_CW_OVERRIDE_REDIRECT)
1708 && attrs->override_redirect);
1709
1710 object = (*android_java_env)->NewObject (android_java_env, class, 1710 object = (*android_java_env)->NewObject (android_java_env, class,
1711 constructor, (jshort) window, 1711 constructor, (jshort) window,
1712 parent_object, (jint) x, (jint) y, 1712 parent_object, (jint) x, (jint) y,
1713 (jint) width, (jint) height); 1713 (jint) width, (jint) height,
1714 (jboolean) override_redirect);
1714 if (!object) 1715 if (!object)
1715 { 1716 {
1716 (*android_java_env)->ExceptionClear (android_java_env); 1717 (*android_java_env)->ExceptionClear (android_java_env);
@@ -3212,6 +3213,66 @@ android_get_geometry (android_window handle,
3212 ANDROID_DELETE_LOCAL_REF (window_geometry); 3213 ANDROID_DELETE_LOCAL_REF (window_geometry);
3213} 3214}
3214 3215
3216void
3217android_move_resize_window (android_window window, int x, int y,
3218 unsigned int width, unsigned int height)
3219{
3220 android_move_window (window, x, y);
3221 android_resize_window (window, width, height);
3222}
3223
3224void
3225android_map_raised (android_window window)
3226{
3227 android_raise_window (window);
3228 android_map_window (window);
3229}
3230
3231void
3232android_translate_coordinates (android_window src, int x,
3233 int y, int *root_x, int *root_y)
3234{
3235 jobject window;
3236 jarray coordinates;
3237 jmethodID method;
3238 jint *ints;
3239
3240 window = android_resolve_handle (src, ANDROID_HANDLE_WINDOW);
3241 method = android_lookup_method ("org/gnu/emacs/EmacsWindow",
3242 "translateCoordinates",
3243 "(II)[I");
3244 coordinates
3245 = (*android_java_env)->CallObjectMethod (android_java_env,
3246 window, method,
3247 (jint) x, (jint) y);
3248
3249 if (!coordinates)
3250 {
3251 (*android_java_env)->ExceptionClear (android_java_env);
3252 memory_full (0);
3253 }
3254
3255 /* The array must contain two elements: X, Y translated to the root
3256 window. */
3257 eassert ((*android_java_env)->GetArrayLength (android_java_env,
3258 coordinates)
3259 == 2);
3260
3261 /* Obtain the coordinates from the array. */
3262 ints = (*android_java_env)->GetIntArrayElements (android_java_env,
3263 coordinates, NULL);
3264 *root_x = ints[0];
3265 *root_y = ints[1];
3266
3267 /* Release the coordinates. */
3268 (*android_java_env)->ReleaseIntArrayElements (android_java_env,
3269 coordinates, ints,
3270 JNI_ABORT);
3271
3272 /* And free the local reference. */
3273 ANDROID_DELETE_LOCAL_REF (coordinates);
3274}
3275
3215 3276
3216 3277
3217/* Low level drawing primitives. */ 3278/* Low level drawing primitives. */
@@ -3384,6 +3445,30 @@ android_set_dont_accept_focus (android_window handle,
3384 (jboolean) no_accept_focus); 3445 (jboolean) no_accept_focus);
3385} 3446}
3386 3447
3448void
3449android_get_keysym_name (int keysym, char *name_return, size_t size)
3450{
3451 jobject string;
3452 const char *buffer;
3453
3454 string = (*android_java_env)->CallObjectMethod (android_java_env,
3455 emacs_service,
3456 service_class.name_keysym,
3457 (jint) keysym);
3458 android_exception_check ();
3459
3460 buffer = (*android_java_env)->GetStringUTFChars (android_java_env,
3461 (jstring) string,
3462 NULL);
3463 android_exception_check ();
3464 strncpy (name_return, buffer, size - 1);
3465
3466 (*android_java_env)->ReleaseStringUTFChars (android_java_env,
3467 (jstring) string,
3468 buffer);
3469 ANDROID_DELETE_LOCAL_REF (string);
3470}
3471
3387 3472
3388 3473
3389#undef faccessat 3474#undef faccessat
@@ -3525,6 +3610,48 @@ emacs_abort (void)
3525 abort (); 3610 abort ();
3526} 3611}
3527 3612
3613
3614
3615/* Given a Lisp string TEXT, return a local reference to an equivalent
3616 Java string. */
3617
3618jstring
3619android_build_string (Lisp_Object text)
3620{
3621 Lisp_Object encoded;
3622 jstring string;
3623
3624 encoded = ENCODE_UTF_8 (text);
3625
3626 /* Note that Java expects this string to be in ``modified UTF
3627 encoding'', which is actually UTF-8, except with NUL encoded as a
3628 two-byte sequence. The only consequence of passing an actual
3629 UTF-8 string is that NUL bytes cannot be represented, which is
3630 not really of consequence. */
3631 string = (*android_java_env)->NewStringUTF (android_java_env,
3632 SSDATA (encoded));
3633 if (!string)
3634 {
3635 (*android_java_env)->ExceptionClear (android_java_env);
3636 memory_full (0);
3637 }
3638
3639 return string;
3640}
3641
3642/* Check for JNI exceptions and call memory_full in that
3643 situation. */
3644
3645void
3646android_exception_check (void)
3647{
3648 if ((*android_java_env)->ExceptionCheck (android_java_env))
3649 {
3650 (*android_java_env)->ExceptionClear (android_java_env);
3651 memory_full (0);
3652 }
3653}
3654
3528#else /* ANDROID_STUBIFY */ 3655#else /* ANDROID_STUBIFY */
3529 3656
3530/* X emulation functions for Android. */ 3657/* X emulation functions for Android. */