diff --git a/client-protocol.h b/client-protocol.h index c1291f28..b0f39055 100644 --- a/client-protocol.h +++ b/client-protocol.h @@ -12,15 +12,18 @@ struct client_string { struct client_data { bool hold:1; bool no_wait:1; - uint8_t reserved:6; + bool xdga_token:1; + uint8_t reserved:5; + uint8_t token_len; uint16_t cwd_len; uint16_t override_count; uint16_t argc; /* char cwd[static cwd_len]; */ + /* char token[static token_len]; */ /* struct client_string overrides[static override_count]; */ /* struct client_string argv[static argc]; */ } __attribute__((packed)); -_Static_assert(sizeof(struct client_data) == 7, "protocol struct size error"); +_Static_assert(sizeof(struct client_data) == 8, "protocol struct size error"); diff --git a/client.c b/client.c index 5d3bd58c..b6749835 100644 --- a/client.c +++ b/client.c @@ -156,6 +156,11 @@ main(int argc, char *const *argv) /* Used to format overrides */ bool no_wait = false; + /* For XDG activation */ + const char *token = getenv("XDG_ACTIVATION_TOKEN"); + bool xdga_token = token != NULL; + size_t token_len = xdga_token ? strlen(token) + 1 : 0; + char buf[1024]; /* Total packet length, not (yet) including overrides or argv[] */ @@ -373,13 +378,15 @@ main(int argc, char *const *argv) const struct client_data data = { .hold = hold, .no_wait = no_wait, + .xdga_token = xdga_token, + .token_len = token_len, .cwd_len = cwd_len, .override_count = override_count, .argc = argc, }; /* Total packet length, not (yet) including argv[] */ - total_len += sizeof(data) + cwd_len; + total_len += sizeof(data) + cwd_len + token_len; /* Add argv[] size to total packet length */ cargv = xmalloc(argc * sizeof(cargv[0])); @@ -398,6 +405,7 @@ main(int argc, char *const *argv) /* Check for size overflows */ if (total_len >= 1llu << (8 * sizeof(uint32_t)) || cwd_len >= 1 << (8 * sizeof(data.cwd_len)) || + token_len >= 1 << (8 * sizeof(data.token_len)) || override_count > (size_t)(unsigned int)data.override_count || argc > (int)(unsigned int)data.argc) { @@ -414,6 +422,15 @@ main(int argc, char *const *argv) goto err; } + /* Send XDGA token, if we have one */ + if (xdga_token) { + if (sendall(fd, token, token_len) != token_len) + { + LOG_ERRNO("failed to send xdg activation token to server"); + goto err; + } + } + /* Send overrides */ tll_foreach(overrides, it) { const struct override *o = &it->item; diff --git a/main.c b/main.c index 07f58080..851a4856 100644 --- a/main.c +++ b/main.c @@ -160,6 +160,10 @@ main(int argc, char *const *argv) static const int foot_exit_failure = -26; int ret = foot_exit_failure; + /* XDG startup notifications */ + const char *token = getenv("XDG_ACTIVATION_TOKEN"); + unsetenv("XDG_ACTIVATION_TOKEN"); + /* Startup notifications; we don't support it, but must ensure we * don't pass this on to programs launched by us */ unsetenv("DESKTOP_STARTUP_ID"); @@ -530,7 +534,8 @@ main(int argc, char *const *argv) goto out; if (!as_server && (term = term_init( - &conf, fdm, reaper, wayl, "foot", cwd, argc, argv, + &conf, fdm, reaper, wayl, "foot", cwd, token, + argc, argv, &term_shutdown_cb, &shutdown_ctx)) == NULL) { goto out; } diff --git a/pgo/pgo.c b/pgo/pgo.c index b4bd0a17..0be2bc62 100644 --- a/pgo/pgo.c +++ b/pgo/pgo.c @@ -75,7 +75,7 @@ render_xcursor_set(struct seat *seat, struct terminal *term, const char *xcursor } struct wl_window * -wayl_win_init(struct terminal *term) +wayl_win_init(struct terminal *term, const char *token) { return NULL; } diff --git a/server.c b/server.c index a5d87b04..1d31abc6 100644 --- a/server.c +++ b/server.c @@ -244,6 +244,17 @@ fdm_client(struct fdm *fdm, int fd, int events, void *data) const char *cwd = (const char *)p; p += cdata.cwd_len; LOG_DBG("CWD = %.*s", cdata.cwd_len, cwd); + /* XDGA token */ + const char *token = NULL; + if (cdata.xdga_token) { + + CHECK_BUF_AND_NULL(cdata.token_len); + token = (const char *)p; p += cdata.token_len; + LOG_DBG("XDGA = %.*s", cdata.token_len, token); + } else { + LOG_DBG("No XDGA token"); + } + /* Overrides */ for (uint16_t i = 0; i < cdata.override_count; i++) { struct client_string arg; @@ -303,7 +314,7 @@ fdm_client(struct fdm *fdm, int fd, int events, void *data) instance->terminal = term_init( conf != NULL ? conf : server->conf, - server->fdm, server->reaper, server->wayl, "footclient", cwd, + server->fdm, server->reaper, server->wayl, "footclient", cwd, token, cdata.argc, argv, &term_shutdown_handler, instance); if (instance->terminal == NULL) { diff --git a/terminal.c b/terminal.c index 50c43d39..910a8857 100644 --- a/terminal.c +++ b/terminal.c @@ -1033,7 +1033,7 @@ static void fdm_client_terminated( struct terminal * term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, struct wayland *wayl, const char *foot_exe, const char *cwd, - int argc, char *const *argv, + const char *token, int argc, char *const *argv, void (*shutdown_cb)(void *data, int exit_code), void *shutdown_data) { int ptmx = -1; @@ -1257,7 +1257,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, sizeof(term->colors.table)); /* Initialize the Wayland window backend */ - if ((term->window = wayl_win_init(term)) == NULL) + if ((term->window = wayl_win_init(term, token)) == NULL) goto err; /* Load fonts */ diff --git a/terminal.h b/terminal.h index 73988ba8..8c847cfd 100644 --- a/terminal.h +++ b/terminal.h @@ -642,7 +642,7 @@ struct config; struct terminal *term_init( const struct config *conf, struct fdm *fdm, struct reaper *reaper, struct wayland *wayl, const char *foot_exe, const char *cwd, - int argc, char *const *argv, + const char *token, int argc, char *const *argv, void (*shutdown_cb)(void *data, int exit_code), void *shutdown_data); bool term_shutdown(struct terminal *term); diff --git a/wayland.c b/wayland.c index 49c8ed92..22e3d6dc 100644 --- a/wayland.c +++ b/wayland.c @@ -1374,7 +1374,7 @@ wayl_destroy(struct wayland *wayl) } struct wl_window * -wayl_win_init(struct terminal *term) +wayl_win_init(struct terminal *term, const char *token) { struct wayland *wayl = term->wl; const struct config *conf = term->conf; @@ -1444,6 +1444,10 @@ wayl_win_init(struct terminal *term) wl_surface_commit(win->surface); + /* Complete XDG startup notification */ + if (token) + xdg_activation_v1_activate(wayl->xdg_activation, token, win->surface); + if (conf->tweak.render_timer_osd) { if (!wayl_win_subsurface_new(win, &win->render_timer)) { LOG_ERR("failed to create render timer surface"); diff --git a/wayland.h b/wayland.h index b92f622d..0fffc0a7 100644 --- a/wayland.h +++ b/wayland.h @@ -492,7 +492,7 @@ bool wayl_reload_xcursor_theme(struct seat *seat, int new_scale); void wayl_flush(struct wayland *wayl); void wayl_roundtrip(struct wayland *wayl); -struct wl_window *wayl_win_init(struct terminal *term); +struct wl_window *wayl_win_init(struct terminal *term, const char *token); void wayl_win_destroy(struct wl_window *win); bool wayl_win_set_urgent(struct wl_window *win);