aboutsummaryrefslogtreecommitdiff
path: root/xwayland/xwm.c
diff options
context:
space:
mode:
Diffstat (limited to 'xwayland/xwm.c')
-rw-r--r--xwayland/xwm.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/xwayland/xwm.c b/xwayland/xwm.c
index b8b152fb..313bfc0a 100644
--- a/xwayland/xwm.c
+++ b/xwayland/xwm.c
@@ -61,6 +61,8 @@ const char *const atom_map[ATOM_LAST] = {
[TIMESTAMP] = "TIMESTAMP",
[DELETE] = "DELETE",
[NET_STARTUP_ID] = "_NET_STARTUP_ID",
+ [NET_STARTUP_INFO] = "_NET_STARTUP_INFO",
+ [NET_STARTUP_INFO_BEGIN] = "_NET_STARTUP_INFO_BEGIN",
[NET_WM_WINDOW_TYPE_NORMAL] = "_NET_WM_WINDOW_TYPE_NORMAL",
[NET_WM_WINDOW_TYPE_UTILITY] = "_NET_WM_WINDOW_TYPE_UTILITY",
[NET_WM_WINDOW_TYPE_TOOLTIP] = "_NET_WM_WINDOW_TYPE_TOOLTIP",
@@ -89,6 +91,14 @@ const char *const atom_map[ATOM_LAST] = {
[NET_CLIENT_LIST_STACKING] = "_NET_CLIENT_LIST_STACKING",
};
+#define STARTUP_INFO_REMOVE_PREFIX "remove: ID="
+struct pending_startup_id {
+ char *msg;
+ size_t len;
+ xcb_window_t window;
+ struct wl_list link;
+};
+
static const struct wlr_surface_role xwayland_surface_role;
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,
wlr_signal_emit_safe(&surface->events.request_activate, surface);
}
+static void pending_startup_id_destroy(struct pending_startup_id *pending) {
+ wl_list_remove(&pending->link);
+ free(pending->msg);
+ free(pending);
+}
+
+static void xwm_handle_net_startup_info_message(struct wlr_xwm *xwm,
+ xcb_client_message_event_t *ev) {
+ struct pending_startup_id *pending, *curr = NULL;
+ wl_list_for_each(pending, &xwm->pending_startup_ids, link) {
+ if (pending->window == ev->window) {
+ curr = pending;
+ break;
+ }
+ }
+
+ char *start;
+ size_t buf_len = sizeof(ev->data);
+ if (curr) {
+ curr->msg = realloc(curr->msg, curr->len + buf_len);
+ if (!curr->msg) {
+ pending_startup_id_destroy(curr);
+ return;
+ }
+ start = curr->msg + curr->len;
+ curr->len += buf_len;
+ } else {
+ curr = calloc(1, sizeof(struct pending_startup_id));
+ if (!curr)
+ return;
+ curr->window = ev->window;
+ curr->msg = malloc(buf_len);
+ if (!curr->msg) {
+ free(curr);
+ return;
+ }
+ start = curr->msg;
+ curr->len = buf_len;
+ wl_list_insert(&xwm->pending_startup_ids, &curr->link);
+ }
+
+ char *id = NULL;
+ const char *data = (const char *)ev->data.data8;
+ for (size_t i = 0; i < buf_len; i++) {
+ start[i] = data[i];
+ if (start[i] == '\0') {
+ if (strncmp(curr->msg, STARTUP_INFO_REMOVE_PREFIX,
+ strlen(STARTUP_INFO_REMOVE_PREFIX)) == 0 &&
+ strlen(curr->msg) > strlen(STARTUP_INFO_REMOVE_PREFIX)) {
+ id = curr->msg + strlen(STARTUP_INFO_REMOVE_PREFIX);
+ break;
+ } else {
+ wlr_log(WLR_ERROR, "Unhandled message '%s'\n", curr->msg);
+ pending_startup_id_destroy(curr);
+ return;
+ }
+ }
+ }
+
+ if (id) {
+ struct wlr_xwayland_remove_startup_info_event data = { id, ev->window };
+ wlr_log(WLR_DEBUG, "Got startup id: %s", id);
+ wlr_signal_emit_safe(&xwm->xwayland->events.remove_startup_info, &data);
+ pending_startup_id_destroy(curr);
+ }
+}
+
static void xwm_handle_wm_change_state_message(struct wlr_xwm *xwm,
xcb_client_message_event_t *ev) {
struct wlr_xwayland_surface *xsurface = lookup_surface(xwm, ev->window);
@@ -1399,6 +1476,9 @@ static void xwm_handle_client_message(struct wlr_xwm *xwm,
xwm_handle_wm_protocols_message(xwm, ev);
} else if (ev->type == xwm->atoms[NET_ACTIVE_WINDOW]) {
xwm_handle_net_active_window_message(xwm, ev);
+ } else if (ev->type == xwm->atoms[NET_STARTUP_INFO] ||
+ ev->type == xwm->atoms[NET_STARTUP_INFO_BEGIN]) {
+ xwm_handle_net_startup_info_message(xwm, ev);
} else if (ev->type == xwm->atoms[WM_CHANGE_STATE]) {
xwm_handle_wm_change_state_message(xwm, ev);
} else if (!xwm_handle_selection_client_message(xwm, ev)) {
@@ -1718,6 +1798,11 @@ void xwm_destroy(struct wlr_xwm *xwm) {
wl_list_remove(&xwm->compositor_destroy.link);
xcb_disconnect(xwm->xcb_conn);
+ struct pending_startup_id *pending, *next;
+ wl_list_for_each_safe(pending, next, &xwm->pending_startup_ids, link) {
+ pending_startup_id_destroy(pending);
+ }
+
xwm->xwayland->xwm = NULL;
free(xwm);
}
@@ -1958,6 +2043,7 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) {
wl_list_init(&xwm->surfaces);
wl_list_init(&xwm->surfaces_in_stack_order);
wl_list_init(&xwm->unpaired_surfaces);
+ wl_list_init(&xwm->pending_startup_ids);
xwm->ping_timeout = 10000;
xwm->xcb_conn = xcb_connect_to_fd(wm_fd, NULL);