Fix MS-Windows tray notifications from different Emacs frames

* src/w32fns.c (EMACS_TRAY_NOTIFICATION_ID_INIT): Rename from
EMACS_TRAY_NOTIFICATION_ID; all users adjusted.
(last_tray_notification_id): New static variable.
(add_tray_notification): Advance 'last_tray_notification_id' for
each new notification; wrap around to the fixed initial value when
reached the maximum.  This allows Lisp programs track notifications
and remove them from the same frame from which they were created.
(Fw32_notification_notify, Fw32_notification_close): Doc fixes.

* doc/lispref/os.texi (Desktop Notifications): Update the
documentation of 'w32-notification-notify' and
'w32-notification-close'.

Bug#79400
This commit is contained in:
Eli Zaretskii 2025-10-11 14:00:09 +03:00
parent c723760f28
commit dcea973c04
2 changed files with 32 additions and 14 deletions

View file

@ -3255,9 +3255,10 @@ Note that versions of Windows before W2K support only @code{:icon} and
@code{:tip}. The other parameters can be passed, but they will be
ignored on those old systems.
There can be at most one active notification at any given time. An
active notification must be removed by calling
@code{w32-notification-close} before a new one can be shown.
There can be at most one active notification at any given time for each
Emacs frame. An active notification must be removed by calling
@code{w32-notification-close} before a new one can be shown for the same
frame.
@end defun
To remove the notification and its icon from the taskbar, use the
@ -3265,7 +3266,12 @@ following function:
@defun w32-notification-close id
This function removes the tray notification given by its unique
@var{id}.
@var{id}. The same Emacs frame which was the selected frame when the
notification was created must be selected when removing the
notification. A Lisp program which shows notifications must track which
frame corresponds to which notification @var{id}, and select that frame
when removing the notification. (When a frame is deleted, a
notification it created, if any, will be removed by MS-Windows.)
@end defun
@cindex desktop notifications, Haiku

View file

@ -10337,8 +10337,8 @@ typedef struct MY_NOTIFYICONDATAW {
#endif
#define EMACS_TRAY_NOTIFICATION_ID 42 /* arbitrary */
#define EMACS_NOTIFICATION_MSG (WM_APP + 1)
#define EMACS_TRAY_NOTIFICATION_ID_INIT 42 /* arbitrary */
#define EMACS_NOTIFICATION_MSG (WM_APP + 1)
enum NI_Severity {
Ni_None,
@ -10403,14 +10403,16 @@ utf8_mbslen_lim (const char *str, int lim)
return mblen;
}
static unsigned short last_tray_notification_id;
/* Low-level subroutine to show tray notifications. All strings are
supposed to be unibyte UTF-8 encoded by the caller. */
static EMACS_INT
static int
add_tray_notification (struct frame *f, const char *icon, const char *tip,
enum NI_Severity severity, unsigned timeout,
const char *title, const char *msg)
{
EMACS_INT retval = EMACS_TRAY_NOTIFICATION_ID;
int retval = -1;
if (FRAME_W32_P (f))
{
@ -10437,7 +10439,12 @@ add_tray_notification (struct frame *f, const char *icon, const char *tip,
else
nidw.cbSize = MYNOTIFYICONDATAW_V1_SIZE; /* < W2K */
nidw.hWnd = FRAME_W32_WINDOW (f);
nidw.uID = EMACS_TRAY_NOTIFICATION_ID;
if (!last_tray_notification_id)
last_tray_notification_id = EMACS_TRAY_NOTIFICATION_ID_INIT;
else
last_tray_notification_id++;
retval = last_tray_notification_id;
nidw.uID = last_tray_notification_id;
nidw.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_INFO;
nidw.uCallbackMessage = EMACS_NOTIFICATION_MSG;
if (!*icon)
@ -10660,16 +10667,19 @@ Note that versions of Windows before W2K support only `:icon' and `:tip'.
You can pass the other parameters, but they will be ignored on
those old systems.
There can be at most one active notification at any given time. An
active notification must be removed by calling `w32-notification-close'
before a new one can be shown.
There can be at most one active notification at any given time per each
Emacs frame. An active notification must be removed by calling the
function `w32-notification-close', with the same frame selected as the
one which was selected when the notification was created, before a new
one can be shown for the same frame. The caller must track which
notification was created from which frame, using the returned ID value.
usage: (w32-notification-notify &rest PARAMS) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
struct frame *f = SELECTED_FRAME ();
Lisp_Object arg_plist, lres;
EMACS_INT retval;
int retval;
char *icon, *tip, *title, *msg;
enum NI_Severity severity;
unsigned timeout = 0;
@ -10732,7 +10742,9 @@ usage: (w32-notification-notify &rest PARAMS) */)
DEFUN ("w32-notification-close",
Fw32_notification_close, Sw32_notification_close,
1, 1, 0,
doc: /* Remove the MS-Windows tray notification specified by its ID. */)
doc: /* Remove the MS-Windows tray notification specified by its ID.
The frame which was selected when the notification was created must
be selected when removing the notification. */)
(Lisp_Object id)
{
struct frame *f = SELECTED_FRAME ();