mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-29 08:31:35 -08:00
Implement tray notifications for MS-Windows
* src/w32fns.c (MY_NOTIFYICONDATAW): New typedef. (NOTIFYICONDATAW_V1_SIZE, NOTIFYICONDATAW_V2_SIZE) (NOTIFYICONDATAW_V3_SIZE, NIF_INFO, NIIF_NONE, NIIF_INFO) (NIIF_WARNING, NIIF_ERROR, EMACS_TRAY_NOTIFICATION_ID) (EMACS_NOTIFICATION_MSG): New macros. (NI_Severity): New enumeration. (get_dll_version, utf8_mbslen_lim, add_tray_notification) (delete_tray_notification, Fw32_notification_notify) (Fw32_notification_close): New functions. (syms_of_w32fns): Defsubr functions exposed to Lisp. DEFSYM keywords used by w32-notification-notify. * doc/lispref/os.texi (Desktop Notifications): Describe the native w32 tray notifications.
This commit is contained in:
parent
ef75c3b56b
commit
9d43941569
2 changed files with 562 additions and 4 deletions
|
|
@ -2323,10 +2323,11 @@ Emacs is restarted by the session manager.
|
|||
@cindex notifications, on desktop
|
||||
|
||||
Emacs is able to send @dfn{notifications} on systems that support the
|
||||
freedesktop.org Desktop Notifications Specification. In order to use
|
||||
this functionality, Emacs must have been compiled with D-Bus support,
|
||||
and the @code{notifications} library must be loaded. @xref{Top, ,
|
||||
D-Bus,dbus,D-Bus integration in Emacs}.
|
||||
freedesktop.org Desktop Notifications Specification and on MS-Windows.
|
||||
In order to use this functionality on Posix hosts, Emacs must have
|
||||
been compiled with D-Bus support, and the @code{notifications} library
|
||||
must be loaded. @xref{Top, , D-Bus,dbus,D-Bus integration in Emacs}.
|
||||
The following function is supported when D-Bus support is available:
|
||||
|
||||
@defun notifications-notify &rest params
|
||||
This function sends a notification to the desktop via D-Bus,
|
||||
|
|
@ -2559,6 +2560,85 @@ If @var{spec_version} is @code{nil}, the server supports a
|
|||
specification prior to @samp{"1.0"}.
|
||||
@end defun
|
||||
|
||||
@cindex tray notifications, MS-Windows
|
||||
When Emacs runs on MS-Windows as a GUI session, it supports a small
|
||||
subset of the D-Bus notifications functionality via a native
|
||||
primitive:
|
||||
|
||||
@defun w32-notification-notify &rest params
|
||||
This function displays an MS-Windows tray notification as specified by
|
||||
@var{params}. MS-Windows tray notifications are displayed in a
|
||||
balloon from an icon in the notification area of the taskbar.
|
||||
|
||||
Value is the integer unique ID of the notification that can be used to
|
||||
remove the notification using @code{w32-notification-close}, described
|
||||
below. If the function fails, the return value is @code{nil}.
|
||||
|
||||
The arguments @var{params} are specified as keyword/value pairs. All the
|
||||
parameters are optional, but if no parameters are specified, the
|
||||
function will do nothing and return @code{nil}.
|
||||
|
||||
The following parameters are supported:
|
||||
|
||||
@table @code
|
||||
@item :icon @var{icon}
|
||||
Display @var{icon} in the system tray. If @var{icon} is a string, it
|
||||
should specify a file name from which to load the icon; the specified
|
||||
file should be a @file{.ico} Windows icon file. If @var{icon} is not
|
||||
a string, or if this parameter is not specified, the standard Emacs
|
||||
icon will be used.
|
||||
|
||||
@item :tip @var{tip}
|
||||
Use @var{tip} as the tooltip for the notification. If @var{tip} is a
|
||||
string, this is the text of a tooltip that will be shown when the
|
||||
mouse pointer hovers over the tray icon added by the notification. If
|
||||
@var{tip} is not a string, or if this parameter is not specified, the
|
||||
default tooltip text is @samp{Emacs notification}. The tooltip text can
|
||||
be up to 127 characters long (63 on Windows versions before W2K).
|
||||
Longer strings will be truncated.
|
||||
|
||||
@item :level @var{level}
|
||||
Notification severity level, one of @code{info}, @code{warning}, or
|
||||
@code{error}. If given, the value determines the icon displayed to the
|
||||
left of the notification title, but only if the @code{:title} parameter
|
||||
(see below) is also specified and is a string.
|
||||
|
||||
@item :timeout @var{timeout}
|
||||
@var{timeout} is the time in seconds after which the notification
|
||||
disappears. The value can be integer or floating-point. This is
|
||||
ignored on Vista and later systems, where the duration is fixed at 9
|
||||
sec and can only be customized via system-wide Accessibility settings.
|
||||
|
||||
@item :title @var{title}
|
||||
The title of the notification. If @var{title} is a string, it is
|
||||
displayed in a larger font immediately above the body text. The title
|
||||
text can be up to 63 characters long; longer text will be truncated.
|
||||
|
||||
@item :body @var{body}
|
||||
The body of the notification. If @var{body} is a string, it specifies
|
||||
the text of the notification message. Use embedded newlines to
|
||||
control how the text is broken into lines. The body text can be up to
|
||||
255 characters long, and will be truncated if it's longer. Unlike
|
||||
with D-Bus, the body text should be plain text, with no markup.
|
||||
@end table
|
||||
|
||||
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.
|
||||
@end defun
|
||||
|
||||
To remove the notification and its icon from the taskbar, use the
|
||||
following function:
|
||||
|
||||
@defun w32-notification-close id
|
||||
This function removes the tray notification given by its unique
|
||||
@var{id}.
|
||||
@end defun
|
||||
|
||||
@node File Notifications
|
||||
@section Notifications on File Changes
|
||||
@cindex file notifications
|
||||
|
|
|
|||
478
src/w32fns.c
478
src/w32fns.c
|
|
@ -55,6 +55,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#include <commctrl.h>
|
||||
#include <commdlg.h>
|
||||
#include <shellapi.h>
|
||||
#include <shlwapi.h>
|
||||
#include <ctype.h>
|
||||
#include <winspool.h>
|
||||
#include <objbase.h>
|
||||
|
|
@ -8755,6 +8756,473 @@ Internal use only. */)
|
|||
return menubar_in_use ? Qt : Qnil;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Tray notifications
|
||||
***********************************************************************/
|
||||
/* A private struct declaration to avoid compile-time limits. */
|
||||
typedef struct MY_NOTIFYICONDATAW {
|
||||
DWORD cbSize;
|
||||
HWND hWnd;
|
||||
UINT uID;
|
||||
UINT uFlags;
|
||||
UINT uCallbackMessage;
|
||||
HICON hIcon;
|
||||
WCHAR szTip[128];
|
||||
DWORD dwState;
|
||||
DWORD dwStateMask;
|
||||
WCHAR szInfo[256];
|
||||
_ANONYMOUS_UNION union {
|
||||
UINT uTimeout;
|
||||
UINT uVersion;
|
||||
} DUMMYUNIONNAME;
|
||||
WCHAR szInfoTitle[64];
|
||||
DWORD dwInfoFlags;
|
||||
GUID guidItem;
|
||||
HICON hBalloonIcon;
|
||||
} MY_NOTIFYICONDATAW;
|
||||
|
||||
#ifndef NOTIFYICONDATAW_V1_SIZE
|
||||
# define NOTIFYICONDATAW_V1_SIZE offsetof (MY_NOTIFYICONDATAW, szTip[64])
|
||||
#endif
|
||||
#ifndef NOTIFYICONDATAW_V2_SIZE
|
||||
# define NOTIFYICONDATAW_V2_SIZE offsetof (MY_NOTIFYICONDATAW, guidItem)
|
||||
#endif
|
||||
#ifndef NOTIFYICONDATAW_V3_SIZE
|
||||
# define NOTIFYICONDATAW_V3_SIZE offsetof (MY_NOTIFYICONDATAW, hBalloonIcon)
|
||||
#endif
|
||||
#ifndef NIF_INFO
|
||||
# define NIF_INFO 0x00000010
|
||||
#endif
|
||||
#ifndef NIIF_NONE
|
||||
# define NIIF_NONE 0x00000000
|
||||
#endif
|
||||
#ifndef NIIF_INFO
|
||||
# define NIIF_INFO 0x00000001
|
||||
#endif
|
||||
#ifndef NIIF_WARNING
|
||||
# define NIIF_WARNING 0x00000002
|
||||
#endif
|
||||
#ifndef NIIF_ERROR
|
||||
# define NIIF_ERROR 0x00000003
|
||||
#endif
|
||||
|
||||
|
||||
#define EMACS_TRAY_NOTIFICATION_ID 42 /* arbitrary */
|
||||
#define EMACS_NOTIFICATION_MSG (WM_APP + 1)
|
||||
|
||||
enum NI_Severity {
|
||||
Ni_None,
|
||||
Ni_Info,
|
||||
Ni_Warn,
|
||||
Ni_Err
|
||||
};
|
||||
|
||||
/* Report the version of a DLL given by its name. The return value is
|
||||
constructed using MAKEDLLVERULL. */
|
||||
static ULONGLONG
|
||||
get_dll_version (const char *dll_name)
|
||||
{
|
||||
ULONGLONG version = 0;
|
||||
HINSTANCE hdll = LoadLibrary (dll_name);
|
||||
|
||||
if (hdll)
|
||||
{
|
||||
DLLGETVERSIONPROC pDllGetVersion
|
||||
= (DLLGETVERSIONPROC) GetProcAddress (hdll, "DllGetVersion");
|
||||
|
||||
if (pDllGetVersion)
|
||||
{
|
||||
DLLVERSIONINFO dvi;
|
||||
HRESULT result;
|
||||
|
||||
memset (&dvi, 0, sizeof(dvi));
|
||||
dvi.cbSize = sizeof(dvi);
|
||||
result = pDllGetVersion (&dvi);
|
||||
if (SUCCEEDED (result))
|
||||
version = MAKEDLLVERULL (dvi.dwMajorVersion, dvi.dwMinorVersion,
|
||||
0, 0);
|
||||
}
|
||||
FreeLibrary (hdll);
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
/* Return the number of bytes in UTF-8 encoded string STR that
|
||||
corresponds to at most LIM characters. If STR ends before LIM
|
||||
characters, return the number of bytes in STR including the
|
||||
terminating null byte. */
|
||||
static int
|
||||
utf8_mbslen_lim (const char *str, int lim)
|
||||
{
|
||||
const char *p = str;
|
||||
int mblen = 0, nchars = 0;
|
||||
|
||||
while (*p && nchars < lim)
|
||||
{
|
||||
int nbytes = CHAR_BYTES (*p);
|
||||
|
||||
mblen += nbytes;
|
||||
nchars++;
|
||||
p += nbytes;
|
||||
}
|
||||
|
||||
if (!*p && nchars < lim)
|
||||
mblen++;
|
||||
|
||||
return mblen;
|
||||
}
|
||||
|
||||
/* Low-level subroutine to show tray notifications. All strings are
|
||||
supposed to be unibyte UTF-8 encoded by the caller. */
|
||||
static EMACS_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;
|
||||
|
||||
if (FRAME_W32_P (f))
|
||||
{
|
||||
MY_NOTIFYICONDATAW nidw;
|
||||
ULONGLONG shell_dll_version = get_dll_version ("Shell32.dll");
|
||||
wchar_t tipw[128], msgw[256], titlew[64];
|
||||
int tiplen;
|
||||
|
||||
memset (&nidw, 0, sizeof(nidw));
|
||||
|
||||
/* MSDN says the full struct is supported since Vista, whose
|
||||
Shell32.dll version is said to be 6.0.6. But DllGetVersion
|
||||
cannot report the 3rd field value, it reports "build number"
|
||||
instead, which is something else. So we use the Windows 7's
|
||||
version 6.1 as cutoff, and Vista loses. (Actually, the loss
|
||||
is not a real one, since we don't expose the hBalloonIcon
|
||||
member of the struct to Lisp.) */
|
||||
if (shell_dll_version >= MAKEDLLVERULL (6, 1, 0, 0)) /* >= Windows 7 */
|
||||
nidw.cbSize = sizeof (nidw);
|
||||
else if (shell_dll_version >= MAKEDLLVERULL (6, 0, 0, 0)) /* XP */
|
||||
nidw.cbSize = NOTIFYICONDATAW_V3_SIZE;
|
||||
else if (shell_dll_version >= MAKEDLLVERULL (5, 0, 0, 0)) /* W2K */
|
||||
nidw.cbSize = NOTIFYICONDATAW_V2_SIZE;
|
||||
else
|
||||
nidw.cbSize = NOTIFYICONDATAW_V1_SIZE; /* < W2K */
|
||||
nidw.hWnd = FRAME_W32_WINDOW (f);
|
||||
nidw.uID = EMACS_TRAY_NOTIFICATION_ID;
|
||||
nidw.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_INFO;
|
||||
nidw.uCallbackMessage = EMACS_NOTIFICATION_MSG;
|
||||
if (!*icon)
|
||||
nidw.hIcon = LoadIcon (hinst, EMACS_CLASS);
|
||||
else
|
||||
{
|
||||
if (w32_unicode_filenames)
|
||||
{
|
||||
wchar_t icon_w[MAX_PATH];
|
||||
|
||||
if (filename_to_utf16 (icon, icon_w) != 0)
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
nidw.hIcon = LoadImageW (NULL, icon_w, IMAGE_ICON, 0, 0,
|
||||
LR_DEFAULTSIZE | LR_LOADFROMFILE);
|
||||
}
|
||||
else
|
||||
{
|
||||
char icon_a[MAX_PATH];
|
||||
|
||||
if (filename_to_ansi (icon, icon_a) != 0)
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
nidw.hIcon = LoadImageA (NULL, icon_a, IMAGE_ICON, 0, 0,
|
||||
LR_DEFAULTSIZE | LR_LOADFROMFILE);
|
||||
}
|
||||
}
|
||||
if (!nidw.hIcon)
|
||||
{
|
||||
switch (GetLastError ())
|
||||
{
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
errno = ENOENT;
|
||||
break;
|
||||
default:
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Windows 9X and NT4 support only 64 characters in the Tip,
|
||||
later versions support up to 128. */
|
||||
if (nidw.cbSize == NOTIFYICONDATAW_V1_SIZE)
|
||||
{
|
||||
tiplen = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
|
||||
tip, utf8_mbslen_lim (tip, 63),
|
||||
tipw, 64);
|
||||
if (tiplen >= 63)
|
||||
tipw[63] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
tiplen = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
|
||||
tip, utf8_mbslen_lim (tip, 127),
|
||||
tipw, 128);
|
||||
if (tiplen >= 127)
|
||||
tipw[127] = 0;
|
||||
}
|
||||
if (tiplen == 0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
retval = -1;
|
||||
goto done;
|
||||
}
|
||||
wcscpy (nidw.szTip, tipw);
|
||||
|
||||
/* The rest of the structure is only supported since Windows 2000. */
|
||||
if (nidw.cbSize > NOTIFYICONDATAW_V1_SIZE)
|
||||
{
|
||||
int slen;
|
||||
|
||||
slen = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
|
||||
msg, utf8_mbslen_lim (msg, 255),
|
||||
msgw, 256);
|
||||
if (slen >= 255)
|
||||
msgw[255] = 0;
|
||||
else if (slen == 0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
retval = -1;
|
||||
goto done;
|
||||
}
|
||||
wcscpy (nidw.szInfo, msgw);
|
||||
nidw.uTimeout = timeout;
|
||||
slen = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
|
||||
title, utf8_mbslen_lim (title, 63),
|
||||
titlew, 64);
|
||||
if (slen >= 63)
|
||||
titlew[63] = 0;
|
||||
else if (slen == 0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
retval = -1;
|
||||
goto done;
|
||||
}
|
||||
wcscpy (nidw.szInfoTitle, titlew);
|
||||
|
||||
switch (severity)
|
||||
{
|
||||
case Ni_None:
|
||||
nidw.dwInfoFlags = NIIF_NONE;
|
||||
break;
|
||||
case Ni_Info:
|
||||
default:
|
||||
nidw.dwInfoFlags = NIIF_INFO;
|
||||
break;
|
||||
case Ni_Warn:
|
||||
nidw.dwInfoFlags = NIIF_WARNING;
|
||||
break;
|
||||
case Ni_Err:
|
||||
nidw.dwInfoFlags = NIIF_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Shell_NotifyIconW (NIM_ADD, (PNOTIFYICONDATAW)&nidw))
|
||||
{
|
||||
/* GetLastError returns meaningless results when
|
||||
Shell_NotifyIcon fails. */
|
||||
DebPrint (("Shell_NotifyIcon ADD failed (err=%d)\n",
|
||||
GetLastError ()));
|
||||
errno = EINVAL;
|
||||
retval = -1;
|
||||
}
|
||||
done:
|
||||
if (*icon && !DestroyIcon (nidw.hIcon))
|
||||
DebPrint (("DestroyIcon failed (err=%d)\n", GetLastError ()));
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Low-level subroutine to remove a tray notification. Note: we only
|
||||
pass the minimum data about the notification: its ID and the handle
|
||||
of the window to which it sends messages. MSDN doesn't say this is
|
||||
enough, but it works in practice. This allows us to avoid keeping
|
||||
the notification data around after we show the notification. */
|
||||
static void
|
||||
delete_tray_notification (struct frame *f, int id)
|
||||
{
|
||||
if (FRAME_W32_P (f))
|
||||
{
|
||||
MY_NOTIFYICONDATAW nidw;
|
||||
|
||||
memset (&nidw, 0, sizeof(nidw));
|
||||
nidw.hWnd = FRAME_W32_WINDOW (f);
|
||||
nidw.uID = id;
|
||||
|
||||
if (!Shell_NotifyIconW (NIM_DELETE, (PNOTIFYICONDATAW)&nidw))
|
||||
{
|
||||
/* GetLastError returns meaningless results when
|
||||
Shell_NotifyIcon fails. */
|
||||
DebPrint (("Shell_NotifyIcon DELETE failed\n"));
|
||||
errno = EINVAL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
DEFUN ("w32-notification-notify",
|
||||
Fw32_notification_notify, Sw32_notification_notify,
|
||||
0, MANY, 0,
|
||||
doc: /* Display an MS-Windows tray notification as specified by PARAMS.
|
||||
|
||||
Value is the integer unique ID of the notification that can be used
|
||||
to remove the notification using `w32-notification-close', which see.
|
||||
If the function fails, the return value is nil.
|
||||
|
||||
Tray notifications, a.k.a. \"taskbar messages\", are messages that
|
||||
inform the user about events unrelated to the current user activity,
|
||||
such as a significant system event, by briefly displaying informative
|
||||
text in a balloon from an icon in the notification area of the taskbar.
|
||||
|
||||
Parameters in PARAMS are specified as keyword/value pairs. All the
|
||||
parameters are optional, but if no parameters are specified, the
|
||||
function will do nothing and return nil.
|
||||
|
||||
The following parameters are supported:
|
||||
|
||||
:icon ICON -- Display ICON in the system tray. If ICON is a string,
|
||||
it should specify a file name from which to load the
|
||||
icon; the specified file should be a .ico Windows icon
|
||||
file. If ICON is not a string, or if this parameter
|
||||
is not specified, the standard Emacs icon will be used.
|
||||
|
||||
:tip TIP -- Use TIP as the tooltip for the notification. If TIP
|
||||
is a string, this is the text of a tooltip that will
|
||||
be shown when the mouse pointer hovers over the tray
|
||||
icon added by the notification. If TIP is not a
|
||||
string, or if this parameter is not specified, the
|
||||
default tooltip text is \"Emacs notification\". The
|
||||
tooltip text can be up to 127 characters long (63
|
||||
on Windows versions before W2K). Longer strings
|
||||
will be truncated.
|
||||
|
||||
:level LEVEL -- Notification severity level, one of `info',
|
||||
`warning', or `error'. If given, the value
|
||||
determines the icon displayed to the left of the
|
||||
notification title, but only if the `:title'
|
||||
parameter (see below) is also specified and is a
|
||||
string.
|
||||
|
||||
:timeout TIMEOUT -- TIMEOUT is the time in seconds after which the
|
||||
notification disappears. The value can be integer
|
||||
or floating-point. This is ignored on Vista and
|
||||
later systems, where the duration is fixed at 9 sec
|
||||
and can only be customized via system-wide
|
||||
Accessibility settings.
|
||||
|
||||
:title TITLE -- The title of the notification. If TITLE is a string,
|
||||
it is displayed in a larger font immediately above
|
||||
the body text. The title text can be up to 63
|
||||
characters long; longer text will be truncated.
|
||||
|
||||
:body BODY -- The body of the notification. If BODY is a string,
|
||||
it specifies the text of the notification message.
|
||||
Use embedded newlines to control how the text is
|
||||
broken into lines. The body text can be up to 255
|
||||
characters long, and will be truncated if it's longer.
|
||||
|
||||
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.
|
||||
|
||||
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;
|
||||
char *icon, *tip, *title, *msg;
|
||||
enum NI_Severity severity;
|
||||
unsigned timeout;
|
||||
|
||||
if (nargs == 0)
|
||||
return Qnil;
|
||||
|
||||
arg_plist = Flist (nargs, args);
|
||||
|
||||
/* Icon. */
|
||||
lres = Fplist_get (arg_plist, QCicon);
|
||||
if (STRINGP (lres))
|
||||
icon = SSDATA (ENCODE_FILE (Fexpand_file_name (lres, Qnil)));
|
||||
else
|
||||
icon = "";
|
||||
|
||||
/* Tip. */
|
||||
lres = Fplist_get (arg_plist, QCtip);
|
||||
if (STRINGP (lres))
|
||||
tip = SSDATA (code_convert_string_norecord (lres, Qutf_8, 1));
|
||||
else
|
||||
tip = "Emacs notification";
|
||||
|
||||
/* Severity. */
|
||||
lres = Fplist_get (arg_plist, QClevel);
|
||||
if (NILP (lres))
|
||||
severity = Ni_None;
|
||||
else if (EQ (lres, Qinfo))
|
||||
severity = Ni_Info;
|
||||
else if (EQ (lres, Qwarning))
|
||||
severity = Ni_Warn;
|
||||
else if (EQ (lres, Qerror))
|
||||
severity = Ni_Err;
|
||||
else
|
||||
severity = Ni_Info;
|
||||
|
||||
/* Timeout. */
|
||||
lres = Fplist_get (arg_plist, QCtimeout);
|
||||
if (NUMBERP (lres))
|
||||
timeout = 1000 * (INTEGERP (lres) ? XINT (lres) : XFLOAT_DATA (lres));
|
||||
else
|
||||
timeout = 0;
|
||||
|
||||
/* Title. */
|
||||
lres = Fplist_get (arg_plist, QCtitle);
|
||||
if (STRINGP (lres))
|
||||
title = SSDATA (code_convert_string_norecord (lres, Qutf_8, 1));
|
||||
else
|
||||
title = "";
|
||||
|
||||
/* Notification body text. */
|
||||
lres = Fplist_get (arg_plist, QCbody);
|
||||
if (STRINGP (lres))
|
||||
msg = SSDATA (code_convert_string_norecord (lres, Qutf_8, 1));
|
||||
else
|
||||
msg = "";
|
||||
|
||||
/* Do it! */
|
||||
retval = add_tray_notification (f, icon, tip, severity, timeout, title, msg);
|
||||
return (retval < 0 ? Qnil : make_number (retval));
|
||||
}
|
||||
|
||||
DEFUN ("w32-notification-close",
|
||||
Fw32_notification_close, Sw32_notification_close,
|
||||
1, 1, 0,
|
||||
doc: /* Remove the MS-Windows tray notification specified by its ID. */)
|
||||
(Lisp_Object id)
|
||||
{
|
||||
struct frame *f = SELECTED_FRAME ();
|
||||
|
||||
if (INTEGERP (id))
|
||||
delete_tray_notification (f, XINT (id));
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
Initialization
|
||||
|
|
@ -8828,6 +9296,14 @@ syms_of_w32fns (void)
|
|||
DEFSYM (Qframes, "frames");
|
||||
DEFSYM (Qtip_frame, "tip-frame");
|
||||
DEFSYM (Qunicode_sip, "unicode-sip");
|
||||
DEFSYM (QCicon, ":icon");
|
||||
DEFSYM (QCtip, ":tip");
|
||||
DEFSYM (QClevel, ":level");
|
||||
DEFSYM (Qinfo, "info");
|
||||
DEFSYM (Qwarning, "warning");
|
||||
DEFSYM (QCtimeout, ":timeout");
|
||||
DEFSYM (QCtitle, ":title");
|
||||
DEFSYM (QCbody, ":body");
|
||||
|
||||
/* Symbols used elsewhere, but only in MS-Windows-specific code. */
|
||||
DEFSYM (Qgnutls_dll, "gnutls");
|
||||
|
|
@ -9161,6 +9637,8 @@ This variable has effect only on Windows Vista and later. */);
|
|||
defsubr (&Sw32_window_exists_p);
|
||||
defsubr (&Sw32_battery_status);
|
||||
defsubr (&Sw32__menu_bar_in_use);
|
||||
defsubr (&Sw32_notification_notify);
|
||||
defsubr (&Sw32_notification_close);
|
||||
|
||||
#ifdef WINDOWSNT
|
||||
defsubr (&Sfile_system_info);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue