diff --git a/.builds/archlinux.yml b/.builds/archlinux.yml index 8457ed585..fae04ab31 100644 --- a/.builds/archlinux.yml +++ b/.builds/archlinux.yml @@ -41,9 +41,10 @@ tasks: cd wlroots/build-gcc/tinywl sudo modprobe vkms udevadm settle + card="/dev/dri/$(ls /sys/devices/faux/vkms/drm/ | grep ^card)" export WLR_BACKENDS=drm export WLR_RENDERER=pixman - export WLR_DRM_DEVICES=/dev/dri/by-path/platform-vkms-card + export WLR_DRM_DEVICES="$card" export UBSAN_OPTIONS=halt_on_error=1 - sudo chmod ugo+rw /dev/dri/by-path/platform-vkms-card + sudo chmod ugo+rw "$card" sudo -E seatd-launch -- ./tinywl -s 'kill $PPID' || [ $? = 143 ] diff --git a/backend/backend.c b/backend/backend.c index a130d9045..3d84aa636 100644 --- a/backend/backend.c +++ b/backend/backend.c @@ -485,5 +485,10 @@ bool wlr_backend_commit(struct wlr_backend *backend, output_apply_commit(state->output, &state->base); } + for (size_t i = 0; i < states_len; i++) { + const struct wlr_backend_output_state *state = &states[i]; + output_send_commit_event(state->output, &state->base); + } + return true; } diff --git a/backend/libinput/tablet_pad.c b/backend/libinput/tablet_pad.c index 98b3e4f4b..2fbfb6a6c 100644 --- a/backend/libinput/tablet_pad.c +++ b/backend/libinput/tablet_pad.c @@ -104,6 +104,7 @@ void init_device_tablet_pad(struct wlr_libinput_input_device *dev) { struct udev_device *udev = libinput_device_get_udev_device(handle); char **dst = wl_array_add(&wlr_tablet_pad->paths, sizeof(char *)); *dst = strdup(udev_device_get_syspath(udev)); + udev_device_unref(udev); int groups = libinput_device_tablet_pad_get_num_mode_groups(handle); for (int i = 0; i < groups; ++i) { diff --git a/backend/libinput/tablet_tool.c b/backend/libinput/tablet_tool.c index eec697c49..d43c6cd0a 100644 --- a/backend/libinput/tablet_tool.c +++ b/backend/libinput/tablet_tool.c @@ -37,6 +37,7 @@ void init_device_tablet(struct wlr_libinput_input_device *dev) { struct udev_device *udev = libinput_device_get_udev_device(dev->handle); char **dst = wl_array_add(&wlr_tablet->paths, sizeof(char *)); *dst = strdup(udev_device_get_syspath(udev)); + udev_device_unref(udev); wl_list_init(&dev->tablet_tools); } diff --git a/backend/session/session.c b/backend/session/session.c index dcf07c708..48f4ab187 100644 --- a/backend/session/session.c +++ b/backend/session/session.c @@ -367,7 +367,10 @@ void wlr_session_close_file(struct wlr_session *session, } assert(wl_list_empty(&dev->events.change.listener_list)); - assert(wl_list_empty(&dev->events.remove.listener_list)); + // TODO: assert that the "remove" listener list is empty as well. Listeners + // will typically call wlr_session_close_file() in response, and + // wl_signal_emit_mutable() installs two phantom listeners, so we'd count + // these two. close(dev->fd); wl_list_remove(&dev->link); diff --git a/include/types/wlr_output.h b/include/types/wlr_output.h index 2dc979c66..b0acac4e8 100644 --- a/include/types/wlr_output.h +++ b/include/types/wlr_output.h @@ -25,6 +25,7 @@ void output_defer_present(struct wlr_output *output, struct wlr_output_event_pre bool output_prepare_commit(struct wlr_output *output, const struct wlr_output_state *state); void output_apply_commit(struct wlr_output *output, const struct wlr_output_state *state); +void output_send_commit_event(struct wlr_output *output, const struct wlr_output_state *state); void output_state_get_buffer_src_box(const struct wlr_output_state *state, struct wlr_fbox *out); diff --git a/include/wlr/types/wlr_drm_lease_v1.h b/include/wlr/types/wlr_drm_lease_v1.h index 752f6efa7..b29a5f6dc 100644 --- a/include/wlr/types/wlr_drm_lease_v1.h +++ b/include/wlr/types/wlr_drm_lease_v1.h @@ -62,8 +62,6 @@ struct wlr_drm_lease_connector_v1 { struct wlr_output *output; struct wlr_drm_lease_device_v1 *device; - /** NULL if no client is currently leasing this connector */ - struct wlr_drm_lease_v1 *active_lease; struct wl_list link; // wlr_drm_lease_device_v1.connectors @@ -93,9 +91,6 @@ struct wlr_drm_lease_v1 { struct wlr_drm_lease_device_v1 *device; - struct wlr_drm_lease_connector_v1 **connectors; - size_t n_connectors; - struct wl_list link; // wlr_drm_lease_device_v1.leases void *data; diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h index 799cebc47..6dafd6529 100644 --- a/include/xwayland/xwm.h +++ b/include/xwayland/xwm.h @@ -162,6 +162,7 @@ struct wlr_xwm { struct wl_listener drop_focus_destroy; }; +// xwm_create takes ownership of wm_fd and will close it under all circumstances. struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland, int wm_fd); void xwm_destroy(struct wlr_xwm *xwm); diff --git a/meson.build b/meson.build index 016e59842..75682e6e4 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project( 'wlroots', 'c', - version: '0.19.0', + version: '0.19.2', license: 'MIT', meson_version: '>=1.3', default_options: [ diff --git a/render/egl.c b/render/egl.c index 07d3a1425..6f3e9c8ca 100644 --- a/render/egl.c +++ b/render/egl.c @@ -260,7 +260,8 @@ static struct wlr_egl *egl_create(void) { return egl; } -static bool egl_init_display(struct wlr_egl *egl, EGLDisplay display) { +static bool egl_init_display(struct wlr_egl *egl, EGLDisplay display, + bool allow_software) { egl->display = display; EGLint major, minor; @@ -326,9 +327,8 @@ static bool egl_init_display(struct wlr_egl *egl, EGLDisplay display) { // The only way a non-DRM device is selected is when the user // explicitly picks software rendering - if (check_egl_ext(device_exts_str, "EGL_MESA_device_software") && - egl->exts.EXT_device_drm) { - if (env_parse_bool("WLR_RENDERER_ALLOW_SOFTWARE")) { + if (check_egl_ext(device_exts_str, "EGL_MESA_device_software")) { + if (allow_software || env_parse_bool("WLR_RENDERER_ALLOW_SOFTWARE")) { wlr_log(WLR_INFO, "Using software rendering"); } else { wlr_log(WLR_ERROR, "Software rendering detected, please use " @@ -382,7 +382,7 @@ static bool egl_init_display(struct wlr_egl *egl, EGLDisplay display) { } static bool egl_init(struct wlr_egl *egl, EGLenum platform, - void *remote_display) { + void *remote_display, bool allow_software) { EGLint display_attribs[3] = {0}; size_t display_attribs_len = 0; @@ -401,7 +401,7 @@ static bool egl_init(struct wlr_egl *egl, EGLenum platform, return false; } - if (!egl_init_display(egl, display)) { + if (!egl_init_display(egl, display, allow_software)) { if (egl->exts.KHR_display_reference) { eglTerminate(display); } @@ -556,6 +556,8 @@ static int open_render_node(int drm_fd) { } struct wlr_egl *wlr_egl_create_with_drm_fd(int drm_fd) { + bool allow_software = drm_fd < 0; + struct wlr_egl *egl = egl_create(); if (egl == NULL) { wlr_log(WLR_ERROR, "Failed to create EGL context"); @@ -569,7 +571,7 @@ struct wlr_egl *wlr_egl_create_with_drm_fd(int drm_fd) { */ EGLDeviceEXT egl_device = get_egl_device_from_drm_fd(egl, drm_fd); if (egl_device != EGL_NO_DEVICE_EXT) { - if (egl_init(egl, EGL_PLATFORM_DEVICE_EXT, egl_device)) { + if (egl_init(egl, EGL_PLATFORM_DEVICE_EXT, egl_device, allow_software)) { wlr_log(WLR_DEBUG, "Using EGL_PLATFORM_DEVICE_EXT"); return egl; } @@ -594,7 +596,7 @@ struct wlr_egl *wlr_egl_create_with_drm_fd(int drm_fd) { goto error; } - if (egl_init(egl, EGL_PLATFORM_GBM_KHR, egl->gbm_device)) { + if (egl_init(egl, EGL_PLATFORM_GBM_KHR, egl->gbm_device, allow_software)) { wlr_log(WLR_DEBUG, "Using EGL_PLATFORM_GBM_KHR"); return egl; } @@ -633,7 +635,7 @@ struct wlr_egl *wlr_egl_create_with_context(EGLDisplay display, return NULL; } - if (!egl_init_display(egl, display)) { + if (!egl_init_display(egl, display, true)) { free(egl); return NULL; } diff --git a/render/pass.c b/render/pass.c index 902228273..23bdf96dd 100644 --- a/render/pass.c +++ b/render/pass.c @@ -21,8 +21,8 @@ void wlr_render_pass_add_texture(struct wlr_render_pass *render_pass, if (!wlr_fbox_empty(&options->src_box)) { const struct wlr_fbox *box = &options->src_box; assert(box->x >= 0 && box->y >= 0 && - box->x + box->width <= options->texture->width && - box->y + box->height <= options->texture->height); + (uint32_t)(box->x + box->width) <= options->texture->width && + (uint32_t)(box->y + box->height) <= options->texture->height); } render_pass->impl->add_texture(render_pass, options); diff --git a/render/vulkan/renderer.c b/render/vulkan/renderer.c index b2feca013..1a696734a 100644 --- a/render/vulkan/renderer.c +++ b/render/vulkan/renderer.c @@ -66,59 +66,72 @@ static struct wlr_vk_descriptor_pool *alloc_ds( struct wl_list *pool_list, size_t *last_pool_size) { VkResult res; - bool found = false; - struct wlr_vk_descriptor_pool *pool; - wl_list_for_each(pool, pool_list, link) { - if (pool->free > 0) { - found = true; - break; - } - } - - if (!found) { // create new pool - pool = calloc(1, sizeof(*pool)); - if (!pool) { - wlr_log_errno(WLR_ERROR, "allocation failed"); - return NULL; - } - - size_t count = 2 * (*last_pool_size); - if (!count) { - count = start_descriptor_pool_size; - } - - pool->free = count; - VkDescriptorPoolSize pool_size = { - .descriptorCount = count, - .type = type, - }; - - VkDescriptorPoolCreateInfo dpool_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - .maxSets = count, - .poolSizeCount = 1, - .pPoolSizes = &pool_size, - .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, - }; - - res = vkCreateDescriptorPool(renderer->dev->dev, &dpool_info, NULL, - &pool->pool); - if (res != VK_SUCCESS) { - wlr_vk_error("vkCreateDescriptorPool", res); - free(pool); - return NULL; - } - - *last_pool_size = count; - wl_list_insert(pool_list, &pool->link); - } - VkDescriptorSetAllocateInfo ds_info = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, .descriptorSetCount = 1, .pSetLayouts = layout, - .descriptorPool = pool->pool, }; + + struct wlr_vk_descriptor_pool *pool; + wl_list_for_each(pool, pool_list, link) { + if (pool->free > 0) { + ds_info.descriptorPool = pool->pool; + res = vkAllocateDescriptorSets(renderer->dev->dev, &ds_info, ds); + switch (res) { + case VK_ERROR_FRAGMENTED_POOL: + case VK_ERROR_OUT_OF_POOL_MEMORY: + // Descriptor sets with more than one descriptor can cause us + // to run out of pool memory early or lead to fragmentation + // that makes the pool unable to service our allocation + // request. Try the next pool or allocate a new one. + continue; + case VK_SUCCESS: + --pool->free; + return pool; + default: + wlr_vk_error("vkAllocateDescriptorSets", res); + return NULL; + } + } + } + + pool = calloc(1, sizeof(*pool)); + if (!pool) { + wlr_log_errno(WLR_ERROR, "allocation failed"); + return NULL; + } + + size_t count = 2 * (*last_pool_size); + if (!count) { + count = start_descriptor_pool_size; + } + + pool->free = count; + VkDescriptorPoolSize pool_size = { + .descriptorCount = count, + .type = type, + }; + + VkDescriptorPoolCreateInfo dpool_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .maxSets = count, + .poolSizeCount = 1, + .pPoolSizes = &pool_size, + .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, + }; + + res = vkCreateDescriptorPool(renderer->dev->dev, &dpool_info, NULL, + &pool->pool); + if (res != VK_SUCCESS) { + wlr_vk_error("vkCreateDescriptorPool", res); + free(pool); + return NULL; + } + + *last_pool_size = count; + wl_list_insert(pool_list, &pool->link); + + ds_info.descriptorPool = pool->pool; res = vkAllocateDescriptorSets(renderer->dev->dev, &ds_info, ds); if (res != VK_SUCCESS) { wlr_vk_error("vkAllocateDescriptorSets", res); diff --git a/types/ext_image_capture_source_v1/output.c b/types/ext_image_capture_source_v1/output.c index e5ef78f93..e661aad3a 100644 --- a/types/ext_image_capture_source_v1/output.c +++ b/types/ext_image_capture_source_v1/output.c @@ -283,7 +283,8 @@ static void output_cursor_source_copy_frame(struct wlr_ext_image_capture_source_ struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - wlr_ext_image_copy_capture_frame_v1_ready(frame, WL_OUTPUT_TRANSFORM_NORMAL, &now); + wlr_ext_image_copy_capture_frame_v1_ready(frame, + cursor_source->output->transform, &now); } static const struct wlr_ext_image_capture_source_v1_interface output_cursor_source_impl = { diff --git a/types/output/cursor.c b/types/output/cursor.c index 154b91120..70647afb7 100644 --- a/types/output/cursor.c +++ b/types/output/cursor.c @@ -288,18 +288,10 @@ static struct wlr_buffer *render_cursor_buffer(struct wlr_output_cursor *cursor) static bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) { struct wlr_output *output = cursor->output; - if (!output->impl->set_cursor || - output->software_cursor_locks > 0) { + if (!output->impl->set_cursor || output->software_cursor_locks > 0) { return false; } - struct wlr_output_cursor *hwcur = output->hardware_cursor; - if (hwcur != NULL && hwcur != cursor) { - return false; - } - - output->hardware_cursor = NULL; - struct wlr_texture *texture = cursor->texture; // If the cursor was hidden or was a software cursor, the hardware @@ -424,12 +416,15 @@ bool output_cursor_set_texture(struct wlr_output_cursor *cursor, wl_list_init(&cursor->renderer_destroy.link); } - if (output_cursor_attempt_hardware(cursor)) { - return true; + if (output->hardware_cursor == NULL || output->hardware_cursor == cursor) { + if (output_cursor_attempt_hardware(cursor)) { + return true; + } + + wlr_log(WLR_DEBUG, "Falling back to software cursor on output '%s'", output->name); + output_disable_hardware_cursor(output); } - wlr_log(WLR_DEBUG, "Falling back to software cursor on output '%s'", output->name); - output_disable_hardware_cursor(output); output_cursor_damage_whole(cursor); return true; } diff --git a/types/output/output.c b/types/output/output.c index a352a5e59..aa2384575 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -745,7 +745,9 @@ void output_apply_commit(struct wlr_output *output, const struct wlr_output_stat } output_apply_state(output, state); +} +void output_send_commit_event(struct wlr_output *output, const struct wlr_output_state *state) { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); struct wlr_output_event_commit event = { @@ -787,6 +789,7 @@ bool wlr_output_commit_state(struct wlr_output *output, } output_apply_commit(output, &pending); + output_send_commit_event(output, &pending); if (new_back_buffer) { wlr_buffer_unlock(pending.buffer); diff --git a/types/scene/surface.c b/types/scene/surface.c index e5b3b0f7d..f0651bc38 100644 --- a/types/scene/surface.c +++ b/types/scene/surface.c @@ -96,8 +96,11 @@ static void scene_buffer_unmark_client_buffer(struct wlr_scene_buffer *scene_buf return; } - assert(buffer->n_ignore_locks > 0); - buffer->n_ignore_locks--; + // If the buffer was a single-pixel buffer where we cached its color + // then it won't have been marked as damage-allowed. + if (buffer->n_ignore_locks > 0) { + buffer->n_ignore_locks--; + } } static int min(int a, int b) { @@ -165,7 +168,21 @@ static void surface_reconfigure(struct wlr_scene_surface *scene_surface) { scene_buffer_unmark_client_buffer(scene_buffer); if (surface->buffer) { - client_buffer_mark_next_can_damage(surface->buffer); + // If we've cached the buffer's single-pixel buffer color + // then any in-place updates to the texture wouldn't be + // reflected in rendering. So only allow in-place texture + // updates if it's not a single pixel buffer. Note that we + // can't use the cached scene_buffer->is_single_pixel_buffer + // because that's only set later on. + bool is_single_pixel_buffer = false; + if (surface->buffer->source != NULL) { + struct wlr_single_pixel_buffer_v1 *spb = + wlr_single_pixel_buffer_v1_try_from_buffer(surface->buffer->source); + is_single_pixel_buffer = spb != NULL; + } + if (!is_single_pixel_buffer) { + client_buffer_mark_next_can_damage(surface->buffer); + } struct wlr_linux_drm_syncobj_surface_v1_state *syncobj_surface_state = wlr_linux_drm_syncobj_v1_get_surface_state(surface); @@ -186,7 +203,8 @@ static void surface_reconfigure(struct wlr_scene_surface *scene_surface) { &surface->buffer->base, &options); if (syncobj_surface_state != NULL && - (surface->current.committed & WLR_SURFACE_STATE_BUFFER)) { + (surface->current.committed & WLR_SURFACE_STATE_BUFFER) && + surface->buffer->source != NULL) { wlr_linux_drm_syncobj_v1_state_signal_release_with_buffer(syncobj_surface_state, surface->buffer->source); } diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index 44b74e926..407d30620 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -530,10 +530,6 @@ static void cursor_output_cursor_update(struct wlr_cursor_output_cursor *output_ struct wlr_cursor *cur = output_cursor->cursor; struct wlr_output *output = output_cursor->output_cursor->output; - if (!output->enabled) { - return; - } - cursor_output_cursor_reset_image(output_cursor); if (cur->state->buffer != NULL) { @@ -589,10 +585,11 @@ static void cursor_output_cursor_update(struct wlr_cursor_output_cursor *output_ &src_box, dst_width, dst_height, surface->current.transform, hotspot_x, hotspot_y, wait_timeline, wait_point); - if (syncobj_surface_state != NULL && surface->buffer != NULL && + if (syncobj_surface_state != NULL && + surface->buffer != NULL && surface->buffer->source != NULL && (surface->current.committed & WLR_SURFACE_STATE_BUFFER)) { wlr_linux_drm_syncobj_v1_state_signal_release_with_buffer(syncobj_surface_state, - &surface->buffer->base); + surface->buffer->source); } if (output_cursor->output_cursor->visible) { diff --git a/types/wlr_drm_lease_v1.c b/types/wlr_drm_lease_v1.c index c64bb0896..14846f21d 100644 --- a/types/wlr_drm_lease_v1.c +++ b/types/wlr_drm_lease_v1.c @@ -68,10 +68,6 @@ static void drm_lease_connector_v1_destroy( wlr_log(WLR_DEBUG, "Destroying connector %s", connector->output->name); - if (connector->active_lease) { - wlr_drm_lease_terminate(connector->active_lease->drm_lease); - } - struct wl_resource *resource, *tmp; wl_resource_for_each_safe(resource, tmp, &connector->resources) { wp_drm_lease_connector_v1_send_withdrawn(resource); @@ -140,14 +136,9 @@ static void lease_handle_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&lease->destroy.link); - for (size_t i = 0; i < lease->n_connectors; ++i) { - lease->connectors[i]->active_lease = NULL; - } - wl_list_remove(&lease->link); wl_resource_set_user_data(lease->resource, NULL); - free(lease->connectors); free(lease); } @@ -180,20 +171,6 @@ struct wlr_drm_lease_v1 *wlr_drm_lease_request_v1_grant( return NULL; } - lease->connectors = calloc(request->n_connectors, sizeof(*lease->connectors)); - if (!lease->connectors) { - wlr_log(WLR_ERROR, "Failed to allocate lease connectors list"); - close(fd); - wp_drm_lease_v1_send_finished(lease->resource); - free(lease); - return NULL; - } - lease->n_connectors = request->n_connectors; - for (size_t i = 0; i < request->n_connectors; ++i) { - lease->connectors[i] = request->connectors[i]; - lease->connectors[i]->active_lease = lease; - } - lease->destroy.notify = lease_handle_destroy; wl_signal_add(&lease->drm_lease->events.destroy, &lease->destroy); @@ -338,16 +315,6 @@ static void drm_lease_request_v1_handle_submit( return; } - for (size_t i = 0; i < request->n_connectors; ++i) { - struct wlr_drm_lease_connector_v1 *conn = request->connectors[i]; - if (conn->active_lease) { - wlr_log(WLR_ERROR, "Failed to create lease, connector %s has " - "already been leased", conn->output->name); - wp_drm_lease_v1_send_finished(lease_resource); - return; - } - } - request->lease_resource = lease_resource; wl_signal_emit_mutable(&request->device->manager->events.request, @@ -440,10 +407,6 @@ static struct wp_drm_lease_connector_v1_interface lease_connector_impl = { static void drm_lease_connector_v1_send_to_client( struct wlr_drm_lease_connector_v1 *connector, struct wl_resource *resource) { - if (connector->active_lease) { - return; - } - struct wl_client *client = wl_resource_get_client(resource); uint32_t version = wl_resource_get_version(resource); @@ -490,10 +453,12 @@ static void lease_device_bind(struct wl_client *wl_client, void *data, if (!device) { wlr_log(WLR_DEBUG, "Failed to bind lease device, " "the wlr_drm_lease_device_v1 has been destroyed"); + wl_list_init(wl_resource_get_link(device_resource)); return; } wl_resource_set_user_data(device_resource, device); + wl_list_insert(&device->resources, wl_resource_get_link(device_resource)); int fd = wlr_drm_backend_get_non_master_fd(device->backend); if (fd < 0) { @@ -505,8 +470,6 @@ static void lease_device_bind(struct wl_client *wl_client, void *data, wp_drm_lease_device_v1_send_drm_fd(device_resource, fd); close(fd); - wl_list_insert(&device->resources, wl_resource_get_link(device_resource)); - struct wlr_drm_lease_connector_v1 *connector; wl_list_for_each(connector, &device->connectors, link) { drm_lease_connector_v1_send_to_client(connector, device_resource); diff --git a/types/wlr_linux_drm_syncobj_v1.c b/types/wlr_linux_drm_syncobj_v1.c index 7873a09c4..988d44e01 100644 --- a/types/wlr_linux_drm_syncobj_v1.c +++ b/types/wlr_linux_drm_syncobj_v1.c @@ -26,7 +26,7 @@ struct wlr_linux_drm_syncobj_surface_v1 { }; struct wlr_linux_drm_syncobj_surface_v1_commit { - struct wlr_linux_drm_syncobj_surface_v1 *surface; + struct wlr_surface *surface; struct wlr_drm_syncobj_timeline_waiter waiter; uint32_t cached_seq; @@ -192,7 +192,7 @@ static struct wlr_linux_drm_syncobj_surface_v1 *surface_from_wlr_surface( } static void surface_commit_destroy(struct wlr_linux_drm_syncobj_surface_v1_commit *commit) { - wlr_surface_unlock_cached(commit->surface->surface, commit->cached_seq); + wlr_surface_unlock_cached(commit->surface, commit->cached_seq); wl_list_remove(&commit->surface_destroy.link); wlr_drm_syncobj_timeline_waiter_finish(&commit->waiter); free(commit); @@ -237,7 +237,7 @@ static bool lock_surface_commit(struct wlr_linux_drm_syncobj_surface_v1 *surface return false; } - commit->surface = surface; + commit->surface = surface->surface; commit->cached_seq = wlr_surface_lock_pending(surface->surface); commit->surface_destroy.notify = surface_commit_handle_surface_destroy; diff --git a/types/wlr_transient_seat_v1.c b/types/wlr_transient_seat_v1.c index af8f87ccf..d99ee6edb 100644 --- a/types/wlr_transient_seat_v1.c +++ b/types/wlr_transient_seat_v1.c @@ -64,6 +64,7 @@ static void manager_create_transient_seat(struct wl_client *client, wl_resource_set_implementation(seat->resource, &transient_seat_impl, seat, transient_seat_handle_resource_destroy); + wl_list_init(&seat->seat_destroy.link); wl_signal_emit_mutable(&manager->events.create_seat, seat); return; diff --git a/util/box.c b/util/box.c index 6a6becf33..aae09888f 100644 --- a/util/box.c +++ b/util/box.c @@ -19,16 +19,15 @@ void wlr_box_closest_point(const struct wlr_box *box, double x, double y, // // In order to be consistent with e.g. wlr_box_contains_point(), // this function returns a point inside the bottom and right edges - // of the box by at least 1/65536 of a unit (pixel). 1/65536 is + // of the box by at least 1/256 of a unit (pixel). 1/256 is // small enough to avoid a "dead zone" with high-resolution mice - // but large enough to avoid rounding to zero (due to loss of - // significant digits) in simple floating-point calculations. + // but large enough to avoid rounding to zero in wl_fixed_from_double(). // find the closest x point if (x < box->x) { *dest_x = box->x; - } else if (x > box->x + box->width - 1/65536.0) { - *dest_x = box->x + box->width - 1/65536.0; + } else if (x > box->x + box->width - 1/256.0) { + *dest_x = box->x + box->width - 1/256.0; } else { *dest_x = x; } @@ -36,8 +35,8 @@ void wlr_box_closest_point(const struct wlr_box *box, double x, double y, // find closest y point if (y < box->y) { *dest_y = box->y; - } else if (y > box->y + box->height - 1/65536.0) { - *dest_y = box->y + box->height - 1/65536.0; + } else if (y > box->y + box->height - 1/256.0) { + *dest_y = box->y + box->height - 1/256.0; } else { *dest_y = y; } @@ -67,7 +66,12 @@ bool wlr_box_intersection(struct wlr_box *dest, const struct wlr_box *box_a, dest->width = x2 - x1; dest->height = y2 - y1; - return !wlr_box_empty(dest); + if (wlr_box_empty(dest)) { + *dest = (struct wlr_box){0}; + return false; + } + + return true; } bool wlr_box_contains_point(const struct wlr_box *box, double x, double y) { diff --git a/xwayland/xwayland.c b/xwayland/xwayland.c index d3b2a6c84..63af99c51 100644 --- a/xwayland/xwayland.c +++ b/xwayland/xwayland.c @@ -42,6 +42,9 @@ static void handle_server_start(struct wl_listener *listener, void *data) { static void xwayland_mark_ready(struct wlr_xwayland *xwayland) { assert(xwayland->server->wm_fd[0] >= 0); xwayland->xwm = xwm_create(xwayland, xwayland->server->wm_fd[0]); + // xwm_create takes ownership of wm_fd[0] under all circumstances + xwayland->server->wm_fd[0] = -1; + if (!xwayland->xwm) { return; } @@ -69,6 +72,11 @@ static void handle_shell_destroy(struct wl_listener *listener, void *data) { struct wlr_xwayland *xwayland = wl_container_of(listener, xwayland, shell_destroy); xwayland->shell_v1 = NULL; + wl_list_remove(&xwayland->shell_destroy.link); + // Will remove this list in handle_shell_destroy(). + // This ensures the link is always initialized and + // avoids the need to keep check conditions in sync. + wl_list_init(&xwayland->shell_destroy.link); } void wlr_xwayland_destroy(struct wlr_xwayland *xwayland) { diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 8cd1d41ab..3caf335e3 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -2470,6 +2470,7 @@ void xwm_set_cursor(struct wlr_xwm *xwm, const uint8_t *pixels, uint32_t stride, struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) { struct wlr_xwm *xwm = calloc(1, sizeof(*xwm)); if (xwm == NULL) { + close(wm_fd); return NULL; } @@ -2484,11 +2485,13 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) { xwm->ping_timeout = 10000; + // xcb_connect_to_fd takes ownership of the FD regardless of success/failure xwm->xcb_conn = xcb_connect_to_fd(wm_fd, NULL); int rc = xcb_connection_has_error(xwm->xcb_conn); if (rc) { wlr_log(WLR_ERROR, "xcb connect failed: %d", rc); + xcb_disconnect(xwm->xcb_conn); free(xwm); return NULL; }