diff options
Diffstat (limited to 'src/android.c')
| -rw-r--r-- | src/android.c | 81 |
1 files changed, 63 insertions, 18 deletions
diff --git a/src/android.c b/src/android.c index 4a74f5b2af4..41481afa475 100644 --- a/src/android.c +++ b/src/android.c | |||
| @@ -40,6 +40,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 40 | 40 | ||
| 41 | #include <sys/param.h> | 41 | #include <sys/param.h> |
| 42 | #include <sys/stat.h> | 42 | #include <sys/stat.h> |
| 43 | #include <sys/select.h> | ||
| 43 | 44 | ||
| 44 | /* Old NDK versions lack MIN and MAX. */ | 45 | /* Old NDK versions lack MIN and MAX. */ |
| 45 | #include <minmax.h> | 46 | #include <minmax.h> |
| @@ -112,6 +113,8 @@ struct android_emacs_window | |||
| 112 | jmethodID define_cursor; | 113 | jmethodID define_cursor; |
| 113 | jmethodID damage_rect; | 114 | jmethodID damage_rect; |
| 114 | jmethodID recreate_activity; | 115 | jmethodID recreate_activity; |
| 116 | jmethodID clear_window; | ||
| 117 | jmethodID clear_area; | ||
| 115 | }; | 118 | }; |
| 116 | 119 | ||
| 117 | struct android_emacs_cursor | 120 | struct android_emacs_cursor |
| @@ -152,6 +155,13 @@ static char *android_files_dir; | |||
| 152 | /* The Java environment being used for the main thread. */ | 155 | /* The Java environment being used for the main thread. */ |
| 153 | JNIEnv *android_java_env; | 156 | JNIEnv *android_java_env; |
| 154 | 157 | ||
| 158 | #ifdef THREADS_ENABLED | ||
| 159 | |||
| 160 | /* The Java VM new threads attach to. */ | ||
| 161 | JavaVM *android_jvm; | ||
| 162 | |||
| 163 | #endif /* THREADS_ENABLED */ | ||
| 164 | |||
| 155 | /* The EmacsGC class. */ | 165 | /* The EmacsGC class. */ |
| 156 | static jclass emacs_gc_class; | 166 | static jclass emacs_gc_class; |
| 157 | 167 | ||
| @@ -496,6 +506,9 @@ android_handle_sigusr1 (int sig, siginfo_t *siginfo, void *arg) | |||
| 496 | This should ideally be defined further down. */ | 506 | This should ideally be defined further down. */ |
| 497 | static sem_t android_query_sem; | 507 | static sem_t android_query_sem; |
| 498 | 508 | ||
| 509 | /* ID of the Emacs thread. */ | ||
| 510 | static pthread_t main_thread_id; | ||
| 511 | |||
| 499 | /* Set up the global event queue by initializing the mutex and two | 512 | /* Set up the global event queue by initializing the mutex and two |
| 500 | condition variables, and the linked list of events. This must be | 513 | condition variables, and the linked list of events. This must be |
| 501 | called before starting the Emacs thread. Also, initialize the | 514 | called before starting the Emacs thread. Also, initialize the |
| @@ -531,6 +544,8 @@ android_init_events (void) | |||
| 531 | event_queue.events.next = &event_queue.events; | 544 | event_queue.events.next = &event_queue.events; |
| 532 | event_queue.events.last = &event_queue.events; | 545 | event_queue.events.last = &event_queue.events; |
| 533 | 546 | ||
| 547 | main_thread_id = pthread_self (); | ||
| 548 | |||
| 534 | #if __ANDROID_API__ >= 16 | 549 | #if __ANDROID_API__ >= 16 |
| 535 | 550 | ||
| 536 | /* Before starting the select thread, make sure the disposition for | 551 | /* Before starting the select thread, make sure the disposition for |
| @@ -579,10 +594,6 @@ android_pending (void) | |||
| 579 | return i; | 594 | return i; |
| 580 | } | 595 | } |
| 581 | 596 | ||
| 582 | /* Forward declaration. */ | ||
| 583 | |||
| 584 | static void android_check_query (void); | ||
| 585 | |||
| 586 | /* Wait for events to become available synchronously. Return once an | 597 | /* Wait for events to become available synchronously. Return once an |
| 587 | event arrives. Also, reply to the UI thread whenever it requires a | 598 | event arrives. Also, reply to the UI thread whenever it requires a |
| 588 | response. */ | 599 | response. */ |
| @@ -732,6 +743,12 @@ android_select (int nfds, fd_set *readfds, fd_set *writefds, | |||
| 732 | static char byte; | 743 | static char byte; |
| 733 | #endif | 744 | #endif |
| 734 | 745 | ||
| 746 | #ifdef THREADS_ENABLED | ||
| 747 | if (!pthread_equal (pthread_self (), main_thread_id)) | ||
| 748 | return pselect (nfds, readfds, writefds, exceptfds, timeout, | ||
| 749 | NULL); | ||
| 750 | #endif /* THREADS_ENABLED */ | ||
| 751 | |||
| 735 | /* Since Emacs is reading keyboard input again, signify that queries | 752 | /* Since Emacs is reading keyboard input again, signify that queries |
| 736 | from input methods are no longer ``urgent''. */ | 753 | from input methods are no longer ``urgent''. */ |
| 737 | 754 | ||
| @@ -837,9 +854,11 @@ android_select (int nfds, fd_set *readfds, fd_set *writefds, | |||
| 837 | if (nfds_return < 0) | 854 | if (nfds_return < 0) |
| 838 | errno = EINTR; | 855 | errno = EINTR; |
| 839 | 856 | ||
| 857 | #ifndef THREADS_ENABLED | ||
| 840 | /* Now check for and run anything the UI thread wants to run in the | 858 | /* Now check for and run anything the UI thread wants to run in the |
| 841 | main thread. */ | 859 | main thread. */ |
| 842 | android_check_query (); | 860 | android_check_query (); |
| 861 | #endif /* THREADS_ENABLED */ | ||
| 843 | 862 | ||
| 844 | return nfds_return; | 863 | return nfds_return; |
| 845 | } | 864 | } |
| @@ -1315,12 +1334,17 @@ NATIVE_NAME (setEmacsParams) (JNIEnv *env, jobject object, | |||
| 1315 | const char *java_string; | 1334 | const char *java_string; |
| 1316 | struct stat statb; | 1335 | struct stat statb; |
| 1317 | 1336 | ||
| 1337 | #ifdef THREADS_ENABLED | ||
| 1338 | /* Save the Java VM. */ | ||
| 1339 | if ((*env)->GetJavaVM (env, &android_jvm)) | ||
| 1340 | emacs_abort (); | ||
| 1341 | #endif /* THREADS_ENABLED */ | ||
| 1342 | |||
| 1318 | /* Set the Android API level early, as it is used by | 1343 | /* Set the Android API level early, as it is used by |
| 1319 | `android_vfs_init'. */ | 1344 | `android_vfs_init'. */ |
| 1320 | android_api_level = api_level; | 1345 | android_api_level = api_level; |
| 1321 | 1346 | ||
| 1322 | /* This function should only be called from the main thread. */ | 1347 | /* This function should only be called from the main thread. */ |
| 1323 | |||
| 1324 | android_pixel_density_x = pixel_density_x; | 1348 | android_pixel_density_x = pixel_density_x; |
| 1325 | android_pixel_density_y = pixel_density_y; | 1349 | android_pixel_density_y = pixel_density_y; |
| 1326 | android_scaled_pixel_density = scaled_density; | 1350 | android_scaled_pixel_density = scaled_density; |
| @@ -1583,16 +1607,13 @@ android_init_emacs_service (void) | |||
| 1583 | FIND_METHOD (draw_point, "drawPoint", | 1607 | FIND_METHOD (draw_point, "drawPoint", |
| 1584 | "(Lorg/gnu/emacs/EmacsDrawable;" | 1608 | "(Lorg/gnu/emacs/EmacsDrawable;" |
| 1585 | "Lorg/gnu/emacs/EmacsGC;II)V"); | 1609 | "Lorg/gnu/emacs/EmacsGC;II)V"); |
| 1586 | FIND_METHOD (clear_window, "clearWindow", | ||
| 1587 | "(Lorg/gnu/emacs/EmacsWindow;)V"); | ||
| 1588 | FIND_METHOD (clear_area, "clearArea", | ||
| 1589 | "(Lorg/gnu/emacs/EmacsWindow;IIII)V"); | ||
| 1590 | FIND_METHOD (ring_bell, "ringBell", "(I)V"); | 1610 | FIND_METHOD (ring_bell, "ringBell", "(I)V"); |
| 1591 | FIND_METHOD (query_tree, "queryTree", | 1611 | FIND_METHOD (query_tree, "queryTree", |
| 1592 | "(Lorg/gnu/emacs/EmacsWindow;)[S"); | 1612 | "(Lorg/gnu/emacs/EmacsWindow;)[S"); |
| 1593 | FIND_METHOD (get_screen_width, "getScreenWidth", "(Z)I"); | 1613 | FIND_METHOD (get_screen_width, "getScreenWidth", "(Z)I"); |
| 1594 | FIND_METHOD (get_screen_height, "getScreenHeight", "(Z)I"); | 1614 | FIND_METHOD (get_screen_height, "getScreenHeight", "(Z)I"); |
| 1595 | FIND_METHOD (detect_mouse, "detectMouse", "()Z"); | 1615 | FIND_METHOD (detect_mouse, "detectMouse", "()Z"); |
| 1616 | FIND_METHOD (detect_keyboard, "detectKeyboard", "()Z"); | ||
| 1596 | FIND_METHOD (name_keysym, "nameKeysym", "(I)Ljava/lang/String;"); | 1617 | FIND_METHOD (name_keysym, "nameKeysym", "(I)Ljava/lang/String;"); |
| 1597 | FIND_METHOD (browse_url, "browseUrl", "(Ljava/lang/String;Z)" | 1618 | FIND_METHOD (browse_url, "browseUrl", "(Ljava/lang/String;Z)" |
| 1598 | "Ljava/lang/String;"); | 1619 | "Ljava/lang/String;"); |
| @@ -1809,6 +1830,8 @@ android_init_emacs_window (void) | |||
| 1809 | android_damage_window. */ | 1830 | android_damage_window. */ |
| 1810 | FIND_METHOD (damage_rect, "damageRect", "(IIII)V"); | 1831 | FIND_METHOD (damage_rect, "damageRect", "(IIII)V"); |
| 1811 | FIND_METHOD (recreate_activity, "recreateActivity", "()V"); | 1832 | FIND_METHOD (recreate_activity, "recreateActivity", "()V"); |
| 1833 | FIND_METHOD (clear_window, "clearWindow", "()V"); | ||
| 1834 | FIND_METHOD (clear_area, "clearArea", "(IIII)V"); | ||
| 1812 | #undef FIND_METHOD | 1835 | #undef FIND_METHOD |
| 1813 | } | 1836 | } |
| 1814 | 1837 | ||
| @@ -2496,6 +2519,8 @@ JNIEXPORT jboolean JNICALL | |||
| 2496 | NATIVE_NAME (shouldForwardMultimediaButtons) (JNIEnv *env, | 2519 | NATIVE_NAME (shouldForwardMultimediaButtons) (JNIEnv *env, |
| 2497 | jobject object) | 2520 | jobject object) |
| 2498 | { | 2521 | { |
| 2522 | JNI_STACK_ALIGNMENT_PROLOGUE; | ||
| 2523 | |||
| 2499 | /* Yes, android_pass_multimedia_buttons_to_system is being | 2524 | /* Yes, android_pass_multimedia_buttons_to_system is being |
| 2500 | read from the UI thread. */ | 2525 | read from the UI thread. */ |
| 2501 | return !android_pass_multimedia_buttons_to_system; | 2526 | return !android_pass_multimedia_buttons_to_system; |
| @@ -2504,6 +2529,8 @@ NATIVE_NAME (shouldForwardMultimediaButtons) (JNIEnv *env, | |||
| 2504 | JNIEXPORT jboolean JNICALL | 2529 | JNIEXPORT jboolean JNICALL |
| 2505 | NATIVE_NAME (shouldForwardCtrlSpace) (JNIEnv *env, jobject object) | 2530 | NATIVE_NAME (shouldForwardCtrlSpace) (JNIEnv *env, jobject object) |
| 2506 | { | 2531 | { |
| 2532 | JNI_STACK_ALIGNMENT_PROLOGUE; | ||
| 2533 | |||
| 2507 | return !android_intercept_control_space; | 2534 | return !android_intercept_control_space; |
| 2508 | } | 2535 | } |
| 2509 | 2536 | ||
| @@ -2607,6 +2634,8 @@ JNIEXPORT void JNICALL | |||
| 2607 | NATIVE_NAME (notifyPixelsChanged) (JNIEnv *env, jobject object, | 2634 | NATIVE_NAME (notifyPixelsChanged) (JNIEnv *env, jobject object, |
| 2608 | jobject bitmap) | 2635 | jobject bitmap) |
| 2609 | { | 2636 | { |
| 2637 | JNI_STACK_ALIGNMENT_PROLOGUE; | ||
| 2638 | |||
| 2610 | void *data; | 2639 | void *data; |
| 2611 | 2640 | ||
| 2612 | /* Lock and unlock the bitmap. This calls | 2641 | /* Lock and unlock the bitmap. This calls |
| @@ -2660,6 +2689,8 @@ NATIVE_NAME (answerQuerySpin) (JNIEnv *env, jobject object) | |||
| 2660 | JNIEXPORT void JNICALL | 2689 | JNIEXPORT void JNICALL |
| 2661 | NATIVE_NAME (setupSystemThread) (void) | 2690 | NATIVE_NAME (setupSystemThread) (void) |
| 2662 | { | 2691 | { |
| 2692 | JNI_STACK_ALIGNMENT_PROLOGUE; | ||
| 2693 | |||
| 2663 | sigset_t sigset; | 2694 | sigset_t sigset; |
| 2664 | 2695 | ||
| 2665 | /* Block everything except for SIGSEGV and SIGBUS; those two are | 2696 | /* Block everything except for SIGSEGV and SIGBUS; those two are |
| @@ -3408,10 +3439,9 @@ android_clear_window (android_window handle) | |||
| 3408 | window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); | 3439 | window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); |
| 3409 | 3440 | ||
| 3410 | (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, | 3441 | (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, |
| 3411 | emacs_service, | 3442 | window, |
| 3412 | service_class.class, | 3443 | window_class.class, |
| 3413 | service_class.clear_window, | 3444 | window_class.clear_window); |
| 3414 | window); | ||
| 3415 | android_exception_check (); | 3445 | android_exception_check (); |
| 3416 | } | 3446 | } |
| 3417 | 3447 | ||
| @@ -4722,10 +4752,10 @@ android_clear_area (android_window handle, int x, int y, | |||
| 4722 | window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); | 4752 | window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); |
| 4723 | 4753 | ||
| 4724 | (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, | 4754 | (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, |
| 4725 | emacs_service, | 4755 | window, |
| 4726 | service_class.class, | 4756 | window_class.class, |
| 4727 | service_class.clear_area, | 4757 | window_class.clear_area, |
| 4728 | window, (jint) x, (jint) y, | 4758 | (jint) x, (jint) y, |
| 4729 | (jint) width, (jint) height); | 4759 | (jint) width, (jint) height); |
| 4730 | } | 4760 | } |
| 4731 | 4761 | ||
| @@ -5626,6 +5656,21 @@ android_detect_mouse (void) | |||
| 5626 | return rc; | 5656 | return rc; |
| 5627 | } | 5657 | } |
| 5628 | 5658 | ||
| 5659 | bool | ||
| 5660 | android_detect_keyboard (void) | ||
| 5661 | { | ||
| 5662 | bool rc; | ||
| 5663 | jmethodID method; | ||
| 5664 | |||
| 5665 | method = service_class.detect_keyboard; | ||
| 5666 | rc = (*android_java_env)->CallNonvirtualBooleanMethod (android_java_env, | ||
| 5667 | emacs_service, | ||
| 5668 | service_class.class, | ||
| 5669 | method); | ||
| 5670 | android_exception_check (); | ||
| 5671 | return rc; | ||
| 5672 | } | ||
| 5673 | |||
| 5629 | void | 5674 | void |
| 5630 | android_set_dont_focus_on_map (android_window handle, | 5675 | android_set_dont_focus_on_map (android_window handle, |
| 5631 | bool no_focus_on_map) | 5676 | bool no_focus_on_map) |
| @@ -6701,7 +6746,7 @@ static void *android_query_context; | |||
| 6701 | /* Run any function that the UI thread has asked to run, and then | 6746 | /* Run any function that the UI thread has asked to run, and then |
| 6702 | signal its completion. */ | 6747 | signal its completion. */ |
| 6703 | 6748 | ||
| 6704 | static void | 6749 | void |
| 6705 | android_check_query (void) | 6750 | android_check_query (void) |
| 6706 | { | 6751 | { |
| 6707 | void (*proc) (void *); | 6752 | void (*proc) (void *); |