diff options
| author | Po Lu | 2023-08-17 08:34:32 +0000 |
|---|---|---|
| committer | Po Lu | 2023-08-17 08:34:32 +0000 |
| commit | 5856ea5e4e897f4cb5cd1c3c28d14b335fe5cf54 (patch) | |
| tree | e426f160e0f5480d93abad7844198eb8fb8fc79a | |
| parent | c1a45041d66fc479f9b7b94475236d1c2d5001fe (diff) | |
| download | emacs-5856ea5e4e897f4cb5cd1c3c28d14b335fe5cf54.tar.gz emacs-5856ea5e4e897f4cb5cd1c3c28d14b335fe5cf54.zip | |
Introduce support for Desktop Notifications on Haiku
* doc/lispref/os.texi (Desktop Notifications): Document Haiku
desktop notifications.
* etc/NEWS: Announce this change.
* lisp/org/org-clock.el (haiku-notifications-notify): New
declaration.
(org-show-notification): Employ that function.
* src/haiku_io.c (haiku_len) <NOTIFICATION_CLICK_EVENT>: Return
the length for this type of event.
* src/haiku_select.cc (my_team_id, be_display_notification): New
functions.
* src/haiku_support.cc (my_team_id, ArgvReceived): New
functions.
* src/haiku_support.h (enum haiku_event_type): New event type
NOTIFICATION_CLICK_EVENT.
(struct haiku_notification_click_event): New structure.
* src/haikuselect.c (haiku_notifications_notify_1)
(Fhaiku_notifications_notify): New functions.
(syms_of_haikuselect): Register new defsubr.
* src/haikuterm.c (haiku_read_socket):
* src/haikuselect.h:
* src/termhooks.h: Add new events for notification clicks on
Haiku.
| -rw-r--r-- | doc/lispref/os.texi | 35 | ||||
| -rw-r--r-- | etc/NEWS | 6 | ||||
| -rw-r--r-- | lisp/org/org-clock.el | 6 | ||||
| -rw-r--r-- | src/haiku_io.c | 2 | ||||
| -rw-r--r-- | src/haiku_select.cc | 146 | ||||
| -rw-r--r-- | src/haiku_support.cc | 54 | ||||
| -rw-r--r-- | src/haiku_support.h | 7 | ||||
| -rw-r--r-- | src/haikuselect.c | 125 | ||||
| -rw-r--r-- | src/haikuselect.h | 25 | ||||
| -rw-r--r-- | src/haikuterm.c | 13 | ||||
| -rw-r--r-- | src/termhooks.h | 6 |
11 files changed, 414 insertions, 11 deletions
diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index be8624e0fde..b6d34ae0a3d 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi | |||
| @@ -2850,7 +2850,9 @@ Emacs is restarted by the session manager. | |||
| 2850 | @cindex notifications, on desktop | 2850 | @cindex notifications, on desktop |
| 2851 | 2851 | ||
| 2852 | Emacs is able to send @dfn{notifications} on systems that support the | 2852 | Emacs is able to send @dfn{notifications} on systems that support the |
| 2853 | freedesktop.org Desktop Notifications Specification and on MS-Windows. | 2853 | freedesktop.org Desktop Notifications Specification, MS-Windows, and |
| 2854 | Haiku. | ||
| 2855 | |||
| 2854 | In order to use this functionality on POSIX hosts, Emacs must have | 2856 | In order to use this functionality on POSIX hosts, Emacs must have |
| 2855 | been compiled with D-Bus support, and the @code{notifications} library | 2857 | been compiled with D-Bus support, and the @code{notifications} library |
| 2856 | must be loaded. @xref{Top, , D-Bus,dbus,D-Bus integration in Emacs}. | 2858 | must be loaded. @xref{Top, , D-Bus,dbus,D-Bus integration in Emacs}. |
| @@ -3167,6 +3169,37 @@ This function removes the tray notification given by its unique | |||
| 3167 | @var{id}. | 3169 | @var{id}. |
| 3168 | @end defun | 3170 | @end defun |
| 3169 | 3171 | ||
| 3172 | @cindex desktop notifications, Haiku | ||
| 3173 | When Emacs runs under Haiku as a GUI program, it is also provides a | ||
| 3174 | restricted pastiche of the D-Bus desktop notifications interface | ||
| 3175 | previously addressed. The principle capabilities absent from the | ||
| 3176 | function detailed below are call-back functions such as | ||
| 3177 | @code{:actions}, @code{:on-action} and @code{:on-close}. | ||
| 3178 | |||
| 3179 | @defun haiku-notifications-notify &rest params | ||
| 3180 | This function sends a notification to the desktop notification server, | ||
| 3181 | incorporating a number of parameters that are akin to some of those | ||
| 3182 | accepted by @code{notifications-notify}. The parameters are: | ||
| 3183 | |||
| 3184 | @table @code | ||
| 3185 | @item :title @var{title} | ||
| 3186 | @item :body @var{body} | ||
| 3187 | @item :replaces-id @var{replaces-id} | ||
| 3188 | @item :urgency @var{urgency} | ||
| 3189 | These have the same meaning as they do when used in calls to | ||
| 3190 | @code{notifications-notify}. | ||
| 3191 | |||
| 3192 | @item :app-icon @var{app-icon} | ||
| 3193 | This should be the file name designating an image file to use as the | ||
| 3194 | icon for the notification displayed. If @code{nil}, the icon | ||
| 3195 | presented will instead be Emacs's app icon. | ||
| 3196 | @end table | ||
| 3197 | |||
| 3198 | Its return value is a number identifying the notification, which can | ||
| 3199 | be exploited as the @code{:replaces-id} parameter to a subsequent call | ||
| 3200 | to this function. | ||
| 3201 | @end defun | ||
| 3202 | |||
| 3170 | @node File Notifications | 3203 | @node File Notifications |
| 3171 | @section Notifications on File Changes | 3204 | @section Notifications on File Changes |
| 3172 | @cindex file notifications | 3205 | @cindex file notifications |
| @@ -784,6 +784,12 @@ See the "(elisp) Porting Old Advice" node for help converting them | |||
| 784 | to use 'advice-add' or 'define-advice' instead. | 784 | to use 'advice-add' or 'define-advice' instead. |
| 785 | 785 | ||
| 786 | +++ | 786 | +++ |
| 787 | ** Desktop notifications are now supported on the Haiku operating system. | ||
| 788 | The new function 'haiku-notifications-notify' provides a subset of the | ||
| 789 | capabilities of the 'notifications-notify' function in a manner | ||
| 790 | analogous to 'w32-notification-notify'. | ||
| 791 | |||
| 792 | +++ | ||
| 787 | ** New value 'if-regular' for the REPLACE argument to 'insert-file-contents'. | 793 | ** New value 'if-regular' for the REPLACE argument to 'insert-file-contents'. |
| 788 | It results in 'insert-file-contents' erasing the buffer instead of | 794 | It results in 'insert-file-contents' erasing the buffer instead of |
| 789 | preserving markers if the file being inserted is not a regular file, | 795 | preserving markers if the file being inserted is not a regular file, |
diff --git a/lisp/org/org-clock.el b/lisp/org/org-clock.el index b85ce6a6368..32ef0eb4291 100644 --- a/lisp/org/org-clock.el +++ b/lisp/org/org-clock.el | |||
| @@ -51,6 +51,7 @@ | |||
| 51 | (declare-function org-dynamic-block-define "org" (type func)) | 51 | (declare-function org-dynamic-block-define "org" (type func)) |
| 52 | (declare-function w32-notification-notify "w32fns.c" (&rest params)) | 52 | (declare-function w32-notification-notify "w32fns.c" (&rest params)) |
| 53 | (declare-function w32-notification-close "w32fns.c" (&rest params)) | 53 | (declare-function w32-notification-close "w32fns.c" (&rest params)) |
| 54 | (declare-function haiku-notifications-notify "haikufns.c") | ||
| 54 | 55 | ||
| 55 | (defvar org-frame-title-format-backup nil) | 56 | (defvar org-frame-title-format-backup nil) |
| 56 | (defvar org-state) | 57 | (defvar org-state) |
| @@ -855,6 +856,11 @@ use libnotify if available, or fall back on a message." | |||
| 855 | ((stringp org-show-notification-handler) | 856 | ((stringp org-show-notification-handler) |
| 856 | (start-process "emacs-timer-notification" nil | 857 | (start-process "emacs-timer-notification" nil |
| 857 | org-show-notification-handler notification)) | 858 | org-show-notification-handler notification)) |
| 859 | ((fboundp 'haiku-notifications-notify) | ||
| 860 | ;; N.B. timeouts are not available under Haiku. | ||
| 861 | (haiku-notifications-notify :title "Org mode message" | ||
| 862 | :body notification | ||
| 863 | :urgency 'low)) | ||
| 858 | ((fboundp 'w32-notification-notify) | 864 | ((fboundp 'w32-notification-notify) |
| 859 | (let ((id (w32-notification-notify | 865 | (let ((id (w32-notification-notify |
| 860 | :title "Org mode message" | 866 | :title "Org mode message" |
diff --git a/src/haiku_io.c b/src/haiku_io.c index 4f1b1435b4b..c6d7108bf49 100644 --- a/src/haiku_io.c +++ b/src/haiku_io.c | |||
| @@ -111,6 +111,8 @@ haiku_len (enum haiku_event_type type) | |||
| 111 | return sizeof (struct haiku_clipboard_changed_event); | 111 | return sizeof (struct haiku_clipboard_changed_event); |
| 112 | case FONT_CHANGE_EVENT: | 112 | case FONT_CHANGE_EVENT: |
| 113 | return sizeof (struct haiku_font_change_event); | 113 | return sizeof (struct haiku_font_change_event); |
| 114 | case NOTIFICATION_CLICK_EVENT: | ||
| 115 | return sizeof (struct haiku_notification_click_event); | ||
| 114 | } | 116 | } |
| 115 | 117 | ||
| 116 | emacs_abort (); | 118 | emacs_abort (); |
diff --git a/src/haiku_select.cc b/src/haiku_select.cc index fe46075a007..76e2d829204 100644 --- a/src/haiku_select.cc +++ b/src/haiku_select.cc | |||
| @@ -17,15 +17,24 @@ You should have received a copy of the GNU General Public License | |||
| 17 | along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | 17 | along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ |
| 18 | 18 | ||
| 19 | #include <config.h> | 19 | #include <config.h> |
| 20 | #include <intprops.h> | ||
| 20 | 21 | ||
| 21 | #include <Application.h> | 22 | #include <Application.h> |
| 23 | #include <Bitmap.h> | ||
| 22 | #include <Clipboard.h> | 24 | #include <Clipboard.h> |
| 25 | #include <Entry.h> | ||
| 23 | #include <Message.h> | 26 | #include <Message.h> |
| 27 | #include <Notification.h> | ||
| 28 | #include <OS.h> | ||
| 24 | #include <Path.h> | 29 | #include <Path.h> |
| 25 | #include <Entry.h> | 30 | #include <String.h> |
| 31 | |||
| 32 | #include <translation/TranslationUtils.h> | ||
| 26 | 33 | ||
| 27 | #include <cstdlib> | 34 | #include <cstdlib> |
| 28 | #include <cstring> | 35 | #include <cstring> |
| 36 | #include <cstdint> | ||
| 37 | #include <cstdio> | ||
| 29 | 38 | ||
| 30 | #include "haikuselect.h" | 39 | #include "haikuselect.h" |
| 31 | 40 | ||
| @@ -58,6 +67,10 @@ static bool owned_secondary; | |||
| 58 | /* And the clipboard. */ | 67 | /* And the clipboard. */ |
| 59 | static bool owned_clipboard; | 68 | static bool owned_clipboard; |
| 60 | 69 | ||
| 70 | |||
| 71 | |||
| 72 | /* C++ clipboard support. */ | ||
| 73 | |||
| 61 | static BClipboard * | 74 | static BClipboard * |
| 62 | get_clipboard_object (enum haiku_clipboard clipboard) | 75 | get_clipboard_object (enum haiku_clipboard clipboard) |
| 63 | { | 76 | { |
| @@ -517,3 +530,134 @@ be_get_clipboard_count (enum haiku_clipboard id) | |||
| 517 | clipboard = get_clipboard_object (id); | 530 | clipboard = get_clipboard_object (id); |
| 518 | return clipboard->SystemCount (); | 531 | return clipboard->SystemCount (); |
| 519 | } | 532 | } |
| 533 | |||
| 534 | |||
| 535 | |||
| 536 | /* C++ notifications support. | ||
| 537 | |||
| 538 | Desktop notifications on Haiku lack some of the features furnished | ||
| 539 | by notifications.el, specifically displaying multiple titled | ||
| 540 | actions within a single notification, sending callbacks when the | ||
| 541 | notification is dismissed, and providing a timeout after which the | ||
| 542 | notification is hidden. | ||
| 543 | |||
| 544 | Other features, such as notification categories and identifiers, | ||
| 545 | have clean straightforward relationships with their counterparts in | ||
| 546 | notifications.el. */ | ||
| 547 | |||
| 548 | /* The last notification ID allocated. */ | ||
| 549 | static intmax_t last_notification_id; | ||
| 550 | |||
| 551 | /* Return the `enum notification_type' for TYPE. TYPE is the TYPE | ||
| 552 | argument to a call to `be_display_notification'. */ | ||
| 553 | |||
| 554 | static enum notification_type | ||
| 555 | type_for_type (int type) | ||
| 556 | { | ||
| 557 | switch (type) | ||
| 558 | { | ||
| 559 | case 0: | ||
| 560 | return B_INFORMATION_NOTIFICATION; | ||
| 561 | |||
| 562 | case 1: | ||
| 563 | return B_IMPORTANT_NOTIFICATION; | ||
| 564 | |||
| 565 | case 2: | ||
| 566 | return B_ERROR_NOTIFICATION; | ||
| 567 | } | ||
| 568 | |||
| 569 | abort (); | ||
| 570 | } | ||
| 571 | |||
| 572 | /* Return the ID of this team. */ | ||
| 573 | |||
| 574 | static team_id | ||
| 575 | my_team_id (void) | ||
| 576 | { | ||
| 577 | thread_id id; | ||
| 578 | thread_info info; | ||
| 579 | |||
| 580 | id = find_thread (NULL); | ||
| 581 | get_thread_info (id, &info); | ||
| 582 | |||
| 583 | return info.team; | ||
| 584 | } | ||
| 585 | |||
| 586 | /* Display a desktop notification and return its identifier. | ||
| 587 | |||
| 588 | TITLE is the title text of the notification, encoded as UTF-8 text. | ||
| 589 | |||
| 590 | BODY is the text to be displayed within the body of the | ||
| 591 | notification. | ||
| 592 | |||
| 593 | SUPERSEDES is the identifier of a previous notification to replace, | ||
| 594 | or -1 if a new notification should be displayed. | ||
| 595 | |||
| 596 | TYPE states the urgency of the notification. If 0, the | ||
| 597 | notification is displayed without special decoration. If 1, the | ||
| 598 | notification is displayed with a blue band to its left, identifying | ||
| 599 | it as a notification of medium importance. If 2, the notification | ||
| 600 | is displayed with a red band to its left, marking it as one of | ||
| 601 | critical importance. | ||
| 602 | |||
| 603 | ICON is the name of a file containing the icon of the notification, | ||
| 604 | or NULL, in which case Emacs's app icon will be displayed. */ | ||
| 605 | |||
| 606 | intmax_t | ||
| 607 | be_display_notification (const char *title, const char *body, | ||
| 608 | intmax_t supersedes, int type, const char *icon) | ||
| 609 | { | ||
| 610 | intmax_t id; | ||
| 611 | BNotification notification (type_for_type (type)); | ||
| 612 | char buffer[INT_STRLEN_BOUND (team_id) | ||
| 613 | + INT_STRLEN_BOUND (intmax_t) | ||
| 614 | + sizeof "."]; | ||
| 615 | BBitmap *bitmap; | ||
| 616 | |||
| 617 | if (supersedes < 0) | ||
| 618 | { | ||
| 619 | /* SUPERSEDES hasn't been provided, so allocate a new | ||
| 620 | notification ID. */ | ||
| 621 | |||
| 622 | INT_ADD_WRAPV (last_notification_id, 1, | ||
| 623 | &last_notification_id); | ||
| 624 | id = last_notification_id; | ||
| 625 | } | ||
| 626 | else | ||
| 627 | id = supersedes; | ||
| 628 | |||
| 629 | /* Set the title and body text. */ | ||
| 630 | notification.SetTitle (title); | ||
| 631 | notification.SetContent (body); | ||
| 632 | |||
| 633 | /* Derive the notification ID from the ID of this team, so as to | ||
| 634 | avoid abrogating notifications from other Emacs sessions. */ | ||
| 635 | sprintf (buffer, "%d.%jd", my_team_id (), id); | ||
| 636 | notification.SetMessageID (BString (buffer)); | ||
| 637 | |||
| 638 | /* Now set the bitmap icon, if given. */ | ||
| 639 | |||
| 640 | if (icon) | ||
| 641 | { | ||
| 642 | bitmap = BTranslationUtils::GetBitmap (icon); | ||
| 643 | |||
| 644 | if (bitmap) | ||
| 645 | { | ||
| 646 | notification.SetIcon (bitmap); | ||
| 647 | delete bitmap; | ||
| 648 | } | ||
| 649 | } | ||
| 650 | |||
| 651 | /* After this, Emacs::ArgvReceived should be called when the | ||
| 652 | notification is clicked. Lamentably, this does not come about, | ||
| 653 | probably because arguments are only passed to applications if | ||
| 654 | they are not yet running. */ | ||
| 655 | #if 0 | ||
| 656 | notification.SetOnClickApp ("application/x-vnd.GNU-emacs"); | ||
| 657 | notification.AddOnClickArg (BString ("-Notification,") += buffer); | ||
| 658 | #endif /* 0 */ | ||
| 659 | |||
| 660 | /* Finally, send the notification. */ | ||
| 661 | notification.Send (); | ||
| 662 | return id; | ||
| 663 | } | ||
diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 28d8fae39b7..d5649e4d2ce 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc | |||
| @@ -581,6 +581,24 @@ public: | |||
| 581 | } | 581 | } |
| 582 | }; | 582 | }; |
| 583 | 583 | ||
| 584 | #if 0 | ||
| 585 | |||
| 586 | /* Return the ID of this team. */ | ||
| 587 | |||
| 588 | static team_id | ||
| 589 | my_team_id (void) | ||
| 590 | { | ||
| 591 | thread_id id; | ||
| 592 | thread_info info; | ||
| 593 | |||
| 594 | id = find_thread (NULL); | ||
| 595 | get_thread_info (id, &info); | ||
| 596 | |||
| 597 | return info.team; | ||
| 598 | } | ||
| 599 | |||
| 600 | #endif /* 0 */ | ||
| 601 | |||
| 584 | class Emacs : public BApplication | 602 | class Emacs : public BApplication |
| 585 | { | 603 | { |
| 586 | public: | 604 | public: |
| @@ -621,7 +639,8 @@ public: | |||
| 621 | { | 639 | { |
| 622 | BAlert *about = new BAlert (PACKAGE_NAME, | 640 | BAlert *about = new BAlert (PACKAGE_NAME, |
| 623 | PACKAGE_STRING | 641 | PACKAGE_STRING |
| 624 | "\nThe extensible, self-documenting, real-time display editor.", | 642 | "\nThe extensible, self-documenting, " |
| 643 | "real-time display editor.", | ||
| 625 | "Close"); | 644 | "Close"); |
| 626 | about->Go (); | 645 | about->Go (); |
| 627 | } | 646 | } |
| @@ -674,6 +693,39 @@ public: | |||
| 674 | else | 693 | else |
| 675 | BApplication::MessageReceived (msg); | 694 | BApplication::MessageReceived (msg); |
| 676 | } | 695 | } |
| 696 | |||
| 697 | /* The code below doesn't function; see `be_display_notification' | ||
| 698 | for further specifics. */ | ||
| 699 | |||
| 700 | #if 0 | ||
| 701 | void | ||
| 702 | ArgvReceived (int32 argc, char **argv) | ||
| 703 | { | ||
| 704 | struct haiku_notification_click_event rq; | ||
| 705 | intmax_t id; | ||
| 706 | team_id team; | ||
| 707 | |||
| 708 | /* ArgvReceived is called after Emacs is first started, with each | ||
| 709 | command line argument passed to Emacs. It is, moreover, called | ||
| 710 | with ARGC set to 1 and ARGV[0] a string starting with | ||
| 711 | -Notification, after a notification is clicked. This string | ||
| 712 | both incorporates the team ID and the notification ID. */ | ||
| 713 | |||
| 714 | if (argc == 1 | ||
| 715 | && sscanf (argv[0], "-Notification,%d.%jd", &team, &id) == 2) | ||
| 716 | { | ||
| 717 | /* Since this is a valid notification message, generate an | ||
| 718 | event if the team ID matches. */ | ||
| 719 | if (team == my_team_id ()) | ||
| 720 | { | ||
| 721 | rq.id = id; | ||
| 722 | haiku_write (NOTIFICATION_CLICK_EVENT, &rq); | ||
| 723 | } | ||
| 724 | } | ||
| 725 | |||
| 726 | BApplication::ArgvReceived (argc, argv); | ||
| 727 | } | ||
| 728 | #endif /* 0 */ | ||
| 677 | }; | 729 | }; |
| 678 | 730 | ||
| 679 | class EmacsWindow : public BWindow | 731 | class EmacsWindow : public BWindow |
diff --git a/src/haiku_support.h b/src/haiku_support.h index 564f61f57c7..5c22eb3b0db 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h | |||
| @@ -116,6 +116,7 @@ enum haiku_event_type | |||
| 116 | MENU_BAR_LEFT, | 116 | MENU_BAR_LEFT, |
| 117 | CLIPBOARD_CHANGED_EVENT, | 117 | CLIPBOARD_CHANGED_EVENT, |
| 118 | FONT_CHANGE_EVENT, | 118 | FONT_CHANGE_EVENT, |
| 119 | NOTIFICATION_CLICK_EVENT, | ||
| 119 | }; | 120 | }; |
| 120 | 121 | ||
| 121 | struct haiku_clipboard_changed_event | 122 | struct haiku_clipboard_changed_event |
| @@ -464,6 +465,12 @@ struct haiku_font_change_event | |||
| 464 | enum haiku_what_font what; | 465 | enum haiku_what_font what; |
| 465 | }; | 466 | }; |
| 466 | 467 | ||
| 468 | struct haiku_notification_click_event | ||
| 469 | { | ||
| 470 | /* ID uniquely designating a single notification. */ | ||
| 471 | intmax_t id; | ||
| 472 | }; | ||
| 473 | |||
| 467 | struct haiku_session_manager_reply | 474 | struct haiku_session_manager_reply |
| 468 | { | 475 | { |
| 469 | bool quit_reply; | 476 | bool quit_reply; |
diff --git a/src/haikuselect.c b/src/haikuselect.c index b57c336c264..608b8e8fe30 100644 --- a/src/haikuselect.c +++ b/src/haikuselect.c | |||
| @@ -1255,6 +1255,120 @@ haiku_start_watching_selections (void) | |||
| 1255 | be_start_watching_selection (CLIPBOARD_SECONDARY); | 1255 | be_start_watching_selection (CLIPBOARD_SECONDARY); |
| 1256 | } | 1256 | } |
| 1257 | 1257 | ||
| 1258 | |||
| 1259 | |||
| 1260 | /* Notification support. */ | ||
| 1261 | |||
| 1262 | static intmax_t | ||
| 1263 | haiku_notifications_notify_1 (Lisp_Object title, Lisp_Object body, | ||
| 1264 | Lisp_Object replaces_id, | ||
| 1265 | Lisp_Object app_icon, Lisp_Object urgency) | ||
| 1266 | { | ||
| 1267 | int type; | ||
| 1268 | intmax_t supersedes; | ||
| 1269 | const char *icon; | ||
| 1270 | |||
| 1271 | if (EQ (urgency, Qlow)) | ||
| 1272 | type = 0; | ||
| 1273 | else if (EQ (urgency, Qnormal)) | ||
| 1274 | type = 1; | ||
| 1275 | else if (EQ (urgency, Qcritical)) | ||
| 1276 | type = 2; | ||
| 1277 | else | ||
| 1278 | signal_error ("Invalid notification type provided", urgency); | ||
| 1279 | |||
| 1280 | supersedes = -1; | ||
| 1281 | |||
| 1282 | if (!NILP (replaces_id)) | ||
| 1283 | { | ||
| 1284 | CHECK_INTEGER (replaces_id); | ||
| 1285 | if (!integer_to_intmax (replaces_id, &supersedes)) | ||
| 1286 | supersedes = -1; | ||
| 1287 | } | ||
| 1288 | |||
| 1289 | icon = NULL; | ||
| 1290 | |||
| 1291 | if (!NILP (app_icon)) | ||
| 1292 | icon = SSDATA (ENCODE_FILE (app_icon)); | ||
| 1293 | |||
| 1294 | /* GC should not transpire from here onwards. */ | ||
| 1295 | return be_display_notification (SSDATA (title), SSDATA (body), | ||
| 1296 | supersedes, type, icon); | ||
| 1297 | } | ||
| 1298 | |||
| 1299 | DEFUN ("haiku-notifications-notify", Fhaiku_notifications_notify, | ||
| 1300 | Shaiku_notifications_notify, 0, MANY, 0, doc: | ||
| 1301 | /* Display a desktop notification. | ||
| 1302 | ARGS must contain keywords followed by values. Each of the following | ||
| 1303 | keywords is understood: | ||
| 1304 | |||
| 1305 | :title The notification title. | ||
| 1306 | :body The notification body. | ||
| 1307 | :replaces-id The ID of a previous notification to supersede. | ||
| 1308 | :app-icon The file name of the notification's icon, if any. | ||
| 1309 | :urgency One of the symbols `low', `normal' or `critical', | ||
| 1310 | specifying the importance of the notification. | ||
| 1311 | |||
| 1312 | :title and :body must be provided. Value is an integer (fixnum or | ||
| 1313 | bignum) identifying the notification displayed. | ||
| 1314 | |||
| 1315 | usage: (haiku-notifications-notify &rest ARGS) */) | ||
| 1316 | (ptrdiff_t nargs, Lisp_Object *args) | ||
| 1317 | { | ||
| 1318 | Lisp_Object title, body, replaces_id, app_icon, urgency; | ||
| 1319 | Lisp_Object key, value; | ||
| 1320 | ptrdiff_t i; | ||
| 1321 | |||
| 1322 | /* First, clear each of the variables above. */ | ||
| 1323 | title = body = replaces_id = app_icon = urgency = Qnil; | ||
| 1324 | |||
| 1325 | /* If NARGS is odd, error. */ | ||
| 1326 | |||
| 1327 | if (nargs & 1) | ||
| 1328 | error ("Odd number of arguments in call to `haiku-notifications-notify'"); | ||
| 1329 | |||
| 1330 | /* Next, iterate through ARGS, searching for arguments. */ | ||
| 1331 | |||
| 1332 | for (i = 0; i < nargs; i += 2) | ||
| 1333 | { | ||
| 1334 | key = args[i]; | ||
| 1335 | value = args[i + 1]; | ||
| 1336 | |||
| 1337 | if (EQ (key, QCtitle)) | ||
| 1338 | title = value; | ||
| 1339 | else if (EQ (key, QCbody)) | ||
| 1340 | body = value; | ||
| 1341 | else if (EQ (key, QCreplaces_id)) | ||
| 1342 | replaces_id = value; | ||
| 1343 | else if (EQ (key, QCapp_icon)) | ||
| 1344 | app_icon = value; | ||
| 1345 | else if (EQ (key, QCurgency)) | ||
| 1346 | urgency = value; | ||
| 1347 | } | ||
| 1348 | |||
| 1349 | /* Demand at least TITLE and BODY be present. */ | ||
| 1350 | |||
| 1351 | if (NILP (title) || NILP (body)) | ||
| 1352 | error ("Title or body not provided"); | ||
| 1353 | |||
| 1354 | /* Now check the type and possibly expand each non-nil argument. */ | ||
| 1355 | |||
| 1356 | CHECK_STRING (title); | ||
| 1357 | title = ENCODE_UTF_8 (title); | ||
| 1358 | CHECK_STRING (body); | ||
| 1359 | body = ENCODE_UTF_8 (body); | ||
| 1360 | |||
| 1361 | if (NILP (urgency)) | ||
| 1362 | urgency = Qlow; | ||
| 1363 | |||
| 1364 | if (!NILP (app_icon)) | ||
| 1365 | app_icon = Fexpand_file_name (app_icon, Qnil); | ||
| 1366 | |||
| 1367 | return make_int (haiku_notifications_notify_1 (title, body, | ||
| 1368 | replaces_id, | ||
| 1369 | app_icon, urgency)); | ||
| 1370 | } | ||
| 1371 | |||
| 1258 | void | 1372 | void |
| 1259 | syms_of_haikuselect (void) | 1373 | syms_of_haikuselect (void) |
| 1260 | { | 1374 | { |
| @@ -1312,6 +1426,16 @@ keyboard modifiers currently held down. */); | |||
| 1312 | DEFSYM (Qdouble, "double"); | 1426 | DEFSYM (Qdouble, "double"); |
| 1313 | DEFSYM (Qalready_running, "already-running"); | 1427 | DEFSYM (Qalready_running, "already-running"); |
| 1314 | 1428 | ||
| 1429 | DEFSYM (QCtitle, ":title"); | ||
| 1430 | DEFSYM (QCbody, ":body"); | ||
| 1431 | DEFSYM (QCreplaces_id, ":replaces-id"); | ||
| 1432 | DEFSYM (QCapp_icon, ":app-icon"); | ||
| 1433 | DEFSYM (QCurgency, ":urgency"); | ||
| 1434 | |||
| 1435 | DEFSYM (Qlow, "low"); | ||
| 1436 | DEFSYM (Qnormal, "normal"); | ||
| 1437 | DEFSYM (Qcritical, "critical"); | ||
| 1438 | |||
| 1315 | defsubr (&Shaiku_selection_data); | 1439 | defsubr (&Shaiku_selection_data); |
| 1316 | defsubr (&Shaiku_selection_timestamp); | 1440 | defsubr (&Shaiku_selection_timestamp); |
| 1317 | defsubr (&Shaiku_selection_put); | 1441 | defsubr (&Shaiku_selection_put); |
| @@ -1320,6 +1444,7 @@ keyboard modifiers currently held down. */); | |||
| 1320 | defsubr (&Shaiku_roster_launch); | 1444 | defsubr (&Shaiku_roster_launch); |
| 1321 | defsubr (&Shaiku_write_node_attribute); | 1445 | defsubr (&Shaiku_write_node_attribute); |
| 1322 | defsubr (&Shaiku_send_message); | 1446 | defsubr (&Shaiku_send_message); |
| 1447 | defsubr (&Shaiku_notifications_notify); | ||
| 1323 | 1448 | ||
| 1324 | haiku_dnd_frame = NULL; | 1449 | haiku_dnd_frame = NULL; |
| 1325 | } | 1450 | } |
diff --git a/src/haikuselect.h b/src/haikuselect.h index 28a1682e587..c117a2ab4f9 100644 --- a/src/haikuselect.h +++ b/src/haikuselect.h | |||
| @@ -21,9 +21,11 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 21 | 21 | ||
| 22 | #ifdef __cplusplus | 22 | #ifdef __cplusplus |
| 23 | #include <cstdio> | 23 | #include <cstdio> |
| 24 | #else | 24 | #include <cstdint> |
| 25 | #else /* !__cplusplus */ | ||
| 25 | #include <stdio.h> | 26 | #include <stdio.h> |
| 26 | #endif | 27 | #include <stdint.h> |
| 28 | #endif /* __cplusplus */ | ||
| 27 | 29 | ||
| 28 | #include <SupportDefs.h> | 30 | #include <SupportDefs.h> |
| 29 | 31 | ||
| @@ -37,15 +39,16 @@ enum haiku_clipboard | |||
| 37 | #ifdef __cplusplus | 39 | #ifdef __cplusplus |
| 38 | extern "C" | 40 | extern "C" |
| 39 | { | 41 | { |
| 40 | #endif | 42 | #endif /* __cplusplus */ |
| 41 | /* Defined in haikuselect.c. */ | 43 | /* Defined in haikuselect.c. */ |
| 42 | extern void haiku_selection_disowned (enum haiku_clipboard, int64); | 44 | extern void haiku_selection_disowned (enum haiku_clipboard, int64); |
| 43 | 45 | ||
| 44 | /* Defined in haiku_select.cc. */ | 46 | /* Defined in haiku_select.cc. */ |
| 45 | extern void be_clipboard_init (void); | 47 | extern void be_clipboard_init (void); |
| 46 | extern char *be_find_clipboard_data (enum haiku_clipboard, const char *, ssize_t *); | 48 | extern char *be_find_clipboard_data (enum haiku_clipboard, const char *, |
| 47 | extern void be_set_clipboard_data (enum haiku_clipboard, const char *, const char *, | 49 | ssize_t *); |
| 48 | ssize_t, bool); | 50 | extern void be_set_clipboard_data (enum haiku_clipboard, const char *, |
| 51 | const char *, ssize_t, bool); | ||
| 49 | extern bool be_clipboard_owner_p (enum haiku_clipboard); | 52 | extern bool be_clipboard_owner_p (enum haiku_clipboard); |
| 50 | extern void be_update_clipboard_count (enum haiku_clipboard); | 53 | extern void be_update_clipboard_count (enum haiku_clipboard); |
| 51 | 54 | ||
| @@ -58,7 +61,8 @@ extern uint32 be_get_message_type (void *); | |||
| 58 | extern void be_set_message_type (void *, uint32); | 61 | extern void be_set_message_type (void *, uint32); |
| 59 | extern void *be_get_message_message (void *, const char *, int32); | 62 | extern void *be_get_message_message (void *, const char *, int32); |
| 60 | extern void *be_create_simple_message (void); | 63 | extern void *be_create_simple_message (void); |
| 61 | extern int be_add_message_data (void *, const char *, int32, const void *, ssize_t); | 64 | extern int be_add_message_data (void *, const char *, int32, const void *, |
| 65 | ssize_t); | ||
| 62 | extern int be_add_refs_data (void *, const char *, const char *); | 66 | extern int be_add_refs_data (void *, const char *, const char *); |
| 63 | extern int be_add_point_data (void *, const char *, float, float); | 67 | extern int be_add_point_data (void *, const char *, float, float); |
| 64 | extern int be_add_message_message (void *, const char *, void *); | 68 | extern int be_add_message_message (void *, const char *, void *); |
| @@ -69,9 +73,14 @@ extern void be_start_watching_selection (enum haiku_clipboard); | |||
| 69 | extern bool be_selection_outdated_p (enum haiku_clipboard, int64); | 73 | extern bool be_selection_outdated_p (enum haiku_clipboard, int64); |
| 70 | extern int64 be_get_clipboard_count (enum haiku_clipboard); | 74 | extern int64 be_get_clipboard_count (enum haiku_clipboard); |
| 71 | 75 | ||
| 76 | |||
| 77 | |||
| 78 | extern intmax_t be_display_notification (const char *, const char *, | ||
| 79 | intmax_t, int, const char *); | ||
| 80 | |||
| 72 | #ifdef __cplusplus | 81 | #ifdef __cplusplus |
| 73 | }; | 82 | }; |
| 74 | #endif | 83 | #endif /* __cplusplus */ |
| 75 | #endif /* _HAIKU_SELECT_H_ */ | 84 | #endif /* _HAIKU_SELECT_H_ */ |
| 76 | 85 | ||
| 77 | // Local Variables: | 86 | // Local Variables: |
diff --git a/src/haikuterm.c b/src/haikuterm.c index ed28a806ff2..70984936bf9 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c | |||
| @@ -4042,6 +4042,19 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 4042 | handled in Lisp. */ | 4042 | handled in Lisp. */ |
| 4043 | haiku_handle_font_change_event (buf, &inev); | 4043 | haiku_handle_font_change_event (buf, &inev); |
| 4044 | break; | 4044 | break; |
| 4045 | |||
| 4046 | case NOTIFICATION_CLICK_EVENT: | ||
| 4047 | /* This code doesn't function, but the why is unknown. */ | ||
| 4048 | #if 0 | ||
| 4049 | { | ||
| 4050 | struct haiku_notification_click_event *b = buf; | ||
| 4051 | |||
| 4052 | inev.kind = NOTIFICATION_CLICKED_EVENT; | ||
| 4053 | inev.arg = make_int (b->id); | ||
| 4054 | break; | ||
| 4055 | } | ||
| 4056 | #endif /* 0 */ | ||
| 4057 | |||
| 4045 | case KEY_UP: | 4058 | case KEY_UP: |
| 4046 | case DUMMY_EVENT: | 4059 | case DUMMY_EVENT: |
| 4047 | default: | 4060 | default: |
diff --git a/src/termhooks.h b/src/termhooks.h index d978819aeca..6bf507aae33 100644 --- a/src/termhooks.h +++ b/src/termhooks.h | |||
| @@ -337,6 +337,12 @@ enum event_kind | |||
| 337 | monitor configuration changed. .timestamp gives the time on | 337 | monitor configuration changed. .timestamp gives the time on |
| 338 | which the monitors changed. */ | 338 | which the monitors changed. */ |
| 339 | , MONITORS_CHANGED_EVENT | 339 | , MONITORS_CHANGED_EVENT |
| 340 | |||
| 341 | #ifdef HAVE_HAIKU | ||
| 342 | /* In a NOTIFICATION_CLICKED_EVENT, .arg is an integer identifying | ||
| 343 | the notification that was clicked. */ | ||
| 344 | , NOTIFICATION_CLICKED_EVENT | ||
| 345 | #endif /* HAVE_HAIKU */ | ||
| 340 | }; | 346 | }; |
| 341 | 347 | ||
| 342 | /* Bit width of an enum event_kind tag at the start of structs and unions. */ | 348 | /* Bit width of an enum event_kind tag at the start of structs and unions. */ |