diff options
| author | Po Lu | 2024-03-13 10:59:39 +0800 |
|---|---|---|
| committer | Po Lu | 2024-03-13 11:01:39 +0800 |
| commit | 6b40d557c4a9a4152565c1a1b0da49a1aaaec84f (patch) | |
| tree | ac82dd76319ccc7df22a9d70923ec28f97c4f41a /src | |
| parent | 4afafa03704aab0c21e4cb4f028256ecead5f795 (diff) | |
| download | emacs-6b40d557c4a9a4152565c1a1b0da49a1aaaec84f.tar.gz emacs-6b40d557c4a9a4152565c1a1b0da49a1aaaec84f.zip | |
Port more notification senders to non-XDG systems
* doc/lispref/os.texi (Desktop Notifications): Document that
`:timeout' is now implemented.
* java/org/gnu/emacs/EmacsDesktopNotification.java
(EmacsDesktopNotification): New field delay.
(display1): Set delay on Android 8.0 and up.
* lisp/erc/erc-desktop-notifications.el
(erc-notifications-notify): Call Android or Haiku notification
functions on those systems.
* lisp/gnus/gnus-notifications.el (gnus-notifications-action)
(gnus-notification-close): Remove dismissed notifications from
the notification to message map.
(gnus-notifications-notify): Call android-notifications-notify
if possible.
* src/androidselect.c (android_init_emacs_desktop_notification):
Update accordingly.
(android_notifications_notify_1): New argument TIMEOUT.
(Fandroid_notifications_notify): New argument QCtimeout.
(syms_of_androidselect) <QCtimeout>: New symbol.
Diffstat (limited to 'src')
| -rw-r--r-- | src/androidselect.c | 86 |
1 files changed, 59 insertions, 27 deletions
diff --git a/src/androidselect.c b/src/androidselect.c index 521133976a7..87dd2c3d079 100644 --- a/src/androidselect.c +++ b/src/androidselect.c | |||
| @@ -526,7 +526,7 @@ android_init_emacs_desktop_notification (void) | |||
| 526 | FIND_METHOD (init, "<init>", "(Ljava/lang/String;" | 526 | FIND_METHOD (init, "<init>", "(Ljava/lang/String;" |
| 527 | "Ljava/lang/String;Ljava/lang/String;" | 527 | "Ljava/lang/String;Ljava/lang/String;" |
| 528 | "Ljava/lang/String;II[Ljava/lang/String;" | 528 | "Ljava/lang/String;II[Ljava/lang/String;" |
| 529 | "[Ljava/lang/String;)V"); | 529 | "[Ljava/lang/String;J)V"); |
| 530 | FIND_METHOD (display, "display", "()V"); | 530 | FIND_METHOD (display, "display", "()V"); |
| 531 | #undef FIND_METHOD | 531 | #undef FIND_METHOD |
| 532 | } | 532 | } |
| @@ -567,16 +567,17 @@ 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, RESIDENT, ACTION_CB and | 570 | REPLACES_ID, GROUP, ICON, URGENCY, ACTIONS, TIMEOUT, RESIDENT, |
| 571 | CLOSE_CB. Return an identifier for the resulting notification. */ | 571 | ACTION_CB and CLOSE_CB. Return an identifier for the resulting |
| 572 | notification. */ | ||
| 572 | 573 | ||
| 573 | static intmax_t | 574 | static intmax_t |
| 574 | android_notifications_notify_1 (Lisp_Object title, Lisp_Object body, | 575 | android_notifications_notify_1 (Lisp_Object title, Lisp_Object body, |
| 575 | Lisp_Object replaces_id, | 576 | Lisp_Object replaces_id, |
| 576 | Lisp_Object group, Lisp_Object icon, | 577 | Lisp_Object group, Lisp_Object icon, |
| 577 | Lisp_Object urgency, Lisp_Object actions, | 578 | Lisp_Object urgency, Lisp_Object actions, |
| 578 | Lisp_Object resident, Lisp_Object action_cb, | 579 | Lisp_Object timeout, Lisp_Object resident, |
| 579 | Lisp_Object close_cb) | 580 | Lisp_Object action_cb, Lisp_Object close_cb) |
| 580 | { | 581 | { |
| 581 | static intmax_t counter; | 582 | static intmax_t counter; |
| 582 | intmax_t id; | 583 | intmax_t id; |
| @@ -593,6 +594,7 @@ android_notifications_notify_1 (Lisp_Object title, Lisp_Object body, | |||
| 593 | jint nitems, i; | 594 | jint nitems, i; |
| 594 | jstring item; | 595 | jstring item; |
| 595 | Lisp_Object length; | 596 | Lisp_Object length; |
| 597 | jlong timeout_val; | ||
| 596 | 598 | ||
| 597 | if (EQ (urgency, Qlow)) | 599 | if (EQ (urgency, Qlow)) |
| 598 | type = 2; /* IMPORTANCE_LOW */ | 600 | type = 2; /* IMPORTANCE_LOW */ |
| @@ -603,6 +605,23 @@ android_notifications_notify_1 (Lisp_Object title, Lisp_Object body, | |||
| 603 | else | 605 | else |
| 604 | signal_error ("Invalid notification importance given", urgency); | 606 | signal_error ("Invalid notification importance given", urgency); |
| 605 | 607 | ||
| 608 | /* Decode the timeout. */ | ||
| 609 | |||
| 610 | timeout_val = 0; | ||
| 611 | |||
| 612 | if (!NILP (timeout)) | ||
| 613 | { | ||
| 614 | CHECK_INTEGER (timeout); | ||
| 615 | |||
| 616 | if (!integer_to_intmax (timeout, &id) | ||
| 617 | || id > TYPE_MAXIMUM (jlong) | ||
| 618 | || id < TYPE_MINIMUM (jlong)) | ||
| 619 | signal_error ("Invalid timeout", timeout); | ||
| 620 | |||
| 621 | if (id > 0) | ||
| 622 | timeout_val = id; | ||
| 623 | } | ||
| 624 | |||
| 606 | nitems = 0; | 625 | nitems = 0; |
| 607 | 626 | ||
| 608 | /* If ACTIONS is provided, split it into two arrays of Java strings | 627 | /* If ACTIONS is provided, split it into two arrays of Java strings |
| @@ -714,7 +733,8 @@ android_notifications_notify_1 (Lisp_Object title, Lisp_Object body, | |||
| 714 | notification_class.init, | 733 | notification_class.init, |
| 715 | title1, body1, group1, | 734 | title1, body1, group1, |
| 716 | identifier1, icon1, type, | 735 | identifier1, icon1, type, |
| 717 | action_keys, action_titles); | 736 | action_keys, action_titles, |
| 737 | timeout_val); | ||
| 718 | android_exception_check_6 (title1, body1, group1, identifier1, | 738 | android_exception_check_6 (title1, body1, group1, identifier1, |
| 719 | action_titles, action_keys); | 739 | action_titles, action_keys); |
| 720 | 740 | ||
| @@ -723,12 +743,8 @@ android_notifications_notify_1 (Lisp_Object title, Lisp_Object body, | |||
| 723 | ANDROID_DELETE_LOCAL_REF (body1); | 743 | ANDROID_DELETE_LOCAL_REF (body1); |
| 724 | ANDROID_DELETE_LOCAL_REF (group1); | 744 | ANDROID_DELETE_LOCAL_REF (group1); |
| 725 | ANDROID_DELETE_LOCAL_REF (identifier1); | 745 | ANDROID_DELETE_LOCAL_REF (identifier1); |
| 726 | 746 | ANDROID_DELETE_LOCAL_REF (action_keys); | |
| 727 | if (action_keys) | 747 | ANDROID_DELETE_LOCAL_REF (action_titles); |
| 728 | ANDROID_DELETE_LOCAL_REF (action_keys); | ||
| 729 | |||
| 730 | if (action_titles) | ||
| 731 | ANDROID_DELETE_LOCAL_REF (action_titles); | ||
| 732 | 748 | ||
| 733 | /* Display the notification. */ | 749 | /* Display the notification. */ |
| 734 | (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, | 750 | (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, |
| @@ -769,8 +785,14 @@ keywords is understood: | |||
| 769 | The action for which CALLBACK is called when the | 785 | The action for which CALLBACK is called when the |
| 770 | notification itself is selected is named "default", | 786 | notification itself is selected is named "default", |
| 771 | its existence is implied, and its TITLE is ignored. | 787 | its existence is implied, and its TITLE is ignored. |
| 772 | No more than three actions can be defined, not | 788 | No more than three actions defined here will be |
| 773 | counting any action with "default" as its key. | 789 | displayed, not counting any with "default" as its |
| 790 | key. | ||
| 791 | :timeout Number of miliseconds from the display of the | ||
| 792 | notification at which it will be automatically | ||
| 793 | dismissed, or a value of zero or smaller if it | ||
| 794 | is to remain until user action is taken to dismiss | ||
| 795 | it. | ||
| 774 | :resident When set the notification will not be automatically | 796 | :resident When set the notification will not be automatically |
| 775 | dismissed when it or an action is selected. | 797 | dismissed when it or an action is selected. |
| 776 | :on-action Function to call when an action is invoked. | 798 | :on-action Function to call when an action is invoked. |
| @@ -780,12 +802,15 @@ keywords is understood: | |||
| 780 | with the notification id and the symbol `undefined' | 802 | with the notification id and the symbol `undefined' |
| 781 | for arguments. | 803 | for arguments. |
| 782 | 804 | ||
| 783 | The notification group is ignored on Android 7.1 and earlier versions | 805 | The notification group and timeout are ignored on Android 7.1 and |
| 784 | of Android. Outside such older systems, it identifies a category that | 806 | earlier versions of Android. On more recent versions, the urgency |
| 785 | will be displayed in the system Settings menu, and the urgency | 807 | identifies a category that will be displayed in the system Settings |
| 786 | provided always extends to affect all notifications displayed within | 808 | menu, and the urgency provided always extends to affect all |
| 787 | that category. If the group is not provided, it defaults to the | 809 | notifications displayed within that category, though it may be ignored |
| 788 | string "Desktop Notifications". | 810 | if higher than any previously-specified urgency or if the user have |
| 811 | already configured a different urgency for this category from Settings. | ||
| 812 | If the group is not provided, it defaults to the string "Desktop | ||
| 813 | Notifications" with the urgency suffixed. | ||
| 789 | 814 | ||
| 790 | Each caller should strive to provide one unchanging combination of | 815 | Each caller should strive to provide one unchanging combination of |
| 791 | notification group and urgency for each kind of notification it sends, | 816 | notification group and urgency for each kind of notification it sends, |
| @@ -795,8 +820,8 @@ first notification sent to its notification group. | |||
| 795 | 820 | ||
| 796 | The provided icon should be the name of a "drawable resource" present | 821 | The provided icon should be the name of a "drawable resource" present |
| 797 | within the "android.R.drawable" class designating an icon with a | 822 | within the "android.R.drawable" class designating an icon with a |
| 798 | transparent background. If no icon is provided (or the icon is absent | 823 | transparent background. Should no icon be provided (or the icon is |
| 799 | from this system), it defaults to "ic_dialog_alert". | 824 | absent from this system), it defaults to "ic_dialog_alert". |
| 800 | 825 | ||
| 801 | Actions specified with :actions cannot be displayed on Android 4.0 and | 826 | Actions specified with :actions cannot be displayed on Android 4.0 and |
| 802 | earlier versions of the system. | 827 | earlier versions of the system. |
| @@ -814,17 +839,18 @@ this function. | |||
| 814 | usage: (android-notifications-notify &rest ARGS) */) | 839 | usage: (android-notifications-notify &rest ARGS) */) |
| 815 | (ptrdiff_t nargs, Lisp_Object *args) | 840 | (ptrdiff_t nargs, Lisp_Object *args) |
| 816 | { | 841 | { |
| 817 | Lisp_Object title, body, replaces_id, group, urgency, resident; | 842 | Lisp_Object title, body, replaces_id, group, urgency, timeout, resident; |
| 818 | Lisp_Object icon; | 843 | Lisp_Object icon; |
| 819 | Lisp_Object key, value, actions, action_cb, close_cb; | 844 | Lisp_Object key, value, actions, action_cb, close_cb; |
| 820 | ptrdiff_t i; | 845 | ptrdiff_t i; |
| 846 | AUTO_STRING (default_icon, "ic_dialog_alert"); | ||
| 821 | 847 | ||
| 822 | if (!android_init_gui) | 848 | if (!android_init_gui) |
| 823 | error ("No Android display connection!"); | 849 | error ("No Android display connection!"); |
| 824 | 850 | ||
| 825 | /* Clear each variable above. */ | 851 | /* Clear each variable above. */ |
| 826 | title = body = replaces_id = group = icon = urgency = actions = Qnil; | 852 | title = body = replaces_id = group = icon = urgency = actions = Qnil; |
| 827 | resident = action_cb = close_cb = Qnil; | 853 | timeout = resident = action_cb = close_cb = Qnil; |
| 828 | 854 | ||
| 829 | /* If NARGS is odd, error. */ | 855 | /* If NARGS is odd, error. */ |
| 830 | 856 | ||
| @@ -852,6 +878,8 @@ usage: (android-notifications-notify &rest ARGS) */) | |||
| 852 | icon = value; | 878 | icon = value; |
| 853 | else if (EQ (key, QCactions)) | 879 | else if (EQ (key, QCactions)) |
| 854 | actions = value; | 880 | actions = value; |
| 881 | else if (EQ (key, QCtimeout)) | ||
| 882 | timeout = value; | ||
| 855 | else if (EQ (key, QCresident)) | 883 | else if (EQ (key, QCresident)) |
| 856 | resident = value; | 884 | resident = value; |
| 857 | else if (EQ (key, QCon_action)) | 885 | else if (EQ (key, QCon_action)) |
| @@ -874,16 +902,19 @@ usage: (android-notifications-notify &rest ARGS) */) | |||
| 874 | urgency = Qlow; | 902 | urgency = Qlow; |
| 875 | 903 | ||
| 876 | if (NILP (group)) | 904 | if (NILP (group)) |
| 877 | group = build_string ("Desktop Notifications"); | 905 | { |
| 906 | AUTO_STRING (format, "Desktop Notifications (%s importance)"); | ||
| 907 | group = CALLN (Fformat, format, urgency); | ||
| 908 | } | ||
| 878 | 909 | ||
| 879 | if (NILP (icon)) | 910 | if (NILP (icon)) |
| 880 | icon = build_string ("ic_dialog_alert"); | 911 | icon = default_icon; |
| 881 | else | 912 | else |
| 882 | CHECK_STRING (icon); | 913 | CHECK_STRING (icon); |
| 883 | 914 | ||
| 884 | return make_int (android_notifications_notify_1 (title, body, replaces_id, | 915 | return make_int (android_notifications_notify_1 (title, body, replaces_id, |
| 885 | group, icon, urgency, | 916 | group, icon, urgency, |
| 886 | actions, resident, | 917 | actions, timeout, resident, |
| 887 | action_cb, close_cb)); | 918 | action_cb, close_cb)); |
| 888 | } | 919 | } |
| 889 | 920 | ||
| @@ -1001,6 +1032,7 @@ syms_of_androidselect (void) | |||
| 1001 | DEFSYM (QCurgency, ":urgency"); | 1032 | DEFSYM (QCurgency, ":urgency"); |
| 1002 | DEFSYM (QCicon, ":icon"); | 1033 | DEFSYM (QCicon, ":icon"); |
| 1003 | DEFSYM (QCactions, ":actions"); | 1034 | DEFSYM (QCactions, ":actions"); |
| 1035 | DEFSYM (QCtimeout, ":timeout"); | ||
| 1004 | DEFSYM (QCresident, ":resident"); | 1036 | DEFSYM (QCresident, ":resident"); |
| 1005 | DEFSYM (QCon_action, ":on-action"); | 1037 | DEFSYM (QCon_action, ":on-action"); |
| 1006 | DEFSYM (QCon_close, ":on-close"); | 1038 | DEFSYM (QCon_close, ":on-close"); |