2020-12-10 18:06:24 +01:00
|
|
|
#include "notify.h"
|
|
|
|
|
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
#include <errno.h>
|
2020-12-10 18:06:24 +01:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
#include <sys/epoll.h>
|
2020-12-10 18:06:24 +01:00
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
|
|
#define LOG_MODULE "notify"
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
#define LOG_ENABLE_DBG 1
|
2020-12-10 18:06:24 +01:00
|
|
|
#include "log.h"
|
|
|
|
|
#include "config.h"
|
|
|
|
|
#include "spawn.h"
|
osc/notify: add support for OSC-99, kitty desktop notifications
This adds limited support for OSC-99, kitty desktop notifications[^1]. We
support everything defined by the "protocol", except:
* 'a': action to perform on notification activation. Since we don't
trigger the notification ourselves (over D-Bus), we don't know a)
which ID the notification got, or b) when it is clicked.
* ... and that's it. Everything else is supported
To be explicit, we *do* support:
* Chunked notifications (d=0|1), allowing the application to append
data to a notification in chunks, before it's finally displayed.
* Plain UTF-8, or base64-encoded UTF-8 payload (e=0|1).
* Notification identifier (i=xyz).
* Payload type (p=title|body).
* When to honor the notification (o=always|unfocused|invisible), with
the following quirks:
- we don't know when the window is invisible, thus it's treated as
'unfocused'.
- the foot option 'notify-focus-inhibit' overrides 'always'
* Urgency (u=0|1|2)
[^1]: https://sw.kovidgoyal.net/kitty/desktop-notifications/
2024-07-19 15:04:28 +02:00
|
|
|
#include "terminal.h"
|
2024-07-23 11:29:05 +02:00
|
|
|
#include "util.h"
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
#include "wayland.h"
|
2020-12-10 18:06:24 +01:00
|
|
|
#include "xmalloc.h"
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
#include "xsnprintf.h"
|
2020-12-10 18:06:24 +01:00
|
|
|
|
|
|
|
|
void
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
notify_free(struct terminal *term, struct notification *notif)
|
2020-12-10 18:06:24 +01:00
|
|
|
{
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
fdm_del(term->fdm, notif->stdout_fd);
|
|
|
|
|
free(notif->id);
|
|
|
|
|
free(notif->title);
|
|
|
|
|
free(notif->body);
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
free(notif->category);
|
|
|
|
|
free(notif->app_id);
|
2024-07-23 11:29:05 +02:00
|
|
|
free(notif->icon_id);
|
|
|
|
|
free(notif->icon_symbolic_name);
|
|
|
|
|
free(notif->icon_data);
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
free(notif->xdg_token);
|
2024-07-23 09:42:14 +02:00
|
|
|
free(notif->stdout_data);
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
|
|
|
|
|
tll_free_and_free(notif->actions, free);
|
|
|
|
|
|
|
|
|
|
if (notif->icon_path != NULL) {
|
|
|
|
|
unlink(notif->icon_path);
|
|
|
|
|
free(notif->icon_path);
|
|
|
|
|
|
|
|
|
|
if (notif->icon_fd >= 0)
|
|
|
|
|
close(notif->icon_fd);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
write_icon_file(const void *data, size_t data_sz, int *fd, char **filename,
|
|
|
|
|
char **symbolic_name)
|
|
|
|
|
{
|
|
|
|
|
xassert(*filename == NULL);
|
|
|
|
|
xassert(*symbolic_name == NULL);
|
|
|
|
|
|
|
|
|
|
char name[64] = "/tmp/foot-notification-icon-XXXXXX";
|
|
|
|
|
|
|
|
|
|
*filename = NULL;
|
|
|
|
|
*symbolic_name = NULL;
|
|
|
|
|
*fd = mkostemp(name, O_CLOEXEC);
|
|
|
|
|
|
|
|
|
|
if (*fd < 0) {
|
|
|
|
|
LOG_ERRNO("failed to create temporary file for icon cache");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (write(*fd, data, data_sz) != (ssize_t)data_sz) {
|
|
|
|
|
LOG_ERRNO("failed to write icon data to temporary file");
|
|
|
|
|
close(*fd);
|
|
|
|
|
*fd = -1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LOG_DBG("wrote icon data to %s", name);
|
|
|
|
|
*filename = xstrdup(name);
|
|
|
|
|
*symbolic_name = xasprintf("file://%s", *filename);
|
|
|
|
|
return true;
|
2024-07-23 09:33:18 +02:00
|
|
|
}
|
|
|
|
|
|
2024-07-24 16:02:19 +02:00
|
|
|
static bool
|
|
|
|
|
to_integer(const char *line, size_t len, uint32_t *res)
|
|
|
|
|
{
|
|
|
|
|
bool is_id = true;
|
|
|
|
|
uint32_t maybe_id = 0;
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < len; i++) {
|
|
|
|
|
char digit = line[i];
|
|
|
|
|
if (digit < '0' || digit > '9') {
|
|
|
|
|
is_id = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
maybe_id *= 10;
|
|
|
|
|
maybe_id += digit - '0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*res = maybe_id;
|
|
|
|
|
return is_id;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-23 09:33:18 +02:00
|
|
|
static void
|
|
|
|
|
consume_stdout(struct notification *notif, bool eof)
|
|
|
|
|
{
|
2024-07-23 09:42:14 +02:00
|
|
|
char *data = notif->stdout_data;
|
2024-07-23 09:33:18 +02:00
|
|
|
const char *line = data;
|
|
|
|
|
size_t left = notif->stdout_sz;
|
|
|
|
|
|
|
|
|
|
/* Process stdout, line-by-line */
|
|
|
|
|
while (left > 0) {
|
|
|
|
|
line = data;
|
|
|
|
|
size_t len = left;
|
|
|
|
|
char *eol = memchr(line, '\n', left);
|
|
|
|
|
|
|
|
|
|
if (eol != NULL) {
|
|
|
|
|
*eol = '\0';
|
|
|
|
|
len = strlen(line);
|
|
|
|
|
data = eol + 1;
|
|
|
|
|
} else if (!eof)
|
|
|
|
|
break;
|
|
|
|
|
|
2024-07-24 16:02:19 +02:00
|
|
|
uint32_t maybe_id = 0;
|
|
|
|
|
|
|
|
|
|
/* Check for daemon assigned ID, either '123', or 'id=123' */
|
|
|
|
|
if (to_integer(line, len, &maybe_id) ||
|
|
|
|
|
(len > 3 && memcmp(line, "id=", 3) == 0 &&
|
|
|
|
|
to_integer(&line[3], len - 3, &maybe_id)))
|
|
|
|
|
{
|
|
|
|
|
notif->external_id = maybe_id;
|
|
|
|
|
LOG_DBG("external ID: %u", notif->external_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check for triggered action, either 'default' or 'action=default' */
|
|
|
|
|
else if ((len == 7 && memcmp(line, "default", 7) == 0) ||
|
|
|
|
|
(len == 7 + 7 && memcmp(line, "action=default", 7 + 7) == 0))
|
|
|
|
|
{
|
2024-07-23 16:41:52 +02:00
|
|
|
notif->activated = true;
|
2024-07-24 16:02:19 +02:00
|
|
|
LOG_DBG("notification's default action was triggered");
|
|
|
|
|
}
|
2024-07-23 16:41:52 +02:00
|
|
|
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
else if (len > 7 && memcmp(line, "action=", 7) == 0) {
|
|
|
|
|
notif->activated = true;
|
|
|
|
|
|
|
|
|
|
uint32_t maybe_button_nr;
|
|
|
|
|
if (to_integer(&line[7], len - 7, &maybe_button_nr)) {
|
|
|
|
|
notif->activated_button = maybe_button_nr;
|
|
|
|
|
LOG_DBG("custom action %u triggered", notif->activated_button);
|
|
|
|
|
} else {
|
|
|
|
|
LOG_DBG("unrecognized action triggered: %.*s",
|
|
|
|
|
(int)(len - 7), &line[7]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-24 16:02:19 +02:00
|
|
|
/* Check for XDG activation token, 'xdgtoken=xyz' */
|
2024-07-23 16:41:52 +02:00
|
|
|
else if (len > 9 && memcmp(line, "xdgtoken=", 9) == 0) {
|
2024-07-23 09:33:18 +02:00
|
|
|
notif->xdg_token = xstrndup(&line[9], len - 9);
|
|
|
|
|
LOG_DBG("XDG token: \"%s\"", notif->xdg_token);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
left -= len + (eol != NULL ? 1 : 0);
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-23 18:48:45 +02:00
|
|
|
if (left > 0)
|
2024-07-23 15:29:08 +02:00
|
|
|
memmove(notif->stdout_data, data, left);
|
2024-07-23 18:48:45 +02:00
|
|
|
|
|
|
|
|
notif->stdout_sz = left;
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
fdm_notify_stdout(struct fdm *fdm, int fd, int events, void *data)
|
|
|
|
|
{
|
|
|
|
|
const struct terminal *term = data;
|
|
|
|
|
struct notification *notif = NULL;
|
|
|
|
|
|
|
|
|
|
/* Find notification */
|
2024-07-23 11:53:30 +02:00
|
|
|
tll_foreach(term->active_notifications, it) {
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
if (it->item.stdout_fd == fd) {
|
|
|
|
|
notif = &it->item;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (events & EPOLLIN) {
|
|
|
|
|
char buf[512];
|
|
|
|
|
ssize_t count = read(fd, buf, sizeof(buf) - 1);
|
|
|
|
|
|
|
|
|
|
if (count < 0) {
|
|
|
|
|
if (errno == EINTR)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
LOG_ERRNO("failed to read notification activation token");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-23 09:33:18 +02:00
|
|
|
if (count > 0 && notif != NULL) {
|
2024-07-23 09:42:14 +02:00
|
|
|
if (notif->stdout_data == NULL) {
|
2024-07-23 09:33:18 +02:00
|
|
|
xassert(notif->stdout_sz == 0);
|
2024-07-23 09:42:14 +02:00
|
|
|
notif->stdout_data = xmemdup(buf, count);
|
2024-07-23 09:33:18 +02:00
|
|
|
} else {
|
2024-07-23 09:42:14 +02:00
|
|
|
notif->stdout_data = xrealloc(notif->stdout_data, notif->stdout_sz + count);
|
|
|
|
|
memcpy(¬if->stdout_data[notif->stdout_sz], buf, count);
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
}
|
2024-07-23 09:33:18 +02:00
|
|
|
|
|
|
|
|
notif->stdout_sz += count;
|
|
|
|
|
consume_stdout(notif, false);
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (events & EPOLLHUP) {
|
|
|
|
|
fdm_del(fdm, fd);
|
2024-07-23 09:33:18 +02:00
|
|
|
if (notif != NULL) {
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
notif->stdout_fd = -1;
|
2024-07-23 09:33:18 +02:00
|
|
|
consume_stdout(notif, true);
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
notif_done(struct reaper *reaper, pid_t pid, int status, void *data)
|
|
|
|
|
{
|
|
|
|
|
struct terminal *term = data;
|
|
|
|
|
|
2024-07-23 11:53:30 +02:00
|
|
|
tll_foreach(term->active_notifications, it) {
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
struct notification *notif = &it->item;
|
|
|
|
|
if (notif->pid != pid)
|
|
|
|
|
continue;
|
|
|
|
|
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
LOG_DBG("notification %s closed",
|
|
|
|
|
notif->id != NULL ? notif->id : "<unset>");
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
|
2024-07-23 16:41:52 +02:00
|
|
|
if (notif->activated && notif->focus) {
|
|
|
|
|
LOG_DBG("focus window on notification activation: \"%s\"",
|
|
|
|
|
notif->xdg_token);
|
2024-07-26 16:23:17 +02:00
|
|
|
|
|
|
|
|
if (notif->xdg_token == NULL)
|
|
|
|
|
LOG_WARN("cannot focus window: no activation token available");
|
|
|
|
|
else
|
|
|
|
|
wayl_activate(term->wl, term->window, notif->xdg_token);
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
}
|
|
|
|
|
|
2024-07-25 18:35:15 +02:00
|
|
|
if (notif->activated && notif->report_activated) {
|
2024-07-25 18:47:23 +02:00
|
|
|
LOG_DBG("sending notification activation event to client");
|
2020-12-10 18:06:24 +01:00
|
|
|
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
const char *id = notif->id != NULL ? notif->id : "0";
|
|
|
|
|
|
|
|
|
|
char button_nr[16] = {0};
|
|
|
|
|
if (notif->activated_button > 0) {
|
|
|
|
|
xsnprintf(
|
|
|
|
|
button_nr, sizeof(button_nr), "%u", notif->activated_button);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char reply[7 + strlen(id) + 1 + strlen(button_nr) + 2 + 1];
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
int n = xsnprintf(
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
reply, sizeof(reply), "\033]99;i=%s;%s\033\\", id, button_nr);
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
term_to_slave(term, reply, n);
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-25 18:47:23 +02:00
|
|
|
if (notif->report_closed) {
|
|
|
|
|
LOG_DBG("sending notification close event to client");
|
|
|
|
|
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
const char *id = notif->id != NULL ? notif->id : "0";
|
|
|
|
|
char reply[7 + strlen(id) + 1 + 7 + 1 + 2 + 1];
|
2024-07-25 18:47:23 +02:00
|
|
|
int n = xsnprintf(
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
reply, sizeof(reply), "\033]99;i=%s:p=close;\033\\", id);
|
2024-07-25 18:47:23 +02:00
|
|
|
term_to_slave(term, reply, n);
|
|
|
|
|
}
|
|
|
|
|
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
notify_free(term, notif);
|
2024-07-23 11:53:30 +02:00
|
|
|
tll_remove(term->active_notifications, it);
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
2024-07-23 11:53:30 +02:00
|
|
|
notify_notify(struct terminal *term, struct notification *notif)
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
{
|
|
|
|
|
xassert(notif->xdg_token == NULL);
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
xassert(notif->external_id == 0);
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
xassert(notif->pid == 0);
|
2024-07-23 11:53:30 +02:00
|
|
|
xassert(notif->stdout_fd <= 0);
|
2024-07-23 09:42:14 +02:00
|
|
|
xassert(notif->stdout_data == NULL);
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
xassert(notif->icon_path == NULL);
|
|
|
|
|
xassert(notif->icon_fd <= 0);
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
|
|
|
|
|
notif->pid = -1;
|
|
|
|
|
notif->stdout_fd = -1;
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
notif->icon_fd = -1;
|
|
|
|
|
|
|
|
|
|
if (term->conf->desktop_notifications.command.argv.args == NULL)
|
|
|
|
|
return false;
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
if ((term->conf->desktop_notifications.inhibit_when_focused ||
|
|
|
|
|
notif->when != NOTIFY_ALWAYS)
|
|
|
|
|
&& term->kbd_focus)
|
|
|
|
|
{
|
|
|
|
|
/* No notifications while we're focused */
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *app_id = notif->app_id != NULL
|
|
|
|
|
? notif->app_id
|
|
|
|
|
: term->app_id != NULL
|
|
|
|
|
? term->app_id
|
|
|
|
|
: term->conf->app_id;
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
const char *title = notif->title != NULL ? notif->title : notif->body;
|
|
|
|
|
const char *body = notif->title != NULL && notif->body != NULL ? notif->body : "";
|
|
|
|
|
|
2024-07-30 17:16:02 +02:00
|
|
|
/* Icon: symbolic name if present, otherwise a filename */
|
|
|
|
|
const char *icon_name_or_path = "";
|
2024-07-23 11:29:05 +02:00
|
|
|
|
|
|
|
|
if (notif->icon_id != NULL) {
|
|
|
|
|
for (size_t i = 0; i < ALEN(term->notification_icons); i++) {
|
|
|
|
|
const struct notification_icon *icon = &term->notification_icons[i];
|
|
|
|
|
|
2024-07-24 16:04:14 +02:00
|
|
|
if (icon->id != NULL && streq(icon->id, notif->icon_id)) {
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
/* For now, we set the symbolic name to 'file:///path'
|
|
|
|
|
* when using a file based icon. */
|
|
|
|
|
xassert(icon->symbolic_name != NULL);
|
|
|
|
|
icon_name_or_path = icon->symbolic_name;
|
|
|
|
|
|
|
|
|
|
LOG_DBG("using icon from cache (cache ID: %s): %s",
|
|
|
|
|
icon->id, icon_name_or_path);
|
2024-07-23 11:29:05 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-07-23 15:30:01 +02:00
|
|
|
} else if (notif->icon_symbolic_name != NULL) {
|
|
|
|
|
icon_name_or_path = notif->icon_symbolic_name;
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
LOG_DBG("using symbolic icon from notification: %s", icon_name_or_path);
|
|
|
|
|
} else if (notif->icon_data_sz > 0) {
|
|
|
|
|
xassert(notif->icon_data != NULL);
|
|
|
|
|
|
|
|
|
|
if (write_icon_file(
|
|
|
|
|
notif->icon_data, notif->icon_data_sz,
|
|
|
|
|
¬if->icon_fd,
|
|
|
|
|
¬if->icon_path,
|
|
|
|
|
¬if->icon_symbolic_name))
|
|
|
|
|
icon_name_or_path = notif->icon_symbolic_name;
|
|
|
|
|
|
|
|
|
|
LOG_DBG("using icon data from notification: %s", icon_name_or_path);
|
2024-07-23 11:29:05 +02:00
|
|
|
}
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
|
2024-07-26 16:23:17 +02:00
|
|
|
bool track_notification = notif->focus ||
|
|
|
|
|
notif->report_activated ||
|
|
|
|
|
notif->may_be_programatically_closed;
|
2024-07-23 11:53:30 +02:00
|
|
|
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
uint32_t replaces_id = 0;
|
|
|
|
|
if (notif->id != NULL) {
|
|
|
|
|
tll_foreach(term->active_notifications, it) {
|
|
|
|
|
struct notification *existing = &it->item;
|
|
|
|
|
|
|
|
|
|
if (existing->id == NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* When replacing/updating a notificaton, we may have
|
|
|
|
|
* *multiple* notification helpers running for the "same"
|
|
|
|
|
* notification. Make sure only the *last* notification's
|
|
|
|
|
* report closed/activated are honored, to avoid sending
|
|
|
|
|
* multiple reports.
|
|
|
|
|
*
|
|
|
|
|
* This also means we cannot 'break' out of the loop - we
|
|
|
|
|
* must check *all* notifications.
|
|
|
|
|
*/
|
|
|
|
|
if (existing->external_id != 0 && streq(existing->id, notif->id)) {
|
|
|
|
|
replaces_id = existing->external_id;
|
|
|
|
|
existing->report_activated = false;
|
|
|
|
|
existing->report_closed = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-12-10 18:07:50 +01:00
|
|
|
}
|
|
|
|
|
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
char replaces_id_str[16];
|
|
|
|
|
xsnprintf(replaces_id_str, sizeof(replaces_id_str), "%u", replaces_id);
|
2021-01-31 14:40:27 +01:00
|
|
|
|
osc/notify: add support for OSC-99, kitty desktop notifications
This adds limited support for OSC-99, kitty desktop notifications[^1]. We
support everything defined by the "protocol", except:
* 'a': action to perform on notification activation. Since we don't
trigger the notification ourselves (over D-Bus), we don't know a)
which ID the notification got, or b) when it is clicked.
* ... and that's it. Everything else is supported
To be explicit, we *do* support:
* Chunked notifications (d=0|1), allowing the application to append
data to a notification in chunks, before it's finally displayed.
* Plain UTF-8, or base64-encoded UTF-8 payload (e=0|1).
* Notification identifier (i=xyz).
* Payload type (p=title|body).
* When to honor the notification (o=always|unfocused|invisible), with
the following quirks:
- we don't know when the window is invisible, thus it's treated as
'unfocused'.
- the foot option 'notify-focus-inhibit' overrides 'always'
* Urgency (u=0|1|2)
[^1]: https://sw.kovidgoyal.net/kitty/desktop-notifications/
2024-07-19 15:04:28 +02:00
|
|
|
const char *urgency_str =
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
notif->urgency == NOTIFY_URGENCY_LOW
|
osc/notify: add support for OSC-99, kitty desktop notifications
This adds limited support for OSC-99, kitty desktop notifications[^1]. We
support everything defined by the "protocol", except:
* 'a': action to perform on notification activation. Since we don't
trigger the notification ourselves (over D-Bus), we don't know a)
which ID the notification got, or b) when it is clicked.
* ... and that's it. Everything else is supported
To be explicit, we *do* support:
* Chunked notifications (d=0|1), allowing the application to append
data to a notification in chunks, before it's finally displayed.
* Plain UTF-8, or base64-encoded UTF-8 payload (e=0|1).
* Notification identifier (i=xyz).
* Payload type (p=title|body).
* When to honor the notification (o=always|unfocused|invisible), with
the following quirks:
- we don't know when the window is invisible, thus it's treated as
'unfocused'.
- the foot option 'notify-focus-inhibit' overrides 'always'
* Urgency (u=0|1|2)
[^1]: https://sw.kovidgoyal.net/kitty/desktop-notifications/
2024-07-19 15:04:28 +02:00
|
|
|
? "low"
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
: notif->urgency == NOTIFY_URGENCY_NORMAL
|
osc/notify: add support for OSC-99, kitty desktop notifications
This adds limited support for OSC-99, kitty desktop notifications[^1]. We
support everything defined by the "protocol", except:
* 'a': action to perform on notification activation. Since we don't
trigger the notification ourselves (over D-Bus), we don't know a)
which ID the notification got, or b) when it is clicked.
* ... and that's it. Everything else is supported
To be explicit, we *do* support:
* Chunked notifications (d=0|1), allowing the application to append
data to a notification in chunks, before it's finally displayed.
* Plain UTF-8, or base64-encoded UTF-8 payload (e=0|1).
* Notification identifier (i=xyz).
* Payload type (p=title|body).
* When to honor the notification (o=always|unfocused|invisible), with
the following quirks:
- we don't know when the window is invisible, thus it's treated as
'unfocused'.
- the foot option 'notify-focus-inhibit' overrides 'always'
* Urgency (u=0|1|2)
[^1]: https://sw.kovidgoyal.net/kitty/desktop-notifications/
2024-07-19 15:04:28 +02:00
|
|
|
? "normal" : "critical";
|
|
|
|
|
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
LOG_DBG("notify: title=\"%s\", body=\"%s\", app-id=\"%s\", category=\"%s\", "
|
|
|
|
|
"urgency=\"%s\", icon=\"%s\", expires=%d, replaces=%u (tracking: %s)",
|
|
|
|
|
title, body, app_id, notif->category, urgency_str, icon_name_or_path,
|
|
|
|
|
notif->expire_time, replaces_id, track_notification ? "yes" : "no");
|
|
|
|
|
|
|
|
|
|
xassert(title != NULL);
|
|
|
|
|
if (title == NULL)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
char **argv = NULL;
|
|
|
|
|
size_t argc = 0;
|
|
|
|
|
char **action_argv = NULL;
|
|
|
|
|
size_t action_argc = 0;
|
|
|
|
|
|
|
|
|
|
char expire_time[16];
|
|
|
|
|
xsnprintf(expire_time, sizeof(expire_time), "%d", notif->expire_time);
|
|
|
|
|
|
|
|
|
|
if (term->conf->desktop_notifications.command_action_arg.argv.args) {
|
|
|
|
|
struct action {
|
|
|
|
|
const char *name;
|
|
|
|
|
const char *label;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
tll(struct action) actions = tll_init();
|
|
|
|
|
tll_push_back(actions, ((struct action){"default", "Click to activate"}));
|
|
|
|
|
|
|
|
|
|
tll_foreach(notif->actions, it) {
|
|
|
|
|
tll_push_back(actions, ((struct action){NULL, it->item}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t action_idx = 0;
|
|
|
|
|
tll_foreach(actions, it) {
|
|
|
|
|
const char *name = it->item.name;
|
|
|
|
|
const char *label = it->item.label;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Custom actions (buttons) start at 1.
|
|
|
|
|
*
|
|
|
|
|
* We always insert our own default action first, causing
|
|
|
|
|
* all custom actions to start at index 1 in our list.
|
|
|
|
|
*/
|
|
|
|
|
char numerical_name[16];
|
|
|
|
|
xsnprintf(numerical_name, sizeof(numerical_name), "%zu", action_idx);
|
|
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
|
name = numerical_name;
|
|
|
|
|
|
|
|
|
|
char **expanded = NULL;
|
|
|
|
|
size_t count = 0;
|
|
|
|
|
|
|
|
|
|
if (!spawn_expand_template(
|
|
|
|
|
&term->conf->desktop_notifications.command_action_arg, 2,
|
|
|
|
|
(const char *[]){"action-name", "action-label"},
|
|
|
|
|
(const char *[]){name, label},
|
|
|
|
|
&count, &expanded))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Append to the "global" actions argv */
|
|
|
|
|
action_argv = xrealloc(
|
|
|
|
|
action_argv, (action_argc + count) * sizeof(action_argv[0]));
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < count; i++)
|
|
|
|
|
action_argv[action_argc + i] = expanded[i];
|
|
|
|
|
|
|
|
|
|
action_argc += count;
|
|
|
|
|
|
|
|
|
|
free(expanded);
|
|
|
|
|
action_idx++;
|
|
|
|
|
tll_remove(actions, it);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-31 14:40:27 +01:00
|
|
|
if (!spawn_expand_template(
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
&term->conf->desktop_notifications.command, 10,
|
2024-07-23 16:41:52 +02:00
|
|
|
(const char *[]){
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
"app-id", "window-title", "icon", "title", "body", "category",
|
|
|
|
|
"urgency", "expire-time", "replace-id", "action-arg"},
|
2024-07-23 16:41:52 +02:00
|
|
|
(const char *[]){
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
app_id, term->window_title, icon_name_or_path, title, body,
|
|
|
|
|
notif->category != NULL ? notif->category : "", urgency_str,
|
|
|
|
|
expire_time, replaces_id_str,
|
|
|
|
|
|
|
|
|
|
/* Custom expansion below, since we need to expand to multiple arguments */
|
|
|
|
|
"${action-arg}"},
|
2024-07-23 16:41:52 +02:00
|
|
|
&argc, &argv))
|
2021-01-31 14:40:27 +01:00
|
|
|
{
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
return false;
|
2020-12-10 18:06:24 +01:00
|
|
|
}
|
|
|
|
|
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
for (size_t i = 0; i < argc; i++) {
|
|
|
|
|
if (!streq(argv[i], "${action-arg}"))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (action_argc == 0) {
|
|
|
|
|
free(argv[i]);
|
|
|
|
|
memmove(&argv[i], &argv[i + 1], (argc - i - 1) * sizeof(argv[0]));
|
|
|
|
|
argv[argc--] = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Remove the "${action-arg}" entry, add all actions argument from earlier */
|
|
|
|
|
argv = xrealloc(argv, (argc + action_argc - 1) * sizeof(argv[0]));
|
|
|
|
|
|
|
|
|
|
/* Move remaining arguments to after the action arguments */
|
|
|
|
|
memmove(&argv[i + action_argc],
|
|
|
|
|
&argv[i + 1],
|
|
|
|
|
(argc - (i + 1)) * sizeof(argv[0]));
|
|
|
|
|
|
|
|
|
|
free(argv[i]); /* Free xstrdup("${action-arg}"); */
|
|
|
|
|
|
|
|
|
|
/* Insert the action arguments */
|
|
|
|
|
for (size_t j = 0; j < action_argc; j++) {
|
|
|
|
|
argv[i + j] = action_argv[j];
|
|
|
|
|
action_argv[j] = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
argc += action_argc;
|
|
|
|
|
argc--; /* The ${action-arg} option has been removed */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-10 18:06:24 +01:00
|
|
|
LOG_DBG("notify command:");
|
2021-01-31 14:40:27 +01:00
|
|
|
for (size_t i = 0; i < argc; i++)
|
2020-12-10 18:06:24 +01:00
|
|
|
LOG_DBG(" argv[%zu] = \"%s\"", i, argv[i]);
|
|
|
|
|
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
int stdout_fds[2] = {-1, -1};
|
2024-07-23 11:53:30 +02:00
|
|
|
if (track_notification) {
|
|
|
|
|
if (pipe2(stdout_fds, O_CLOEXEC | O_NONBLOCK) < 0) {
|
|
|
|
|
LOG_WARN("failed to create stdout pipe");
|
|
|
|
|
track_notification = false;
|
|
|
|
|
/* Non-fatal */
|
|
|
|
|
} else {
|
|
|
|
|
tll_push_back(term->active_notifications, *notif);
|
|
|
|
|
notif->id = NULL;
|
|
|
|
|
notif->title = NULL;
|
|
|
|
|
notif->body = NULL;
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
notif->category = NULL;
|
|
|
|
|
notif->app_id = NULL;
|
2024-07-23 11:53:30 +02:00
|
|
|
notif->icon_id = NULL;
|
2024-07-23 19:08:21 +02:00
|
|
|
notif->icon_symbolic_name = NULL;
|
2024-07-23 11:53:30 +02:00
|
|
|
notif->icon_data = NULL;
|
|
|
|
|
notif->icon_data_sz = 0;
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
notif->icon_path = NULL;
|
|
|
|
|
notif->icon_fd = -1;
|
|
|
|
|
notif->stdout_fd = -1;
|
|
|
|
|
struct notification *new_notif = &tll_back(term->active_notifications);
|
|
|
|
|
|
|
|
|
|
/* We don't need these anymore. They'll be free:d by the caller */
|
|
|
|
|
memset(&new_notif->actions, 0, sizeof(new_notif->actions));
|
|
|
|
|
notif = new_notif;
|
2024-07-23 11:53:30 +02:00
|
|
|
}
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (stdout_fds[0] >= 0) {
|
|
|
|
|
fdm_add(term->fdm, stdout_fds[0], EPOLLIN,
|
|
|
|
|
&fdm_notify_stdout, (void *)term);
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-10 18:06:24 +01:00
|
|
|
/* Redirect stdin to /dev/null, but ignore failure to open */
|
|
|
|
|
int devnull = open("/dev/null", O_RDONLY);
|
2024-07-23 06:57:30 +02:00
|
|
|
pid_t pid = spawn(
|
|
|
|
|
term->reaper, NULL, argv, devnull, stdout_fds[1], -1,
|
2024-07-23 11:53:30 +02:00
|
|
|
track_notification ? ¬if_done : NULL, (void *)term, NULL);
|
2024-07-23 06:57:30 +02:00
|
|
|
|
|
|
|
|
if (stdout_fds[1] >= 0) {
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
/* Close write-end of stdout pipe */
|
|
|
|
|
close(stdout_fds[1]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pid < 0 && stdout_fds[0] >= 0) {
|
|
|
|
|
/* Remove FDM callback if we failed to spawn */
|
|
|
|
|
fdm_del(term->fdm, stdout_fds[0]);
|
|
|
|
|
}
|
2020-12-10 18:06:24 +01:00
|
|
|
|
|
|
|
|
if (devnull >= 0)
|
|
|
|
|
close(devnull);
|
|
|
|
|
|
2021-01-31 14:40:27 +01:00
|
|
|
for (size_t i = 0; i < argc; i++)
|
2020-12-10 18:06:24 +01:00
|
|
|
free(argv[i]);
|
|
|
|
|
free(argv);
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
for (size_t i = 0; i < action_argc; i++)
|
|
|
|
|
free(action_argv[i]);
|
|
|
|
|
free(action_argv);
|
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
2024-07-23 06:59:46 +02:00
|
|
|
|
|
|
|
|
notif->pid = pid;
|
|
|
|
|
notif->stdout_fd = stdout_fds[0];
|
|
|
|
|
return true;
|
2020-12-10 18:06:24 +01:00
|
|
|
}
|
2024-07-23 11:29:05 +02:00
|
|
|
|
2024-07-25 19:24:28 +02:00
|
|
|
void
|
|
|
|
|
notify_close(struct terminal *term, const char *id)
|
|
|
|
|
{
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
xassert(id != NULL);
|
2024-07-25 19:24:28 +02:00
|
|
|
LOG_DBG("close notification %s", id);
|
|
|
|
|
|
|
|
|
|
tll_foreach(term->active_notifications, it) {
|
|
|
|
|
const struct notification *notif = &it->item;
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
if (notif->id == NULL || !streq(notif->id, id))
|
2024-07-25 19:24:28 +02:00
|
|
|
continue;
|
|
|
|
|
|
2024-07-26 16:23:17 +02:00
|
|
|
if (term->conf->desktop_notifications.close.argv.args == NULL) {
|
|
|
|
|
LOG_DBG(
|
|
|
|
|
"trying to close notification \"%s\" by sending SIGINT to %u",
|
|
|
|
|
id, notif->pid);
|
2024-07-25 19:24:28 +02:00
|
|
|
|
2024-07-26 16:23:17 +02:00
|
|
|
if (notif->pid == 0) {
|
|
|
|
|
LOG_WARN(
|
|
|
|
|
"cannot close notification \"%s\": no helper process running",
|
|
|
|
|
id);
|
|
|
|
|
} else {
|
|
|
|
|
/* Best-effort... */
|
|
|
|
|
kill(notif->pid, SIGINT);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
LOG_DBG(
|
|
|
|
|
"trying to close notification \"%s\" "
|
|
|
|
|
"by running user defined command", id);
|
|
|
|
|
|
|
|
|
|
if (notif->external_id == 0) {
|
|
|
|
|
LOG_WARN("cannot close notification \"%s\": "
|
|
|
|
|
"no daemon assigned notification ID available", id);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-07-25 19:24:28 +02:00
|
|
|
|
2024-07-26 16:23:17 +02:00
|
|
|
char **argv = NULL;
|
|
|
|
|
size_t argc = 0;
|
2024-07-25 19:24:28 +02:00
|
|
|
|
2024-07-26 16:23:17 +02:00
|
|
|
char external_id[16];
|
|
|
|
|
xsnprintf(external_id, sizeof(external_id), "%u", notif->external_id);
|
|
|
|
|
|
|
|
|
|
if (!spawn_expand_template(
|
|
|
|
|
&term->conf->desktop_notifications.close, 1,
|
|
|
|
|
(const char *[]){"id"},
|
|
|
|
|
(const char *[]){external_id},
|
|
|
|
|
&argc, &argv))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-07-25 19:24:28 +02:00
|
|
|
|
2024-07-26 16:23:17 +02:00
|
|
|
int devnull = open("/dev/null", O_RDONLY);
|
|
|
|
|
spawn(
|
|
|
|
|
term->reaper, NULL, argv, devnull, -1, -1,
|
|
|
|
|
NULL, (void *)term, NULL);
|
2024-07-25 19:24:28 +02:00
|
|
|
|
2024-07-26 16:23:17 +02:00
|
|
|
if (devnull >= 0)
|
|
|
|
|
close(devnull);
|
2024-07-25 19:24:28 +02:00
|
|
|
|
2024-07-26 16:23:17 +02:00
|
|
|
for (size_t i = 0; i < argc; i++)
|
|
|
|
|
free(argv[i]);
|
|
|
|
|
free(argv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
2024-07-25 19:24:28 +02:00
|
|
|
}
|
2024-07-26 16:23:17 +02:00
|
|
|
|
|
|
|
|
LOG_WARN("cannot close notification \"%s\": no such notification", id);
|
2024-07-25 19:24:28 +02:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 11:29:05 +02:00
|
|
|
static void
|
|
|
|
|
add_icon(struct notification_icon *icon, const char *id, const char *symbolic_name,
|
|
|
|
|
const uint8_t *data, size_t data_sz)
|
|
|
|
|
{
|
|
|
|
|
icon->id = xstrdup(id);
|
|
|
|
|
icon->symbolic_name = symbolic_name != NULL ? xstrdup(symbolic_name) : NULL;
|
2024-07-24 15:59:52 +02:00
|
|
|
icon->tmp_file_name = NULL;
|
|
|
|
|
icon->tmp_file_fd = -1;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Dump in-line data to a temporary file. This allows us to pass
|
|
|
|
|
* the filename as a parameter to notification helpers
|
|
|
|
|
* (i.e. notify-send -i <path>).
|
|
|
|
|
*
|
|
|
|
|
* Optimization: since we always prefer (i.e. use) the symbolic
|
|
|
|
|
* name if present, there's no need to create a file on disk if we
|
|
|
|
|
* have a symbolic name.
|
|
|
|
|
*/
|
|
|
|
|
if (symbolic_name == NULL && data_sz > 0) {
|
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
|
|
|
write_icon_file(
|
|
|
|
|
data, data_sz,
|
|
|
|
|
&icon->tmp_file_fd,
|
|
|
|
|
&icon->tmp_file_name,
|
|
|
|
|
&icon->symbolic_name);
|
2024-07-23 11:29:05 +02:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 12:12:50 +02:00
|
|
|
LOG_DBG("added icon to cache: ID=%s: sym=%s, file=%s",
|
2024-07-24 15:59:52 +02:00
|
|
|
icon->id, icon->symbolic_name, icon->tmp_file_name);
|
2024-07-23 11:29:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
notify_icon_add(struct terminal *term, const char *id,
|
|
|
|
|
const char *symbolic_name, const uint8_t *data, size_t data_sz)
|
|
|
|
|
{
|
|
|
|
|
#if defined(_DEBUG)
|
|
|
|
|
for (size_t i = 0; i < ALEN(term->notification_icons); i++) {
|
|
|
|
|
struct notification_icon *icon = &term->notification_icons[i];
|
2024-07-24 16:04:14 +02:00
|
|
|
if (icon->id != NULL && streq(icon->id, id)) {
|
2024-07-23 11:29:05 +02:00
|
|
|
BUG("notification icon cache already contains \"%s\"", id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < ALEN(term->notification_icons); i++) {
|
|
|
|
|
struct notification_icon *icon = &term->notification_icons[i];
|
|
|
|
|
if (icon->id == NULL) {
|
|
|
|
|
add_icon(icon, id, symbolic_name, data, data_sz);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Cache full - throw out first entry, add new entry last */
|
|
|
|
|
notify_icon_free(&term->notification_icons[0]);
|
|
|
|
|
memmove(&term->notification_icons[0],
|
|
|
|
|
&term->notification_icons[1],
|
|
|
|
|
((ALEN(term->notification_icons) - 1) *
|
|
|
|
|
sizeof(term->notification_icons[0])));
|
|
|
|
|
|
|
|
|
|
add_icon(
|
|
|
|
|
&term->notification_icons[ALEN(term->notification_icons) - 1],
|
|
|
|
|
id, symbolic_name, data, data_sz);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
notify_icon_del(struct terminal *term, const char *id)
|
|
|
|
|
{
|
|
|
|
|
for (size_t i = 0; i < ALEN(term->notification_icons); i++) {
|
|
|
|
|
struct notification_icon *icon = &term->notification_icons[i];
|
|
|
|
|
|
2024-07-24 16:04:14 +02:00
|
|
|
if (icon->id == NULL || !streq(icon->id, id))
|
2024-07-23 11:29:05 +02:00
|
|
|
continue;
|
|
|
|
|
|
2024-07-23 12:12:50 +02:00
|
|
|
LOG_DBG("expelled %s from the notification icon cache", icon->id);
|
2024-07-23 11:29:05 +02:00
|
|
|
notify_icon_free(icon);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
notify_icon_free(struct notification_icon *icon)
|
|
|
|
|
{
|
2024-07-30 16:33:19 +02:00
|
|
|
if (icon->tmp_file_name != NULL) {
|
2024-07-24 15:59:52 +02:00
|
|
|
unlink(icon->tmp_file_name);
|
2024-07-30 17:24:48 +02:00
|
|
|
if (icon->tmp_file_fd >= 0)
|
2024-07-30 16:33:19 +02:00
|
|
|
close(icon->tmp_file_fd);
|
|
|
|
|
}
|
2024-07-23 11:29:05 +02:00
|
|
|
|
|
|
|
|
free(icon->id);
|
|
|
|
|
free(icon->symbolic_name);
|
2024-07-24 15:59:52 +02:00
|
|
|
free(icon->tmp_file_name);
|
2024-07-23 11:29:05 +02:00
|
|
|
|
|
|
|
|
icon->id = NULL;
|
|
|
|
|
icon->symbolic_name = NULL;
|
2024-07-24 15:59:52 +02:00
|
|
|
icon->tmp_file_name = NULL;
|
|
|
|
|
icon->tmp_file_fd = -1;
|
2024-07-23 11:29:05 +02:00
|
|
|
}
|