mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-22 05:33:45 -04:00
osc: kitty notifications: updated support for icons
This implements the suggested protocol discussed in https://github.com/kovidgoyal/kitty/issues/7657. Icons are handled by loading a cache. Both in-band PNG data, and symbolic names are allowed. Applications use a graphical ID to reference the icon both when loading the cache, and when showing a notification. * 'g' is the graphical ID * 'n' is optional, and assigns a symbolic name to the icon * 'p=icon' - the payload is icon PNG data. It needs to be base64 encoded, but this is *not* implied. I.e. the application *must* use e=1 explicitly. To load an icon (in-band PNG data): printf '\e]99;g=123:p=icon;<base64-encoded-png-data>\e\\' or (symbolic name) printf '\e]99;g=123:n=firefox:p=icon;\e\\' Of course, we can combine the two, assigning *both* a symbolic name, *and* PNG data: printf '\e]99;g=123:n=firefox:p=icon;<base64-encoded-png>\e\\' Then, to use the icon in a notification: printf '\e]99;g=123;this is a notification\e\\' Foot also allows a *symbolic* icon to be defined and used at the same time: printf '\e]99;g=123:n=firefox;this is a notification\e\\' This obviously won't work with PNG data, since it uses the payload portion of the escape sequence.
This commit is contained in:
parent
c7cffea9ee
commit
ccb184ae64
7 changed files with 245 additions and 49 deletions
12
base64.c
12
base64.c
|
|
@ -42,7 +42,7 @@ static const char lookup[64] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
char *
|
char *
|
||||||
base64_decode(const char *s)
|
base64_decode(const char *s, size_t *size)
|
||||||
{
|
{
|
||||||
const size_t len = strlen(s);
|
const size_t len = strlen(s);
|
||||||
if (unlikely(len % 4 != 0)) {
|
if (unlikely(len % 4 != 0)) {
|
||||||
|
|
@ -54,6 +54,9 @@ base64_decode(const char *s)
|
||||||
if (unlikely(ret == NULL))
|
if (unlikely(ret == NULL))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (unlikely(size != NULL))
|
||||||
|
*size = len / 4 * 3;
|
||||||
|
|
||||||
for (size_t i = 0, o = 0; i < len; i += 4, o += 3) {
|
for (size_t i = 0, o = 0; i < len; i += 4, o += 3) {
|
||||||
unsigned a = reverse_lookup[(unsigned char)s[i + 0]];
|
unsigned a = reverse_lookup[(unsigned char)s[i + 0]];
|
||||||
unsigned b = reverse_lookup[(unsigned char)s[i + 1]];
|
unsigned b = reverse_lookup[(unsigned char)s[i + 1]];
|
||||||
|
|
@ -68,6 +71,13 @@ base64_decode(const char *s)
|
||||||
if (unlikely(i + 4 != len || (a | b) & P || (c & P && !(d & P))))
|
if (unlikely(i + 4 != len || (a | b) & P || (c & P && !(d & P))))
|
||||||
goto invalid;
|
goto invalid;
|
||||||
|
|
||||||
|
if (unlikely(size != NULL)) {
|
||||||
|
if (c & P)
|
||||||
|
*size = len / 4 * 3 - 2;
|
||||||
|
else
|
||||||
|
*size = len / 4 * 3 - 1;
|
||||||
|
}
|
||||||
|
|
||||||
c &= 63;
|
c &= 63;
|
||||||
d &= 63;
|
d &= 63;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
base64.h
2
base64.h
|
|
@ -3,6 +3,6 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
char *base64_decode(const char *s);
|
char *base64_decode(const char *s, size_t *out_len);
|
||||||
char *base64_encode(const uint8_t *data, size_t size);
|
char *base64_encode(const uint8_t *data, size_t size);
|
||||||
void base64_encode_final(const uint8_t *data, size_t size, char result[4]);
|
void base64_encode_final(const uint8_t *data, size_t size, char result[4]);
|
||||||
|
|
|
||||||
126
notify.c
126
notify.c
|
|
@ -10,11 +10,12 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#define LOG_MODULE "notify"
|
#define LOG_MODULE "notify"
|
||||||
#define LOG_ENABLE_DBG 0
|
#define LOG_ENABLE_DBG 1
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "spawn.h"
|
#include "spawn.h"
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
|
#include "util.h"
|
||||||
#include "wayland.h"
|
#include "wayland.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "xsnprintf.h"
|
#include "xsnprintf.h"
|
||||||
|
|
@ -26,7 +27,9 @@ notify_free(struct terminal *term, struct notification *notif)
|
||||||
free(notif->id);
|
free(notif->id);
|
||||||
free(notif->title);
|
free(notif->title);
|
||||||
free(notif->body);
|
free(notif->body);
|
||||||
free(notif->icon);
|
free(notif->icon_id);
|
||||||
|
free(notif->icon_symbolic_name);
|
||||||
|
free(notif->icon_data);
|
||||||
free(notif->xdg_token);
|
free(notif->xdg_token);
|
||||||
free(notif->stdout_data);
|
free(notif->stdout_data);
|
||||||
}
|
}
|
||||||
|
|
@ -167,11 +170,22 @@ notify_notify(const struct terminal *term, struct notification *notif)
|
||||||
|
|
||||||
/* Icon: use symbolic name from notification, if present,
|
/* Icon: use symbolic name from notification, if present,
|
||||||
otherwise fallback to the application ID */
|
otherwise fallback to the application ID */
|
||||||
const char *icon = notif->icon != NULL
|
const char *icon_name_or_path = term->app_id != NULL
|
||||||
? notif->icon
|
? term->app_id
|
||||||
: term->app_id != NULL
|
: term->conf->app_id;
|
||||||
? term->app_id
|
|
||||||
: term->conf->app_id;
|
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];
|
||||||
|
|
||||||
|
if (icon->id != NULL && strcmp(icon->id, notif->icon_id) == 0) {
|
||||||
|
icon_name_or_path = icon->symbolic_name != NULL
|
||||||
|
? icon->symbolic_name
|
||||||
|
: icon->tmp_file_on_disk;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LOG_DBG("notify: title=\"%s\", body=\"%s\"", title, body);
|
LOG_DBG("notify: title=\"%s\", body=\"%s\"", title, body);
|
||||||
|
|
||||||
|
|
@ -201,9 +215,11 @@ notify_notify(const struct terminal *term, struct notification *notif)
|
||||||
|
|
||||||
if (!spawn_expand_template(
|
if (!spawn_expand_template(
|
||||||
&term->conf->desktop_notifications.command, 6,
|
&term->conf->desktop_notifications.command, 6,
|
||||||
(const char *[]){"app-id", "window-title", "icon", "title", "body", "urgency"},
|
(const char *[]){
|
||||||
(const char *[]){term->app_id ? term->app_id : term->conf->app_id,
|
"app-id", "window-title", "icon", "title", "body", "urgency"},
|
||||||
term->window_title, icon, title, body, urgency_str},
|
(const char *[]){
|
||||||
|
term->app_id ? term->app_id : term->conf->app_id,
|
||||||
|
term->window_title, icon_name_or_path, title, body, urgency_str},
|
||||||
&argc, &argv))
|
&argc, &argv))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -254,3 +270,93 @@ notify_notify(const struct terminal *term, struct notification *notif)
|
||||||
notif->stdout_fd = stdout_fds[0];
|
notif->stdout_fd = stdout_fds[0];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
icon->tmp_file_on_disk = NULL;
|
||||||
|
|
||||||
|
if (data_sz > 0) {
|
||||||
|
char name[64] = "/tmp/foot-notification-icon-cache-XXXXXX";
|
||||||
|
int fd = mkstemp(name);
|
||||||
|
|
||||||
|
if (fd < 0) {
|
||||||
|
LOG_ERRNO("failed to create temporary file for icon cache");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
write(fd, data, data_sz);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
LOG_DBG("wrote icon data to %s", name);
|
||||||
|
icon->tmp_file_on_disk = xstrdup(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DBG("added icon to cache: %s: sym=%s, file=%s",
|
||||||
|
icon->id, icon->symbolic_name, icon->tmp_file_on_disk);
|
||||||
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
if (icon->id != NULL && strcmp(icon->id, id) == 0) {
|
||||||
|
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];
|
||||||
|
|
||||||
|
if (icon->id == NULL || strcmp(icon->id, id) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
notify_icon_free(icon);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
notify_icon_free(struct notification_icon *icon)
|
||||||
|
{
|
||||||
|
if (icon->tmp_file_on_disk != NULL)
|
||||||
|
unlink(icon->tmp_file_on_disk);
|
||||||
|
|
||||||
|
free(icon->id);
|
||||||
|
free(icon->symbolic_name);
|
||||||
|
free(icon->tmp_file_on_disk);
|
||||||
|
|
||||||
|
icon->id = NULL;
|
||||||
|
icon->symbolic_name = NULL;
|
||||||
|
icon->tmp_file_on_disk = NULL;
|
||||||
|
}
|
||||||
|
|
|
||||||
19
notify.h
19
notify.h
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
struct terminal;
|
struct terminal;
|
||||||
|
|
@ -29,7 +30,11 @@ struct notification {
|
||||||
char *id;
|
char *id;
|
||||||
char *title;
|
char *title;
|
||||||
char *body;
|
char *body;
|
||||||
char *icon;
|
|
||||||
|
char *icon_id;
|
||||||
|
char *icon_symbolic_name;
|
||||||
|
uint8_t *icon_data;
|
||||||
|
size_t icon_data_sz;
|
||||||
|
|
||||||
enum notify_when when;
|
enum notify_when when;
|
||||||
enum notify_urgency urgency;
|
enum notify_urgency urgency;
|
||||||
|
|
@ -49,5 +54,17 @@ struct notification {
|
||||||
size_t stdout_sz;
|
size_t stdout_sz;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct notification_icon {
|
||||||
|
char *id;
|
||||||
|
char *symbolic_name;
|
||||||
|
char *tmp_file_on_disk;
|
||||||
|
};
|
||||||
|
|
||||||
bool notify_notify(const struct terminal *term, struct notification *notif);
|
bool notify_notify(const struct terminal *term, struct notification *notif);
|
||||||
void notify_free(struct terminal *term, struct notification *notif);
|
void notify_free(struct terminal *term, struct notification *notif);
|
||||||
|
|
||||||
|
void notify_icon_add(struct terminal *term, const char *id,
|
||||||
|
const char *symbolic_name, const uint8_t *data,
|
||||||
|
size_t data_sz);
|
||||||
|
void notify_icon_del(struct terminal *term, const char *id);
|
||||||
|
void notify_icon_free(struct notification_icon *icon);
|
||||||
|
|
|
||||||
128
osc.c
128
osc.c
|
|
@ -67,7 +67,7 @@ osc_to_clipboard(struct terminal *term, const char *target,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *decoded = base64_decode(base64_data);
|
char *decoded = base64_decode(base64_data, NULL);
|
||||||
if (decoded == NULL) {
|
if (decoded == NULL) {
|
||||||
if (errno == EINVAL)
|
if (errno == EINVAL)
|
||||||
LOG_WARN("OSC: invalid clipboard data: %s", base64_data);
|
LOG_WARN("OSC: invalid clipboard data: %s", base64_data);
|
||||||
|
|
@ -579,12 +579,19 @@ kitty_notification(struct terminal *term, char *string)
|
||||||
payload++;
|
payload++;
|
||||||
|
|
||||||
char *id = xstrdup("0"); /* The 'i' parameter */
|
char *id = xstrdup("0"); /* The 'i' parameter */
|
||||||
char *icon = NULL; /* The 'I' parameter */
|
char *icon_id = NULL; /* The 'g' parameter */
|
||||||
|
char *symbolic_icon = NULL; /* The 'n' parameter */
|
||||||
bool focus = true; /* The 'a' parameter */
|
bool focus = true; /* The 'a' parameter */
|
||||||
bool report = false; /* The 'a' parameter */
|
bool report = false; /* The 'a' parameter */
|
||||||
bool done = true; /* The 'd' parameter */
|
bool done = true; /* The 'd' parameter */
|
||||||
bool base64 = false; /* The 'e' parameter */
|
bool base64 = false; /* The 'e' parameter */
|
||||||
bool payload_is_title = true; /* The 'p' parameter */
|
|
||||||
|
size_t payload_size;
|
||||||
|
enum {
|
||||||
|
PAYLOAD_TITLE,
|
||||||
|
PAYLOAD_BODY,
|
||||||
|
PAYLOAD_ICON,
|
||||||
|
} payload_type = PAYLOAD_TITLE; /* The 'p' parameter */
|
||||||
|
|
||||||
enum notify_when when = NOTIFY_ALWAYS;
|
enum notify_when when = NOTIFY_ALWAYS;
|
||||||
enum notify_urgency urgency = NOTIFY_URGENCY_NORMAL;
|
enum notify_urgency urgency = NOTIFY_URGENCY_NORMAL;
|
||||||
|
|
@ -653,9 +660,11 @@ kitty_notification(struct terminal *term, char *string)
|
||||||
case 'p':
|
case 'p':
|
||||||
/* payload content: title|body */
|
/* payload content: title|body */
|
||||||
if (strcmp(value, "title") == 0)
|
if (strcmp(value, "title") == 0)
|
||||||
payload_is_title = true;
|
payload_type = PAYLOAD_TITLE;
|
||||||
else if (strcmp(value, "body") == 0)
|
else if (strcmp(value, "body") == 0)
|
||||||
payload_is_title = false;
|
payload_type = PAYLOAD_BODY;
|
||||||
|
else if (strcmp(value, "icon") == 0)
|
||||||
|
payload_type = PAYLOAD_ICON;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'o':
|
case 'o':
|
||||||
|
|
@ -680,21 +689,26 @@ kitty_notification(struct terminal *term, char *string)
|
||||||
urgency = NOTIFY_URGENCY_CRITICAL;
|
urgency = NOTIFY_URGENCY_CRITICAL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
case 'g':
|
||||||
* The options below are not (yet) part of the official spec.
|
free(icon_id);
|
||||||
*/
|
icon_id = xstrdup(value);
|
||||||
case 'I':
|
break;
|
||||||
/* icon: only symbolic names allowed; absolute paths are ignored */
|
|
||||||
if (value[0] != '/')
|
case 'n':
|
||||||
icon = xstrdup(value);
|
free(symbolic_icon);
|
||||||
|
symbolic_icon = xstrdup(value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (base64)
|
if (base64) {
|
||||||
payload = base64_decode(payload);
|
payload = base64_decode(payload, &payload_size);
|
||||||
else
|
if (payload == NULL)
|
||||||
|
goto out;
|
||||||
|
} else {
|
||||||
payload = xstrdup(payload);
|
payload = xstrdup(payload);
|
||||||
|
payload_size = strlen(payload);
|
||||||
|
}
|
||||||
|
|
||||||
LOG_DBG("id=%s, done=%d, focus=%d, report=%d, base64=%d, icon=%s, payload: %s, "
|
LOG_DBG("id=%s, done=%d, focus=%d, report=%d, base64=%d, icon=%s, payload: %s, "
|
||||||
"honor: %s, urgency: %s, %s: %s",
|
"honor: %s, urgency: %s, %s: %s",
|
||||||
|
|
@ -724,9 +738,6 @@ kitty_notification(struct terminal *term, char *string)
|
||||||
if (notif == NULL) {
|
if (notif == NULL) {
|
||||||
tll_push_front(term->notifications, ((struct notification){
|
tll_push_front(term->notifications, ((struct notification){
|
||||||
.id = id,
|
.id = id,
|
||||||
.icon = NULL,
|
|
||||||
.title = NULL,
|
|
||||||
.body = NULL,
|
|
||||||
.when = when,
|
.when = when,
|
||||||
.urgency = urgency,
|
.urgency = urgency,
|
||||||
.focus = focus,
|
.focus = focus,
|
||||||
|
|
@ -753,34 +764,78 @@ kitty_notification(struct terminal *term, char *string)
|
||||||
if (have_u)
|
if (have_u)
|
||||||
notif->urgency = urgency;
|
notif->urgency = urgency;
|
||||||
|
|
||||||
if (icon != NULL) {
|
if (icon_id != NULL) {
|
||||||
free(notif->icon);
|
free(notif->icon_id);
|
||||||
notif->icon = icon;
|
notif->icon_id = icon_id;
|
||||||
icon = NULL; /* Prevent double free */
|
icon_id = NULL; /* Prevent double free */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (payload_is_title) {
|
if (symbolic_icon != NULL) {
|
||||||
if (notif->title == NULL) {
|
free(notif->icon_symbolic_name);
|
||||||
notif->title = payload;
|
notif->icon_symbolic_name = symbolic_icon;
|
||||||
|
symbolic_icon = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handled chunked payload - append to existing metadata */
|
||||||
|
switch (payload_type) {
|
||||||
|
case PAYLOAD_TITLE:
|
||||||
|
case PAYLOAD_BODY: {
|
||||||
|
char **ptr = payload_type == PAYLOAD_TITLE
|
||||||
|
? ¬if->title
|
||||||
|
: ¬if->body;
|
||||||
|
|
||||||
|
if (*ptr == NULL) {
|
||||||
|
*ptr = payload;
|
||||||
payload = NULL;
|
payload = NULL;
|
||||||
} else {
|
} else {
|
||||||
char *old_title = notif->title;
|
char *old = *ptr;
|
||||||
notif->title = xstrjoin(old_title, payload);
|
*ptr = xstrjoin(old, payload);
|
||||||
free(old_title);
|
free(old);
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
if (notif->body == NULL) {
|
}
|
||||||
notif->body = payload;
|
|
||||||
|
case PAYLOAD_ICON:
|
||||||
|
if (notif->icon_data == NULL) {
|
||||||
|
notif->icon_data = (uint8_t *)payload;
|
||||||
|
notif->icon_data_sz = payload_size;
|
||||||
payload = NULL;
|
payload = NULL;
|
||||||
} else {
|
} else {
|
||||||
char *old_body = notif->body;
|
notif->icon_data = xrealloc(
|
||||||
notif->body = xstrjoin(old_body, payload);
|
notif->icon_data, notif->icon_data_sz + payload_size);
|
||||||
free(old_body);
|
memcpy(¬if->icon_data[notif->icon_data_sz], payload, payload_size);
|
||||||
|
notif->icon_data_sz += payload_size;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (done) {
|
if (done) {
|
||||||
if (!notify_notify(term, notif)) {
|
/* Update icon cache, if necessary */
|
||||||
|
if (notif->icon_id != NULL &&
|
||||||
|
(notif->icon_symbolic_name != NULL || notif->icon_data != NULL))
|
||||||
|
{
|
||||||
|
notify_icon_del(term, notif->icon_id);
|
||||||
|
notify_icon_add(term, notif->icon_id,
|
||||||
|
notif->icon_symbolic_name,
|
||||||
|
notif->icon_data, notif->icon_data_sz);
|
||||||
|
|
||||||
|
/* Don't need this anymore */
|
||||||
|
free(notif->icon_symbolic_name);
|
||||||
|
free(notif->icon_data);
|
||||||
|
notif->icon_symbolic_name = NULL;
|
||||||
|
notif->icon_data = NULL;
|
||||||
|
notif->icon_data_sz = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Show notification.
|
||||||
|
*
|
||||||
|
* The checks for title|body is to handle notifications that
|
||||||
|
* only load icon data into the icon cache
|
||||||
|
*/
|
||||||
|
if ((notif->title != NULL || notif->body != NULL) &&
|
||||||
|
!notify_notify(term, notif))
|
||||||
|
{
|
||||||
tll_foreach(term->notifications, it) {
|
tll_foreach(term->notifications, it) {
|
||||||
if (&it->item == notif) {
|
if (&it->item == notif) {
|
||||||
notify_free(term, &it->item);
|
notify_free(term, &it->item);
|
||||||
|
|
@ -793,7 +848,8 @@ kitty_notification(struct terminal *term, char *string)
|
||||||
|
|
||||||
out:
|
out:
|
||||||
free(id);
|
free(id);
|
||||||
free(icon);
|
free(icon_id);
|
||||||
|
free(symbolic_icon);
|
||||||
free(payload);
|
free(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1823,6 +1823,9 @@ term_destroy(struct terminal *term)
|
||||||
tll_remove(term->notifications, it);
|
tll_remove(term->notifications, it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ALEN(term->notification_icons); i++)
|
||||||
|
notify_icon_free(&term->notification_icons[i]);
|
||||||
|
|
||||||
sixel_fini(term);
|
sixel_fini(term);
|
||||||
|
|
||||||
term_ime_reset(term);
|
term_ime_reset(term);
|
||||||
|
|
@ -2033,6 +2036,9 @@ term_reset(struct terminal *term, bool hard)
|
||||||
tll_remove(term->notifications, it);
|
tll_remove(term->notifications, it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ALEN(term->notification_icons); i++)
|
||||||
|
notify_icon_free(&term->notification_icons[i]);
|
||||||
|
|
||||||
term->grapheme_shaping = term->conf->tweak.grapheme_shaping;
|
term->grapheme_shaping = term->conf->tweak.grapheme_shaping;
|
||||||
|
|
||||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||||
|
|
|
||||||
|
|
@ -802,6 +802,7 @@ struct terminal {
|
||||||
/* Notifications that either haven't been sent yet, or have been
|
/* Notifications that either haven't been sent yet, or have been
|
||||||
sent but not yet dismissed */
|
sent but not yet dismissed */
|
||||||
tll(struct notification) notifications;
|
tll(struct notification) notifications;
|
||||||
|
struct notification_icon notification_icons[32];
|
||||||
|
|
||||||
char *foot_exe;
|
char *foot_exe;
|
||||||
char *cwd;
|
char *cwd;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue