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/drm/drm.c b/backend/drm/drm.c index ea23f1741..4b918b706 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -796,13 +796,12 @@ static bool drm_connector_prepare(struct wlr_drm_connector_state *conn_state, bo return false; } - if ((state->committed & WLR_OUTPUT_STATE_ENABLED) && state->enabled) { - if (output->current_mode == NULL && - !(state->committed & WLR_OUTPUT_STATE_MODE)) { - wlr_drm_conn_log(conn, WLR_DEBUG, - "Can't enable an output without a mode"); - return false; - } + if ((state->committed & WLR_OUTPUT_STATE_ENABLED) && state->enabled && + output->width == 0 && output->height == 0 && + !(state->committed & WLR_OUTPUT_STATE_MODE)) { + wlr_drm_conn_log(conn, WLR_DEBUG, + "Can't enable an output without a mode"); + return false; } if ((state->committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) && @@ -1582,6 +1581,7 @@ static bool connect_drm_connector(struct wlr_drm_connector *wlr_conn, wlr_log(WLR_INFO, "Detected modes:"); + bool found_current_mode = false; for (int i = 0; i < drm_conn->count_modes; ++i) { if (drm_conn->modes[i].flags & DRM_MODE_FLAG_INTERLACE) { continue; @@ -1600,14 +1600,7 @@ static bool connect_drm_connector(struct wlr_drm_connector *wlr_conn, if (current_modeinfo != NULL && memcmp(&mode->drm_mode, current_modeinfo, sizeof(*current_modeinfo)) == 0) { wlr_output_state_set_mode(&state, &mode->wlr_mode); - - uint64_t mode_id = 0; - get_drm_prop(drm->fd, wlr_conn->crtc->id, - wlr_conn->crtc->props.mode_id, &mode_id); - - wlr_conn->crtc->own_mode_id = false; - wlr_conn->crtc->mode_id = mode_id; - wlr_conn->refresh = calculate_refresh_rate(current_modeinfo); + found_current_mode = true; } wlr_log(WLR_INFO, " %"PRId32"x%"PRId32" @ %.3f Hz %s", @@ -1618,6 +1611,23 @@ static bool connect_drm_connector(struct wlr_drm_connector *wlr_conn, wl_list_insert(modes.prev, &mode->wlr_mode.link); } + if (current_modeinfo != NULL) { + int32_t refresh = calculate_refresh_rate(current_modeinfo); + + if (!found_current_mode) { + wlr_output_state_set_custom_mode(&state, + current_modeinfo->hdisplay, current_modeinfo->vdisplay, refresh); + } + + uint64_t mode_id = 0; + get_drm_prop(drm->fd, wlr_conn->crtc->id, + wlr_conn->crtc->props.mode_id, &mode_id); + + wlr_conn->crtc->own_mode_id = false; + wlr_conn->crtc->mode_id = mode_id; + wlr_conn->refresh = refresh; + } + free(current_modeinfo); wlr_output_init(output, &drm->backend, &output_impl, drm->session->event_loop, &state); diff --git a/include/wlr/types/wlr_screencopy_v1.h b/include/wlr/types/wlr_screencopy_v1.h index c1e990fa8..fff10d89d 100644 --- a/include/wlr/types/wlr_screencopy_v1.h +++ b/include/wlr/types/wlr_screencopy_v1.h @@ -52,7 +52,6 @@ struct wlr_screencopy_frame_v1 { struct wlr_output *output; struct wl_listener output_commit; struct wl_listener output_destroy; - struct wl_listener output_enable; void *data; }; diff --git a/meson.build b/meson.build index f36411d95..d41a43d4c 100644 --- a/meson.build +++ b/meson.build @@ -1,11 +1,11 @@ project( 'wlroots', 'c', - version: '0.18.2', + version: '0.18.3', license: 'MIT', meson_version: '>=0.59.0', default_options: [ - 'c_std=' + (meson.version().version_compare('>=1.3.0') ? 'c23,c11' : 'c11'), + 'c_std=' + (meson.version().version_compare('>=1.4.0') ? 'c23,c11' : 'c11'), 'warning_level=2', 'werror=true', ], 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/types/scene/surface.c b/types/scene/surface.c index 1905b4dfb..3208c817c 100644 --- a/types/scene/surface.c +++ b/types/scene/surface.c @@ -128,8 +128,8 @@ static void surface_reconfigure(struct wlr_scene_surface *scene_surface) { buffer_width, buffer_height); wlr_output_transform_coords(state->transform, &buffer_width, &buffer_height); - src_box.x += (double)(clip->x * buffer_width) / state->width; - src_box.y += (double)(clip->y * buffer_height) / state->height; + src_box.x += (double)(clip->x * src_box.width) / state->width; + src_box.y += (double)(clip->y * src_box.height) / state->height; src_box.width *= (double)width / state->width; src_box.height *= (double)height / state->height; diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index 77ab2fb70..5a978ac99 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -574,9 +574,15 @@ static void cursor_output_cursor_update(struct wlr_cursor_output_cursor *output_ wlr_xcursor_manager_load(manager, scale); struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor(manager, name, scale); if (xcursor == NULL) { - wlr_log(WLR_DEBUG, "XCursor theme is missing '%s' cursor", name); - wlr_output_cursor_set_buffer(output_cursor->output_cursor, NULL, 0, 0); - return; + /* Try the default cursor: better the wrong image than an invisible + * (and therefore practically unusable) cursor */ + wlr_log(WLR_DEBUG, "XCursor theme is missing '%s' cursor, falling back to 'default'", name); + xcursor = wlr_xcursor_manager_get_xcursor(manager, "default", scale); + if (xcursor == NULL) { + wlr_log(WLR_DEBUG, "XCursor theme is missing a 'default' cursor"); + wlr_output_cursor_set_buffer(output_cursor->output_cursor, NULL, 0, 0); + return; + } } output_cursor->xcursor = xcursor; diff --git a/types/wlr_screencopy_v1.c b/types/wlr_screencopy_v1.c index acd584d5d..53316ec10 100644 --- a/types/wlr_screencopy_v1.c +++ b/types/wlr_screencopy_v1.c @@ -146,7 +146,6 @@ static void frame_destroy(struct wlr_screencopy_frame_v1 *frame) { wl_list_remove(&frame->link); wl_list_remove(&frame->output_commit.link); wl_list_remove(&frame->output_destroy.link); - wl_list_remove(&frame->output_enable.link); // Make the frame resource inert wl_resource_set_user_data(frame->resource, NULL); wlr_buffer_unlock(frame->buffer); @@ -286,6 +285,10 @@ static void frame_handle_output_commit(struct wl_listener *listener, struct wlr_output_event_commit *event = data; struct wlr_output *output = frame->output; + if (event->state->committed & WLR_OUTPUT_STATE_ENABLED && !output->enabled) { + goto err; + } + if (!(event->state->committed & WLR_OUTPUT_STATE_BUFFER)) { return; } @@ -338,16 +341,6 @@ err: frame_destroy(frame); } -static void frame_handle_output_enable(struct wl_listener *listener, - void *data) { - struct wlr_screencopy_frame_v1 *frame = - wl_container_of(listener, frame, output_enable); - if (!frame->output->enabled) { - zwlr_screencopy_frame_v1_send_failed(frame->resource); - frame_destroy(frame); - } -} - static void frame_handle_output_destroy(struct wl_listener *listener, void *data) { struct wlr_screencopy_frame_v1 *frame = @@ -439,9 +432,6 @@ static void frame_handle_copy(struct wl_client *wl_client, wl_signal_add(&output->events.commit, &frame->output_commit); frame->output_commit.notify = frame_handle_output_commit; - wl_signal_add(&output->events.destroy, &frame->output_enable); - frame->output_enable.notify = frame_handle_output_enable; - // Request a frame because we can't assume that the current front buffer is still usable. It may // have been released already, and we shouldn't lock it here because compositors want to render // into the least damaged buffer. @@ -526,7 +516,6 @@ static void capture_output(struct wl_client *wl_client, wl_list_insert(&client->manager->frames, &frame->link); wl_list_init(&frame->output_commit.link); - wl_list_init(&frame->output_enable.link); wl_signal_add(&output->events.destroy, &frame->output_destroy); frame->output_destroy.notify = frame_handle_output_destroy;