diff options
| author | Po Lu | 2024-03-11 21:40:47 +0800 |
|---|---|---|
| committer | Po Lu | 2024-03-11 21:41:14 +0800 |
| commit | a7a37341cad230448e487d0ffa343eeeb8a66a65 (patch) | |
| tree | ab06b5826c5ae7bdd5b3dcc85b3ecba8dbee8c84 /src/android.c | |
| parent | 75cfc6c73faa1561018b1212156964a7919c69fe (diff) | |
| download | emacs-a7a37341cad230448e487d0ffa343eeeb8a66a65.tar.gz emacs-a7a37341cad230448e487d0ffa343eeeb8a66a65.zip | |
Implement notification callbacks on Android
* doc/lispref/os.texi (Desktop Notifications): Document that
:on-cancel, :on-action and :actions are now supported on
Android.
* java/org/gnu/emacs/EmacsActivity.java (onNewIntent): New
function.
* java/org/gnu/emacs/EmacsDesktopNotification.java
(NOTIFICATION_ACTION, NOTIFICATION_TAG, NOTIFICATION_DISMISSED):
New constants. <actions, titles>: New fields.
(insertActions): New function.
(display1, display): Insert actions on Jelly Bean and up, and
arrange to be notified when the notification is dismissed.
(CancellationReceiver): New class.
* java/org/gnu/emacs/EmacsNative.java (sendNotificationDeleted)
(sendNotificationAction): New functions.
* src/android.c (sendDndDrag, sendDndUri, sendDndText): Correct
return types.
(sendNotificationDeleted, sendNotificationAction)
(android_exception_check_5, android_exception_check_6): New
functions.
* src/android.h:
* src/androidgui.h (struct android_notification_event): New
structure.
(union android_event): New member for notification events.
* src/androidselect.c (android_init_emacs_desktop_notification):
Update JNI signatures.
(android_notifications_notify_1, Fandroid_notifications_notify):
New arguments ACTIONS, ACTION_CB and CANCEL_CB. Convert and
record them as appropriate.
(android_notification_deleted, android_notification_action): New
functions.
(syms_of_androidselect): Prepare a hash table of outstanding
notifications.
<QCactions, QCon_action, QCon_cancel> New defsyms.
* src/androidterm.c (handle_one_android_event)
<ANDROID_NOTIFICATION_DELETED>
<ANDROID_NOTIFICATION_ACTION>: Dispatch event contents to
androidselect.c for processing.
* src/androidterm.h:
* src/androidvfs.c (java_string_class): Export.
* src/keyboard.c (kbd_buffer_get_event) <NOTIFICATION_EVENT>:
Call callback specified by the event.
* src/termhooks.h (enum event_kind) [HAVE_ANDROID]: New
enum NOTIFICATION_EVENT.
Diffstat (limited to 'src/android.c')
| -rw-r--r-- | src/android.c | 161 |
1 files changed, 158 insertions, 3 deletions
diff --git a/src/android.c b/src/android.c index d7bd06f1f34..125bb5209c3 100644 --- a/src/android.c +++ b/src/android.c | |||
| @@ -2457,7 +2457,7 @@ NATIVE_NAME (sendExpose) (JNIEnv *env, jobject object, | |||
| 2457 | return event_serial; | 2457 | return event_serial; |
| 2458 | } | 2458 | } |
| 2459 | 2459 | ||
| 2460 | JNIEXPORT jboolean JNICALL | 2460 | JNIEXPORT jlong JNICALL |
| 2461 | NATIVE_NAME (sendDndDrag) (JNIEnv *env, jobject object, | 2461 | NATIVE_NAME (sendDndDrag) (JNIEnv *env, jobject object, |
| 2462 | jshort window, jint x, jint y) | 2462 | jshort window, jint x, jint y) |
| 2463 | { | 2463 | { |
| @@ -2477,7 +2477,7 @@ NATIVE_NAME (sendDndDrag) (JNIEnv *env, jobject object, | |||
| 2477 | return event_serial; | 2477 | return event_serial; |
| 2478 | } | 2478 | } |
| 2479 | 2479 | ||
| 2480 | JNIEXPORT jboolean JNICALL | 2480 | JNIEXPORT jlong JNICALL |
| 2481 | NATIVE_NAME (sendDndUri) (JNIEnv *env, jobject object, | 2481 | NATIVE_NAME (sendDndUri) (JNIEnv *env, jobject object, |
| 2482 | jshort window, jint x, jint y, | 2482 | jshort window, jint x, jint y, |
| 2483 | jstring string) | 2483 | jstring string) |
| @@ -2514,7 +2514,7 @@ NATIVE_NAME (sendDndUri) (JNIEnv *env, jobject object, | |||
| 2514 | return event_serial; | 2514 | return event_serial; |
| 2515 | } | 2515 | } |
| 2516 | 2516 | ||
| 2517 | JNIEXPORT jboolean JNICALL | 2517 | JNIEXPORT jlong JNICALL |
| 2518 | NATIVE_NAME (sendDndText) (JNIEnv *env, jobject object, | 2518 | NATIVE_NAME (sendDndText) (JNIEnv *env, jobject object, |
| 2519 | jshort window, jint x, jint y, | 2519 | jshort window, jint x, jint y, |
| 2520 | jstring string) | 2520 | jstring string) |
| @@ -2551,6 +2551,85 @@ NATIVE_NAME (sendDndText) (JNIEnv *env, jobject object, | |||
| 2551 | return event_serial; | 2551 | return event_serial; |
| 2552 | } | 2552 | } |
| 2553 | 2553 | ||
| 2554 | JNIEXPORT jlong JNICALL | ||
| 2555 | NATIVE_NAME (sendNotificationDeleted) (JNIEnv *env, jobject object, | ||
| 2556 | jstring tag) | ||
| 2557 | { | ||
| 2558 | JNI_STACK_ALIGNMENT_PROLOGUE; | ||
| 2559 | |||
| 2560 | union android_event event; | ||
| 2561 | const char *characters; | ||
| 2562 | |||
| 2563 | event.notification.type = ANDROID_NOTIFICATION_DELETED; | ||
| 2564 | event.notification.serial = ++event_serial; | ||
| 2565 | event.notification.window = ANDROID_NONE; | ||
| 2566 | |||
| 2567 | /* TAG is guaranteed to be an ASCII string, of which the JNI character | ||
| 2568 | encoding is a superset. */ | ||
| 2569 | characters = (*env)->GetStringUTFChars (env, tag, NULL); | ||
| 2570 | if (!characters) | ||
| 2571 | return 0; | ||
| 2572 | |||
| 2573 | event.notification.tag = strdup (characters); | ||
| 2574 | (*env)->ReleaseStringUTFChars (env, tag, characters); | ||
| 2575 | if (!event.notification.tag) | ||
| 2576 | return 0; | ||
| 2577 | |||
| 2578 | event.notification.action = NULL; | ||
| 2579 | event.notification.length = 0; | ||
| 2580 | |||
| 2581 | android_write_event (&event); | ||
| 2582 | return event_serial; | ||
| 2583 | } | ||
| 2584 | |||
| 2585 | JNIEXPORT jlong JNICALL | ||
| 2586 | NATIVE_NAME (sendNotificationAction) (JNIEnv *env, jobject object, | ||
| 2587 | jstring tag, jstring action) | ||
| 2588 | { | ||
| 2589 | JNI_STACK_ALIGNMENT_PROLOGUE; | ||
| 2590 | |||
| 2591 | union android_event event; | ||
| 2592 | const void *characters; | ||
| 2593 | jsize length; | ||
| 2594 | uint16_t *buffer; | ||
| 2595 | |||
| 2596 | event.notification.type = ANDROID_NOTIFICATION_ACTION; | ||
| 2597 | event.notification.serial = ++event_serial; | ||
| 2598 | event.notification.window = ANDROID_NONE; | ||
| 2599 | |||
| 2600 | /* TAG is guaranteed to be an ASCII string, of which the JNI character | ||
| 2601 | encoding is a superset. */ | ||
| 2602 | characters = (*env)->GetStringUTFChars (env, tag, NULL); | ||
| 2603 | if (!characters) | ||
| 2604 | return 0; | ||
| 2605 | |||
| 2606 | event.notification.tag = strdup (characters); | ||
| 2607 | (*env)->ReleaseStringUTFChars (env, tag, characters); | ||
| 2608 | if (!event.notification.tag) | ||
| 2609 | return 0; | ||
| 2610 | |||
| 2611 | length = (*env)->GetStringLength (env, action); | ||
| 2612 | buffer = malloc (length * sizeof *buffer); | ||
| 2613 | characters = (*env)->GetStringChars (env, action, NULL); | ||
| 2614 | |||
| 2615 | if (!characters) | ||
| 2616 | { | ||
| 2617 | /* The JVM has run out of memory; return and let the out of memory | ||
| 2618 | error take its course. */ | ||
| 2619 | xfree (event.notification.tag); | ||
| 2620 | return 0; | ||
| 2621 | } | ||
| 2622 | |||
| 2623 | memcpy (buffer, characters, length * sizeof *buffer); | ||
| 2624 | (*env)->ReleaseStringChars (env, action, characters); | ||
| 2625 | |||
| 2626 | event.notification.action = buffer; | ||
| 2627 | event.notification.length = length; | ||
| 2628 | |||
| 2629 | android_write_event (&event); | ||
| 2630 | return event_serial; | ||
| 2631 | } | ||
| 2632 | |||
| 2554 | JNIEXPORT jboolean JNICALL | 2633 | JNIEXPORT jboolean JNICALL |
| 2555 | NATIVE_NAME (shouldForwardMultimediaButtons) (JNIEnv *env, | 2634 | NATIVE_NAME (shouldForwardMultimediaButtons) (JNIEnv *env, |
| 2556 | jobject object) | 2635 | jobject object) |
| @@ -6310,6 +6389,82 @@ android_exception_check_4 (jobject object, jobject object1, | |||
| 6310 | memory_full (0); | 6389 | memory_full (0); |
| 6311 | } | 6390 | } |
| 6312 | 6391 | ||
| 6392 | /* Like android_exception_check_4, except it takes more than four local | ||
| 6393 | reference arguments. */ | ||
| 6394 | |||
| 6395 | void | ||
| 6396 | android_exception_check_5 (jobject object, jobject object1, | ||
| 6397 | jobject object2, jobject object3, | ||
| 6398 | jobject object4) | ||
| 6399 | { | ||
| 6400 | if (likely (!(*android_java_env)->ExceptionCheck (android_java_env))) | ||
| 6401 | return; | ||
| 6402 | |||
| 6403 | __android_log_print (ANDROID_LOG_WARN, __func__, | ||
| 6404 | "Possible out of memory error. " | ||
| 6405 | " The Java exception follows: "); | ||
| 6406 | /* Describe exactly what went wrong. */ | ||
| 6407 | (*android_java_env)->ExceptionDescribe (android_java_env); | ||
| 6408 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 6409 | |||
| 6410 | if (object) | ||
| 6411 | ANDROID_DELETE_LOCAL_REF (object); | ||
| 6412 | |||
| 6413 | if (object1) | ||
| 6414 | ANDROID_DELETE_LOCAL_REF (object1); | ||
| 6415 | |||
| 6416 | if (object2) | ||
| 6417 | ANDROID_DELETE_LOCAL_REF (object2); | ||
| 6418 | |||
| 6419 | if (object3) | ||
| 6420 | ANDROID_DELETE_LOCAL_REF (object3); | ||
| 6421 | |||
| 6422 | if (object4) | ||
| 6423 | ANDROID_DELETE_LOCAL_REF (object4); | ||
| 6424 | |||
| 6425 | memory_full (0); | ||
| 6426 | } | ||
| 6427 | |||
| 6428 | |||
| 6429 | /* Like android_exception_check_5, except it takes more than five local | ||
| 6430 | reference arguments. */ | ||
| 6431 | |||
| 6432 | void | ||
| 6433 | android_exception_check_6 (jobject object, jobject object1, | ||
| 6434 | jobject object2, jobject object3, | ||
| 6435 | jobject object4, jobject object5) | ||
| 6436 | { | ||
| 6437 | if (likely (!(*android_java_env)->ExceptionCheck (android_java_env))) | ||
| 6438 | return; | ||
| 6439 | |||
| 6440 | __android_log_print (ANDROID_LOG_WARN, __func__, | ||
| 6441 | "Possible out of memory error. " | ||
| 6442 | " The Java exception follows: "); | ||
| 6443 | /* Describe exactly what went wrong. */ | ||
| 6444 | (*android_java_env)->ExceptionDescribe (android_java_env); | ||
| 6445 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 6446 | |||
| 6447 | if (object) | ||
| 6448 | ANDROID_DELETE_LOCAL_REF (object); | ||
| 6449 | |||
| 6450 | if (object1) | ||
| 6451 | ANDROID_DELETE_LOCAL_REF (object1); | ||
| 6452 | |||
| 6453 | if (object2) | ||
| 6454 | ANDROID_DELETE_LOCAL_REF (object2); | ||
| 6455 | |||
| 6456 | if (object3) | ||
| 6457 | ANDROID_DELETE_LOCAL_REF (object3); | ||
| 6458 | |||
| 6459 | if (object4) | ||
| 6460 | ANDROID_DELETE_LOCAL_REF (object4); | ||
| 6461 | |||
| 6462 | if (object5) | ||
| 6463 | ANDROID_DELETE_LOCAL_REF (object5); | ||
| 6464 | |||
| 6465 | memory_full (0); | ||
| 6466 | } | ||
| 6467 | |||
| 6313 | /* Check for JNI problems based on the value of OBJECT. | 6468 | /* Check for JNI problems based on the value of OBJECT. |
| 6314 | 6469 | ||
| 6315 | Signal out of memory if OBJECT is NULL. OBJECT1 means the | 6470 | Signal out of memory if OBJECT is NULL. OBJECT1 means the |