mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
foot/client: implement xdga client activation
This is an application of the xdg activation protocol that will allow compositors to associate new foot toplevels with the command that launched them. footclient receives an activation token from the launcher which the compositor can use to track application startup. It passes the token to the foot server, which then activates the new window with the token to complete the startup sequence.
This commit is contained in:
parent
347e79f8a1
commit
99d5bf64bc
9 changed files with 51 additions and 11 deletions
|
|
@ -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");
|
||||
|
|
|
|||
19
client.c
19
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;
|
||||
|
|
|
|||
7
main.c
7
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
13
server.c
13
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) {
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue