Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit e479dc1

Browse files
agxemersion
authored andcommitted
xwayland: Allow to retrieve startup-id via _NET_STARTUP_INFO
A launchee notifies with a "remove"¹ message when done starting up. Catch these and forward to the compositor. This allows the compositor to end the startup sequence that might have been started by another protocol like xdg-activation. We don't handle other messages since we expect the launcher to use a wayland protocol like xdg-activation. While `_NET_STARTUP_ID` helps to associate toplevels with startup-ids this signals the end of the startup sequence. 1) https://specifications.freedesktop.org/startup-notification-spec/startup-notification-latest.txt
1 parent 4e7a870 commit e479dc1

File tree

4 files changed

+96
-0
lines changed

4 files changed

+96
-0
lines changed

include/wlr/xwayland.h

+6
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ struct wlr_xwayland {
7272
struct {
7373
struct wl_signal ready;
7474
struct wl_signal new_surface;
75+
struct wl_signal remove_startup_info;
7576
} events;
7677

7778
/**
@@ -232,6 +233,11 @@ struct wlr_xwayland_move_event {
232233
struct wlr_xwayland_surface *surface;
233234
};
234235

236+
struct wlr_xwayland_remove_startup_info_event {
237+
const char *id;
238+
xcb_window_t window;
239+
};
240+
235241
struct wlr_xwayland_resize_event {
236242
struct wlr_xwayland_surface *surface;
237243
uint32_t edges;

include/xwayland/xwm.h

+3
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ enum atom_name {
5656
TIMESTAMP,
5757
DELETE,
5858
NET_STARTUP_ID,
59+
NET_STARTUP_INFO,
60+
NET_STARTUP_INFO_BEGIN,
5961
NET_WM_WINDOW_TYPE_NORMAL,
6062
NET_WM_WINDOW_TYPE_UTILITY,
6163
NET_WM_WINDOW_TYPE_TOOLTIP,
@@ -113,6 +115,7 @@ struct wlr_xwm {
113115
// Surfaces in bottom-to-top stacking order, for _NET_CLIENT_LIST_STACKING
114116
struct wl_list surfaces_in_stack_order; // wlr_xwayland_surface::stack_link
115117
struct wl_list unpaired_surfaces; // wlr_xwayland_surface::unpaired_link
118+
struct wl_list pending_startup_ids; // pending_startup_id
116119

117120
struct wlr_drag *drag;
118121
struct wlr_xwayland_surface *drag_focus;

xwayland/xwayland.c

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ struct wlr_xwayland *wlr_xwayland_create(struct wl_display *wl_display,
8181

8282
wl_signal_init(&xwayland->events.new_surface);
8383
wl_signal_init(&xwayland->events.ready);
84+
wl_signal_init(&xwayland->events.remove_startup_info);
8485

8586
struct wlr_xwayland_server_options options = {
8687
.lazy = lazy,

xwayland/xwm.c

+86
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ const char *const atom_map[ATOM_LAST] = {
6161
[TIMESTAMP] = "TIMESTAMP",
6262
[DELETE] = "DELETE",
6363
[NET_STARTUP_ID] = "_NET_STARTUP_ID",
64+
[NET_STARTUP_INFO] = "_NET_STARTUP_INFO",
65+
[NET_STARTUP_INFO_BEGIN] = "_NET_STARTUP_INFO_BEGIN",
6466
[NET_WM_WINDOW_TYPE_NORMAL] = "_NET_WM_WINDOW_TYPE_NORMAL",
6567
[NET_WM_WINDOW_TYPE_UTILITY] = "_NET_WM_WINDOW_TYPE_UTILITY",
6668
[NET_WM_WINDOW_TYPE_TOOLTIP] = "_NET_WM_WINDOW_TYPE_TOOLTIP",
@@ -89,6 +91,14 @@ const char *const atom_map[ATOM_LAST] = {
8991
[NET_CLIENT_LIST_STACKING] = "_NET_CLIENT_LIST_STACKING",
9092
};
9193

94+
#define STARTUP_INFO_REMOVE_PREFIX "remove: ID="
95+
struct pending_startup_id {
96+
char *msg;
97+
size_t len;
98+
xcb_window_t window;
99+
struct wl_list link;
100+
};
101+
92102
static const struct wlr_surface_role xwayland_surface_role;
93103

94104
bool wlr_surface_is_xwayland_surface(struct wlr_surface *surface) {
@@ -1361,6 +1371,73 @@ static void xwm_handle_net_active_window_message(struct wlr_xwm *xwm,
13611371
wlr_signal_emit_safe(&surface->events.request_activate, surface);
13621372
}
13631373

1374+
static void pending_startup_id_destroy(struct pending_startup_id *pending) {
1375+
wl_list_remove(&pending->link);
1376+
free(pending->msg);
1377+
free(pending);
1378+
}
1379+
1380+
static void xwm_handle_net_startup_info_message(struct wlr_xwm *xwm,
1381+
xcb_client_message_event_t *ev) {
1382+
struct pending_startup_id *pending, *curr = NULL;
1383+
wl_list_for_each(pending, &xwm->pending_startup_ids, link) {
1384+
if (pending->window == ev->window) {
1385+
curr = pending;
1386+
break;
1387+
}
1388+
}
1389+
1390+
char *start;
1391+
size_t buf_len = sizeof(ev->data);
1392+
if (curr) {
1393+
curr->msg = realloc(curr->msg, curr->len + buf_len);
1394+
if (!curr->msg) {
1395+
pending_startup_id_destroy(curr);
1396+
return;
1397+
}
1398+
start = curr->msg + curr->len;
1399+
curr->len += buf_len;
1400+
} else {
1401+
curr = calloc(1, sizeof(struct pending_startup_id));
1402+
if (!curr)
1403+
return;
1404+
curr->window = ev->window;
1405+
curr->msg = malloc(buf_len);
1406+
if (!curr->msg) {
1407+
free(curr);
1408+
return;
1409+
}
1410+
start = curr->msg;
1411+
curr->len = buf_len;
1412+
wl_list_insert(&xwm->pending_startup_ids, &curr->link);
1413+
}
1414+
1415+
char *id = NULL;
1416+
const char *data = (const char *)ev->data.data8;
1417+
for (size_t i = 0; i < buf_len; i++) {
1418+
start[i] = data[i];
1419+
if (start[i] == '\0') {
1420+
if (strncmp(curr->msg, STARTUP_INFO_REMOVE_PREFIX,
1421+
strlen(STARTUP_INFO_REMOVE_PREFIX)) == 0 &&
1422+
strlen(curr->msg) > strlen(STARTUP_INFO_REMOVE_PREFIX)) {
1423+
id = curr->msg + strlen(STARTUP_INFO_REMOVE_PREFIX);
1424+
break;
1425+
} else {
1426+
wlr_log(WLR_ERROR, "Unhandled message '%s'\n", curr->msg);
1427+
pending_startup_id_destroy(curr);
1428+
return;
1429+
}
1430+
}
1431+
}
1432+
1433+
if (id) {
1434+
struct wlr_xwayland_remove_startup_info_event data = { id, ev->window };
1435+
wlr_log(WLR_DEBUG, "Got startup id: %s", id);
1436+
wlr_signal_emit_safe(&xwm->xwayland->events.remove_startup_info, &data);
1437+
pending_startup_id_destroy(curr);
1438+
}
1439+
}
1440+
13641441
static void xwm_handle_wm_change_state_message(struct wlr_xwm *xwm,
13651442
xcb_client_message_event_t *ev) {
13661443
struct wlr_xwayland_surface *xsurface = lookup_surface(xwm, ev->window);
@@ -1399,6 +1476,9 @@ static void xwm_handle_client_message(struct wlr_xwm *xwm,
13991476
xwm_handle_wm_protocols_message(xwm, ev);
14001477
} else if (ev->type == xwm->atoms[NET_ACTIVE_WINDOW]) {
14011478
xwm_handle_net_active_window_message(xwm, ev);
1479+
} else if (ev->type == xwm->atoms[NET_STARTUP_INFO] ||
1480+
ev->type == xwm->atoms[NET_STARTUP_INFO_BEGIN]) {
1481+
xwm_handle_net_startup_info_message(xwm, ev);
14021482
} else if (ev->type == xwm->atoms[WM_CHANGE_STATE]) {
14031483
xwm_handle_wm_change_state_message(xwm, ev);
14041484
} else if (!xwm_handle_selection_client_message(xwm, ev)) {
@@ -1718,6 +1798,11 @@ void xwm_destroy(struct wlr_xwm *xwm) {
17181798
wl_list_remove(&xwm->compositor_destroy.link);
17191799
xcb_disconnect(xwm->xcb_conn);
17201800

1801+
struct pending_startup_id *pending, *next;
1802+
wl_list_for_each_safe(pending, next, &xwm->pending_startup_ids, link) {
1803+
pending_startup_id_destroy(pending);
1804+
}
1805+
17211806
xwm->xwayland->xwm = NULL;
17221807
free(xwm);
17231808
}
@@ -1958,6 +2043,7 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) {
19582043
wl_list_init(&xwm->surfaces);
19592044
wl_list_init(&xwm->surfaces_in_stack_order);
19602045
wl_list_init(&xwm->unpaired_surfaces);
2046+
wl_list_init(&xwm->pending_startup_ids);
19612047
xwm->ping_timeout = 10000;
19622048

19632049
xwm->xcb_conn = xcb_connect_to_fd(wm_fd, NULL);

0 commit comments

Comments
 (0)