notify: don't create icon file on disk when we're not going to use it

We always prefer the symbolic name. Thus, there's no need to write raw
PNG data to disk if we have a symbolic name.

Furthermore, keep the file open until the cache entry is evicted.
This commit is contained in:
Daniel Eklöf 2024-07-24 15:59:52 +02:00
parent 24168ed86e
commit 37ab3b1603
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 27 additions and 13 deletions

View file

@ -186,7 +186,7 @@ notify_notify(struct terminal *term, struct notification *notif)
if (icon->id != NULL && strcmp(icon->id, notif->icon_id) == 0) { if (icon->id != NULL && strcmp(icon->id, notif->icon_id) == 0) {
icon_name_or_path = icon->symbolic_name != NULL icon_name_or_path = icon->symbolic_name != NULL
? icon->symbolic_name ? icon->symbolic_name
: icon->tmp_file_on_disk; : icon->tmp_file_name;
break; break;
} }
} }
@ -299,11 +299,21 @@ add_icon(struct notification_icon *icon, const char *id, const char *symbolic_na
{ {
icon->id = xstrdup(id); icon->id = xstrdup(id);
icon->symbolic_name = symbolic_name != NULL ? xstrdup(symbolic_name) : NULL; icon->symbolic_name = symbolic_name != NULL ? xstrdup(symbolic_name) : NULL;
icon->tmp_file_on_disk = NULL; icon->tmp_file_name = NULL;
icon->tmp_file_fd = -1;
if (data_sz > 0) { /*
* 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) {
char name[64] = "/tmp/foot-notification-icon-cache-XXXXXX"; char name[64] = "/tmp/foot-notification-icon-cache-XXXXXX";
int fd = mkstemp(name); int fd = mkostemp(name, O_CLOEXEC);
if (fd < 0) { if (fd < 0) {
LOG_ERRNO("failed to create temporary file for icon cache"); LOG_ERRNO("failed to create temporary file for icon cache");
@ -312,16 +322,16 @@ add_icon(struct notification_icon *icon, const char *id, const char *symbolic_na
if (write(fd, data, data_sz) != (ssize_t)data_sz) { if (write(fd, data, data_sz) != (ssize_t)data_sz) {
LOG_ERRNO("failed to write icon data to temporary file"); LOG_ERRNO("failed to write icon data to temporary file");
close(fd);
} else { } else {
LOG_DBG("wrote icon data to %s", name); LOG_DBG("wrote icon data to %s", name);
icon->tmp_file_on_disk = xstrdup(name); icon->tmp_file_name = xstrdup(name);
icon->tmp_file_fd = fd;
} }
close(fd);
} }
LOG_DBG("added icon to cache: ID=%s: sym=%s, file=%s", LOG_DBG("added icon to cache: ID=%s: sym=%s, file=%s",
icon->id, icon->symbolic_name, icon->tmp_file_on_disk); icon->id, icon->symbolic_name, icon->tmp_file_name);
} }
void void
@ -375,14 +385,17 @@ notify_icon_del(struct terminal *term, const char *id)
void void
notify_icon_free(struct notification_icon *icon) notify_icon_free(struct notification_icon *icon)
{ {
if (icon->tmp_file_on_disk != NULL) if (icon->tmp_file_fd >= 0)
unlink(icon->tmp_file_on_disk); close(icon->tmp_file_fd);
if (icon->tmp_file_name != NULL)
unlink(icon->tmp_file_name);
free(icon->id); free(icon->id);
free(icon->symbolic_name); free(icon->symbolic_name);
free(icon->tmp_file_on_disk); free(icon->tmp_file_name);
icon->id = NULL; icon->id = NULL;
icon->symbolic_name = NULL; icon->symbolic_name = NULL;
icon->tmp_file_on_disk = NULL; icon->tmp_file_name = NULL;
icon->tmp_file_fd = -1;
} }

View file

@ -58,7 +58,8 @@ struct notification {
struct notification_icon { struct notification_icon {
char *id; char *id;
char *symbolic_name; char *symbolic_name;
char *tmp_file_on_disk; char *tmp_file_name;
int tmp_file_fd;
}; };
bool notify_notify(struct terminal *term, struct notification *notif); bool notify_notify(struct terminal *term, struct notification *notif);