aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2024-03-12 09:48:53 +0800
committerPo Lu2024-03-12 09:48:53 +0800
commitd7ded996082503ca00546c220c7ce8d96e16b76a (patch)
treec134bf9471567f3a27be6814f117d09994987059 /src
parentbf38783c32e794e46fd03210242f265f34257940 (diff)
downloademacs-d7ded996082503ca00546c220c7ce8d96e16b76a.tar.gz
emacs-d7ded996082503ca00546c220c7ce8d96e16b76a.zip
Implement notification residency on Android
* doc/lispref/os.texi (Desktop Notifications): Document support for `:resident'. * java/org/gnu/emacs/EmacsService.java (cancelNotification): * src/android.c (android_init_emacs_service): * src/android.h (struct android_emacs_service): New function. * src/androidselect.c (android_notifications_notify_1) (Fandroid_notifications_notify): New parameter QCresident; save it within notification lists. (android_notification_deleted, android_notification_action): Adjust for changes to the format of notification lists and cancel non-resident notifications when an action is selected. (syms_of_androidselect): <QCresident>: New symbol.
Diffstat (limited to 'src')
-rw-r--r--src/android.c2
-rw-r--r--src/android.h1
-rw-r--r--src/androidselect.c55
3 files changed, 46 insertions, 12 deletions
diff --git a/src/android.c b/src/android.c
index 125bb5209c3..dcd5c6d99c7 100644
--- a/src/android.c
+++ b/src/android.c
@@ -1688,6 +1688,8 @@ android_init_emacs_service (void)
1688 "externalStorageAvailable", "()Z"); 1688 "externalStorageAvailable", "()Z");
1689 FIND_METHOD (request_storage_access, 1689 FIND_METHOD (request_storage_access,
1690 "requestStorageAccess", "()V"); 1690 "requestStorageAccess", "()V");
1691 FIND_METHOD (cancel_notification,
1692 "cancelNotification", "(Ljava/lang/String;)V");
1691#undef FIND_METHOD 1693#undef FIND_METHOD
1692} 1694}
1693 1695
diff --git a/src/android.h b/src/android.h
index ee634a3e76c..2ca3d7e1446 100644
--- a/src/android.h
+++ b/src/android.h
@@ -302,6 +302,7 @@ struct android_emacs_service
302 jmethodID valid_authority; 302 jmethodID valid_authority;
303 jmethodID external_storage_available; 303 jmethodID external_storage_available;
304 jmethodID request_storage_access; 304 jmethodID request_storage_access;
305 jmethodID cancel_notification;
305}; 306};
306 307
307extern JNIEnv *android_java_env; 308extern JNIEnv *android_java_env;
diff --git a/src/androidselect.c b/src/androidselect.c
index 04f4cf1573f..bcb7bcd2c3b 100644
--- a/src/androidselect.c
+++ b/src/androidselect.c
@@ -567,15 +567,15 @@ android_locate_icon (const char *name)
567} 567}
568 568
569/* Display a desktop notification with the provided TITLE, BODY, 569/* Display a desktop notification with the provided TITLE, BODY,
570 REPLACES_ID, GROUP, ICON, URGENCY, ACTIONS, ACTION_CB and CANCEL_CB. 570 REPLACES_ID, GROUP, ICON, URGENCY, ACTIONS, RESIDENT, ACTION_CB and
571 Return an identifier for the resulting notification. */ 571 CANCEL_CB. Return an identifier for the resulting notification. */
572 572
573static intmax_t 573static intmax_t
574android_notifications_notify_1 (Lisp_Object title, Lisp_Object body, 574android_notifications_notify_1 (Lisp_Object title, Lisp_Object body,
575 Lisp_Object replaces_id, 575 Lisp_Object replaces_id,
576 Lisp_Object group, Lisp_Object icon, 576 Lisp_Object group, Lisp_Object icon,
577 Lisp_Object urgency, Lisp_Object actions, 577 Lisp_Object urgency, Lisp_Object actions,
578 Lisp_Object action_cb, 578 Lisp_Object resident, Lisp_Object action_cb,
579 Lisp_Object cancel_cb) 579 Lisp_Object cancel_cb)
580{ 580{
581 static intmax_t counter; 581 static intmax_t counter;
@@ -740,8 +740,9 @@ android_notifications_notify_1 (Lisp_Object title, Lisp_Object body,
740 740
741 /* If callbacks are provided, save them into notification_table. */ 741 /* If callbacks are provided, save them into notification_table. */
742 742
743 if (!NILP (action_cb) || !NILP (cancel_cb)) 743 if (!NILP (action_cb) || !NILP (cancel_cb) || !NILP (resident))
744 Fputhash (build_string (identifier), Fcons (action_cb, cancel_cb), 744 Fputhash (build_string (identifier), list3 (action_cb, cancel_cb,
745 resident),
745 notification_table); 746 notification_table);
746 747
747 /* Return the ID. */ 748 /* Return the ID. */
@@ -755,12 +756,12 @@ ARGS must contain keywords followed by values. Each of the following
755keywords is understood: 756keywords is understood:
756 757
757 :title The notification title. 758 :title The notification title.
758 :body The notification body. 759 :body The notification body.
759 :replaces-id The ID of a previous notification to supersede. 760 :replaces-id The ID of a previous notification to supersede.
760 :group The notification group, or nil. 761 :group The notification group, or nil.
761 :urgency One of the symbols `low', `normal' or `critical', 762 :urgency One of the symbols `low', `normal' or `critical',
762 defining the importance of the notification group. 763 defining the importance of the notification group.
763 :icon The name of a drawable resource to display as the 764 :icon The name of a drawable resource to display as the
764 notification's icon. 765 notification's icon.
765 :actions A list of actions of the form: 766 :actions A list of actions of the form:
766 (KEY TITLE KEY TITLE ...) 767 (KEY TITLE KEY TITLE ...)
@@ -770,6 +771,8 @@ keywords is understood:
770 its existence is implied, and its TITLE is ignored. 771 its existence is implied, and its TITLE is ignored.
771 No more than three actions can be defined, not 772 No more than three actions can be defined, not
772 counting any action with "default" as its key. 773 counting any action with "default" as its key.
774 :resident When set the notification will not be automatically
775 dismissed when it or an action is selected.
773 :on-action Function to call when an action is invoked. 776 :on-action Function to call when an action is invoked.
774 The notification id and the key of the action are 777 The notification id and the key of the action are
775 provided as arguments to the function. 778 provided as arguments to the function.
@@ -811,7 +814,7 @@ this function.
811usage: (android-notifications-notify &rest ARGS) */) 814usage: (android-notifications-notify &rest ARGS) */)
812 (ptrdiff_t nargs, Lisp_Object *args) 815 (ptrdiff_t nargs, Lisp_Object *args)
813{ 816{
814 Lisp_Object title, body, replaces_id, group, urgency; 817 Lisp_Object title, body, replaces_id, group, urgency, resident;
815 Lisp_Object icon; 818 Lisp_Object icon;
816 Lisp_Object key, value, actions, action_cb, cancel_cb; 819 Lisp_Object key, value, actions, action_cb, cancel_cb;
817 ptrdiff_t i; 820 ptrdiff_t i;
@@ -821,7 +824,7 @@ usage: (android-notifications-notify &rest ARGS) */)
821 824
822 /* Clear each variable above. */ 825 /* Clear each variable above. */
823 title = body = replaces_id = group = icon = urgency = actions = Qnil; 826 title = body = replaces_id = group = icon = urgency = actions = Qnil;
824 action_cb = cancel_cb = Qnil; 827 resident = action_cb = cancel_cb = Qnil;
825 828
826 /* If NARGS is odd, error. */ 829 /* If NARGS is odd, error. */
827 830
@@ -849,6 +852,8 @@ usage: (android-notifications-notify &rest ARGS) */)
849 icon = value; 852 icon = value;
850 else if (EQ (key, QCactions)) 853 else if (EQ (key, QCactions))
851 actions = value; 854 actions = value;
855 else if (EQ (key, QCresident))
856 resident = value;
852 else if (EQ (key, QCon_action)) 857 else if (EQ (key, QCon_action))
853 action_cb = value; 858 action_cb = value;
854 else if (EQ (key, QCon_cancel)) 859 else if (EQ (key, QCon_cancel))
@@ -878,8 +883,8 @@ usage: (android-notifications-notify &rest ARGS) */)
878 883
879 return make_int (android_notifications_notify_1 (title, body, replaces_id, 884 return make_int (android_notifications_notify_1 (title, body, replaces_id,
880 group, icon, urgency, 885 group, icon, urgency,
881 actions, action_cb, 886 actions, resident,
882 cancel_cb)); 887 action_cb, cancel_cb));
883} 888}
884 889
885/* Run callbacks in response to a notification being deleted. 890/* Run callbacks in response to a notification being deleted.
@@ -899,7 +904,7 @@ android_notification_deleted (struct android_notification_event *event,
899 if (!NILP (item)) 904 if (!NILP (item))
900 Fremhash (tag, notification_table); 905 Fremhash (tag, notification_table);
901 906
902 if (CONSP (item) && FUNCTIONP (XCDR (item)) 907 if (CONSP (item) && FUNCTIONP (XCAR (XCDR (item)))
903 && sscanf (event->tag, "%*d.%*ld.%jd", &id) > 0) 908 && sscanf (event->tag, "%*d.%*ld.%jd", &id) > 0)
904 { 909 {
905 ie->kind = NOTIFICATION_EVENT; 910 ie->kind = NOTIFICATION_EVENT;
@@ -919,6 +924,8 @@ android_notification_action (struct android_notification_event *event,
919{ 924{
920 Lisp_Object item, tag; 925 Lisp_Object item, tag;
921 intmax_t id; 926 intmax_t id;
927 jstring tag_object;
928 jmethodID method;
922 929
923 tag = build_string (event->tag); 930 tag = build_string (event->tag);
924 item = Fgethash (tag, notification_table, Qnil); 931 item = Fgethash (tag, notification_table, Qnil);
@@ -929,6 +936,29 @@ android_notification_action (struct android_notification_event *event,
929 ie->kind = NOTIFICATION_EVENT; 936 ie->kind = NOTIFICATION_EVENT;
930 ie->arg = list3 (XCAR (item), make_int (id), action); 937 ie->arg = list3 (XCAR (item), make_int (id), action);
931 } 938 }
939
940 /* Test whether ITEM is resident. Non-resident notifications must be
941 removed when activated. */
942
943 if (!CONSP (item) || NILP (XCAR (XCDR (XCDR (item)))))
944 {
945 method = service_class.cancel_notification;
946 tag_object
947 = (*android_java_env)->NewStringUTF (android_java_env,
948 event->tag);
949 android_exception_check ();
950
951 (*android_java_env)->CallNonvirtualVoidMethod (android_java_env,
952 emacs_service,
953 service_class.class,
954 method, tag_object);
955 android_exception_check_1 (tag_object);
956 ANDROID_DELETE_LOCAL_REF (tag_object);
957
958 /* Remove the notification from the callback table. */
959 if (!NILP (item))
960 Fremhash (tag, notification_table);
961 }
932} 962}
933 963
934 964
@@ -971,6 +1001,7 @@ syms_of_androidselect (void)
971 DEFSYM (QCurgency, ":urgency"); 1001 DEFSYM (QCurgency, ":urgency");
972 DEFSYM (QCicon, ":icon"); 1002 DEFSYM (QCicon, ":icon");
973 DEFSYM (QCactions, ":actions"); 1003 DEFSYM (QCactions, ":actions");
1004 DEFSYM (QCresident, ":resident");
974 DEFSYM (QCon_action, ":on-action"); 1005 DEFSYM (QCon_action, ":on-action");
975 DEFSYM (QCon_cancel, ":on-cancel"); 1006 DEFSYM (QCon_cancel, ":on-cancel");
976 1007