diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 54c09bbfe..e06fd31f8 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -476,11 +476,6 @@ static void update_node_update_outputs(struct wlr_scene_node *node, } } - if (old_primary_output != scene_buffer->primary_output) { - scene_buffer->prev_feedback_options = - (struct wlr_linux_dmabuf_feedback_v1_init_options){0}; - } - uint64_t old_active = scene_buffer->active_outputs; scene_buffer->active_outputs = active_outputs; diff --git a/xwayland/selection/dnd.c b/xwayland/selection/dnd.c index 31e588baf..f80a55d4d 100644 --- a/xwayland/selection/dnd.c +++ b/xwayland/selection/dnd.c @@ -83,7 +83,12 @@ static void xwm_dnd_send_enter(struct wlr_xwm *xwm) { // data and must be retrieved with the DND_TYPE_LIST property data.data32[1] |= 1; - xcb_atom_t targets[n]; + xcb_atom_t *targets = malloc(n * sizeof(targets[0])); + if (targets == NULL) { + wlr_log(WLR_ERROR, "Allocation failed"); + return; + } + size_t i = 0; char **mime_type_ptr; wl_array_for_each(mime_type_ptr, mime_types) { @@ -99,6 +104,8 @@ static void xwm_dnd_send_enter(struct wlr_xwm *xwm) { XCB_ATOM_ATOM, 32, // format n, targets); + + free(targets); } xwm_dnd_send_event(xwm, xwm->atoms[DND_ENTER], &data); diff --git a/xwayland/selection/incoming.c b/xwayland/selection/incoming.c index 85d7775cd..b4f744ee2 100644 --- a/xwayland/selection/incoming.c +++ b/xwayland/selection/incoming.c @@ -103,7 +103,7 @@ static int write_selection_property_to_wl_client(int fd, uint32_t mask, void *data) { struct wlr_xwm_selection_transfer *transfer = data; - char *property = xcb_get_property_value(transfer->property_reply); + const char *property = xcb_get_property_value(transfer->property_reply); int remainder = xcb_get_property_value_length(transfer->property_reply) - transfer->property_start; @@ -343,8 +343,9 @@ static bool source_get_targets(struct wlr_xwm_selection *selection, return false; } - xcb_atom_t *value = xcb_get_property_value(reply); - for (uint32_t i = 0; i < reply->value_len; i++) { + const xcb_atom_t *value = xcb_get_property_value(reply); + uint32_t value_len = xcb_get_property_value_length(reply) / sizeof(value); + for (uint32_t i = 0; i < value_len; i++) { char *mime_type = NULL; if (value[i] == xwm->atoms[UTF8_STRING]) { diff --git a/xwayland/selection/outgoing.c b/xwayland/selection/outgoing.c index 6216abbb4..a58c92e3e 100644 --- a/xwayland/selection/outgoing.c +++ b/xwayland/selection/outgoing.c @@ -336,7 +336,11 @@ static void xwm_selection_send_targets(struct wlr_xwm_selection *selection, } size_t n = 2 + mime_types->size / sizeof(char *); - xcb_atom_t targets[n]; + xcb_atom_t *targets = malloc(n * sizeof(targets[0])); + if (targets == NULL) { + wlr_log(WLR_ERROR, "Allocation failure"); + return; + } targets[0] = xwm->atoms[TIMESTAMP]; targets[1] = xwm->atoms[TARGETS]; @@ -356,6 +360,8 @@ static void xwm_selection_send_targets(struct wlr_xwm_selection *selection, 32, // format n, targets); + free(targets); + xwm_selection_send_notify(selection->xwm, req, true); } diff --git a/xwayland/xwm.c b/xwayland/xwm.c index e44a11743..f31163d94 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -630,6 +630,7 @@ static void xwayland_surface_destroy(struct wlr_xwayland_surface *xsurface) { wl_list_remove(&child->parent_link); wl_list_init(&child->parent_link); child->parent = NULL; + wl_signal_emit_mutable(&child->events.set_parent, NULL); } wl_list_remove(&xsurface->unpaired_link); @@ -659,7 +660,7 @@ static void read_surface_class(struct wlr_xwm *xwm, } size_t len = xcb_get_property_value_length(reply); - char *class = xcb_get_property_value(reply); + const char *class = xcb_get_property_value(reply); // Unpack two sequentially stored strings: instance, class size_t instance_len = strnlen(class, len); @@ -667,6 +668,7 @@ static void read_surface_class(struct wlr_xwm *xwm, if (len > 0 && instance_len < len) { surface->instance = strndup(class, instance_len); class += instance_len + 1; + len -= instance_len + 1; } else { surface->instance = NULL; } @@ -690,7 +692,7 @@ static void read_surface_startup_id(struct wlr_xwm *xwm, } size_t len = xcb_get_property_value_length(reply); - char *startup_id = xcb_get_property_value(reply); + const char *startup_id = xcb_get_property_value(reply); free(xsurface->startup_id); if (len > 0) { @@ -719,7 +721,7 @@ static void read_surface_opacity(struct wlr_xwm *xwm, return; } - uint32_t *val = xcb_get_property_value(reply); + const uint32_t *val = xcb_get_property_value(reply); xsurface->opacity = (double)*val / UINT32_MAX; wl_signal_emit_mutable(&xsurface->events.set_opacity, NULL); } @@ -734,7 +736,7 @@ static void read_surface_role(struct wlr_xwm *xwm, } size_t len = xcb_get_property_value_length(reply); - char *role = xcb_get_property_value(reply); + const char *role = xcb_get_property_value(reply); free(xsurface->role); if (len > 0) { @@ -806,8 +808,12 @@ static void read_surface_parent(struct wlr_xwm *xwm, } struct wlr_xwayland_surface *found_parent = NULL; - xcb_window_t *xid = xcb_get_property_value(reply); - if (reply->type != XCB_ATOM_NONE && xid != NULL) { + if (reply->type != XCB_ATOM_NONE) { + if (xcb_get_property_value_length(reply) != sizeof(xcb_window_t)) { + wlr_log(WLR_DEBUG, "Invalid WM_TRANSIENT_FOR property length"); + return; + } + const xcb_window_t *xid = xcb_get_property_value(reply); found_parent = lookup_surface(xwm, *xid); if (!has_parent(found_parent, xsurface)) { xsurface->parent = found_parent; @@ -837,9 +843,9 @@ static void read_surface_window_type(struct wlr_xwm *xwm, return; } - xcb_atom_t *atoms = xcb_get_property_value(reply); - size_t atoms_len = reply->value_len; - size_t atoms_size = sizeof(xcb_atom_t) * atoms_len; + const xcb_atom_t *atoms = xcb_get_property_value(reply); + size_t atoms_len = xcb_get_property_value_length(reply) / sizeof(atoms[0]); + size_t atoms_size = sizeof(atoms[0]) * atoms_len; free(xsurface->window_type); if (atoms_len > 0) { @@ -864,9 +870,9 @@ static void read_surface_protocols(struct wlr_xwm *xwm, return; } - xcb_atom_t *atoms = xcb_get_property_value(reply); - size_t atoms_len = reply->value_len; - size_t atoms_size = sizeof(xcb_atom_t) * atoms_len; + const xcb_atom_t *atoms = xcb_get_property_value(reply); + size_t atoms_len = xcb_get_property_value_length(reply) / sizeof(atoms[0]); + size_t atoms_size = sizeof(atoms[0]) * atoms_len; free(xsurface->protocols); if (atoms_len > 0) { @@ -893,7 +899,7 @@ static void read_surface_hints(struct wlr_xwm *xwm, } free(xsurface->hints); - if (reply->value_len > 0) { + if (xcb_get_property_value_length(reply) > 0) { xsurface->hints = calloc(1, sizeof(*xsurface->hints)); if (xsurface->hints == NULL) { return; @@ -923,7 +929,7 @@ static void read_surface_normal_hints(struct wlr_xwm *xwm, free(xsurface->size_hints); xsurface->size_hints = NULL; - if (reply->value_len == 0) { + if (xcb_get_property_value_length(reply) == 0) { return; } @@ -970,18 +976,19 @@ static void read_surface_normal_hints(struct wlr_xwm *xwm, static void read_surface_motif_hints(struct wlr_xwm *xwm, struct wlr_xwayland_surface *xsurface, xcb_get_property_reply_t *reply) { - if (reply->value_len == 0) { + if (xcb_get_property_value_length(reply) == 0) { xsurface->decorations = 0; wl_signal_emit_mutable(&xsurface->events.set_decorations, NULL); return; } - if (reply->value_len < 5) { + const uint32_t *motif_hints = xcb_get_property_value(reply); + int motif_hints_len = xcb_get_property_value_length(reply) / sizeof(motif_hints[0]); + if (motif_hints_len < 5) { wlr_log(WLR_DEBUG, "Invalid MOTIF_WM_HINTS property type"); return; } - uint32_t *motif_hints = xcb_get_property_value(reply); if (motif_hints[MWM_HINTS_FLAGS_FIELD] & MWM_HINTS_DECORATIONS) { xsurface->decorations = WLR_XWAYLAND_SURFACE_DECORATIONS_ALL; uint32_t decorations = motif_hints[MWM_HINTS_DECORATIONS_FIELD]; @@ -1029,31 +1036,32 @@ static void read_surface_net_wm_state(struct wlr_xwm *xwm, struct wlr_xwayland_surface *xsurface, xcb_get_property_reply_t *reply) { xsurface->fullscreen = 0; - xcb_atom_t *atom = xcb_get_property_value(reply); - for (uint32_t i = 0; i < reply->value_len; i++) { - if (atom[i] == xwm->atoms[NET_WM_STATE_MODAL]) { + const xcb_atom_t *atoms = xcb_get_property_value(reply); + uint32_t atoms_len = xcb_get_property_value_length(reply) / sizeof(atoms[0]); + for (uint32_t i = 0; i < atoms_len; i++) { + if (atoms[i] == xwm->atoms[NET_WM_STATE_MODAL]) { xsurface->modal = true; - } else if (atom[i] == xwm->atoms[NET_WM_STATE_FULLSCREEN]) { + } else if (atoms[i] == xwm->atoms[NET_WM_STATE_FULLSCREEN]) { xsurface->fullscreen = true; - } else if (atom[i] == xwm->atoms[NET_WM_STATE_MAXIMIZED_VERT]) { + } else if (atoms[i] == xwm->atoms[NET_WM_STATE_MAXIMIZED_VERT]) { xsurface->maximized_vert = true; - } else if (atom[i] == xwm->atoms[NET_WM_STATE_MAXIMIZED_HORZ]) { + } else if (atoms[i] == xwm->atoms[NET_WM_STATE_MAXIMIZED_HORZ]) { xsurface->maximized_horz = true; - } else if (atom[i] == xwm->atoms[NET_WM_STATE_HIDDEN]) { + } else if (atoms[i] == xwm->atoms[NET_WM_STATE_HIDDEN]) { xsurface->minimized = true; - } else if (atom[i] == xwm->atoms[NET_WM_STATE_STICKY]) { + } else if (atoms[i] == xwm->atoms[NET_WM_STATE_STICKY]) { xsurface->sticky = true; - } else if (atom[i] == xwm->atoms[NET_WM_STATE_SHADED]) { + } else if (atoms[i] == xwm->atoms[NET_WM_STATE_SHADED]) { xsurface->shaded = true; - } else if (atom[i] == xwm->atoms[NET_WM_STATE_SKIP_TASKBAR]) { + } else if (atoms[i] == xwm->atoms[NET_WM_STATE_SKIP_TASKBAR]) { xsurface->skip_taskbar = true; - } else if (atom[i] == xwm->atoms[NET_WM_STATE_SKIP_PAGER]) { + } else if (atoms[i] == xwm->atoms[NET_WM_STATE_SKIP_PAGER]) { xsurface->skip_pager = true; - } else if (atom[i] == xwm->atoms[NET_WM_STATE_ABOVE]) { + } else if (atoms[i] == xwm->atoms[NET_WM_STATE_ABOVE]) { xsurface->above = true; - } else if (atom[i] == xwm->atoms[NET_WM_STATE_BELOW]) { + } else if (atoms[i] == xwm->atoms[NET_WM_STATE_BELOW]) { xsurface->below = true; - } else if (atom[i] == xwm->atoms[NET_WM_STATE_DEMANDS_ATTENTION]) { + } else if (atoms[i] == xwm->atoms[NET_WM_STATE_DEMANDS_ATTENTION]) { xsurface->demands_attention = true; } } @@ -1459,15 +1467,31 @@ static void xwm_handle_surface_id_message(struct wlr_xwm *xwm, struct wlr_xwayland_surface *xsurface = lookup_surface(xwm, ev->window); if (xsurface == NULL) { wlr_log(WLR_DEBUG, - "client message WL_SURFACE_ID but no new window %u ?", + "Received client message WL_SURFACE_ID but no X11 window %u", ev->window); return; } - /* Check if we got notified after wayland surface create event */ + if (xsurface->surface != NULL) { + wlr_log(WLR_DEBUG, "Received multiple client messages WL_SURFACE_ID " + "for an already-associated X11 window %u", ev->window); + return; + } + uint32_t id = ev->data.data32[0]; + + // Because the X11 and Wayland connections are separate sockets, the + // WL_SURFACE_ID and wl_compositor.create_surface messages may be received + // in any order. struct wl_resource *resource = wl_client_get_object(xwm->xwayland->server->client, id); if (resource) { + if (wl_resource_get_interface(resource) != &wl_surface_interface) { + wlr_log(WLR_DEBUG, "Received client message WL_SURFACE_ID " + "for X11 window %u but Wayland object is not a wl_surface", + ev->window); + return; + } + struct wlr_surface *surface = wlr_surface_from_resource(resource); xwayland_surface_associate(xwm, xsurface, surface); } else {