diff --git a/.editorconfig b/.editorconfig index 694a7ea..7b0dfeb 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,6 +9,9 @@ indent_style = tab indent_size = 4 max_line_length = 100 +[/.git/**] +max_line_length = unset + [*.xml] indent_style = space indent_size = 2 diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c index 2649a1a..df3a6aa 100644 --- a/backend/drm/atomic.c +++ b/backend/drm/atomic.c @@ -152,18 +152,20 @@ static bool create_gamma_lut_blob(struct wlr_drm_backend *drm, bool create_fb_damage_clips_blob(struct wlr_drm_backend *drm, int width, int height, const pixman_region32_t *damage, uint32_t *blob_id) { - if (!pixman_region32_not_empty(damage)) { - *blob_id = 0; - return true; - } - pixman_region32_t clipped; pixman_region32_init(&clipped); pixman_region32_intersect_rect(&clipped, damage, 0, 0, width, height); int rects_len; const pixman_box32_t *rects = pixman_region32_rectangles(&clipped, &rects_len); - int ret = drmModeCreatePropertyBlob(drm->fd, rects, sizeof(*rects) * rects_len, blob_id); + + int ret; + if (rects_len > 0) { + ret = drmModeCreatePropertyBlob(drm->fd, rects, sizeof(*rects) * rects_len, blob_id); + } else { + ret = 0; + *blob_id = 0; + } pixman_region32_fini(&clipped); if (ret != 0) { wlr_log_errno(WLR_ERROR, "Failed to create FB_DAMAGE_CLIPS property blob"); diff --git a/backend/drm/drm.c b/backend/drm/drm.c index ab3877d..ea23f17 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -577,6 +577,16 @@ static void drm_connector_apply_commit(const struct wlr_drm_connector_state *sta conn->cursor_enabled = false; conn->crtc = NULL; + + // Legacy uAPI doesn't support requesting page-flip events when + // turning off a CRTC + if (page_flip != NULL && conn->backend->iface == &legacy_iface) { + drm_page_flip_pop(page_flip, crtc->id); + conn->pending_page_flip = NULL; + if (page_flip->connectors_len == 0) { + drm_page_flip_destroy(page_flip); + } + } } } @@ -803,6 +813,22 @@ static bool drm_connector_prepare(struct wlr_drm_connector_state *conn_state, bo return false; } + if ((state->committed & WLR_OUTPUT_STATE_BUFFER) && conn->backend->mgpu_renderer.wlr_rend) { + struct wlr_dmabuf_attributes dmabuf; + if (!wlr_buffer_get_dmabuf(state->buffer, &dmabuf)) { + wlr_drm_conn_log(conn, WLR_DEBUG, "Buffer is not a DMA-BUF"); + return false; + } + + if (!wlr_drm_format_set_has(&conn->backend->mgpu_formats, dmabuf.format, dmabuf.modifier)) { + wlr_drm_conn_log(conn, WLR_DEBUG, + "Buffer format 0x%"PRIX32" with modifier 0x%"PRIX64" cannot be " + "imported into multi-GPU renderer", + dmabuf.format, dmabuf.modifier); + return false; + } + } + if (test_only && conn->backend->parent) { // If we're running as a secondary GPU, we can't perform an atomic // commit without blitting a buffer. diff --git a/backend/drm/legacy.c b/backend/drm/legacy.c index 0c591f4..502c092 100644 --- a/backend/drm/legacy.c +++ b/backend/drm/legacy.c @@ -128,7 +128,7 @@ static bool legacy_crtc_commit(const struct wlr_drm_connector_state *state, state->base->adaptive_sync_enabled ? "enabled" : "disabled"); } - if (cursor != NULL && drm_connector_is_cursor_visible(conn)) { + if (cursor != NULL && state->active && drm_connector_is_cursor_visible(conn)) { struct wlr_drm_fb *cursor_fb = state->cursor_fb; if (cursor_fb == NULL) { wlr_drm_conn_log(conn, WLR_DEBUG, "Failed to acquire cursor FB"); @@ -170,7 +170,9 @@ static bool legacy_crtc_commit(const struct wlr_drm_connector_state *state, } } - if (flags & DRM_MODE_PAGE_FLIP_EVENT) { + // Legacy uAPI doesn't support requesting page-flip events when + // turning off a CRTC + if (state->active && (flags & DRM_MODE_PAGE_FLIP_EVENT)) { if (drmModePageFlip(drm->fd, crtc->id, fb_id, flags, page_flip)) { wlr_drm_conn_log_errno(conn, WLR_ERROR, "drmModePageFlip failed"); return false; diff --git a/backend/headless/output.c b/backend/headless/output.c index 5aaf1bd..5a00e2e 100644 --- a/backend/headless/output.c +++ b/backend/headless/output.c @@ -89,6 +89,7 @@ static void output_destroy(struct wlr_output *wlr_output) { static const struct wlr_output_impl output_impl = { .destroy = output_destroy, + .test = output_test, .commit = output_commit, }; diff --git a/backend/wayland/output.c b/backend/wayland/output.c index 39803ea..66e0e89 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -198,7 +198,7 @@ static struct wl_buffer *import_shm(struct wlr_wl_backend *wl, struct wlr_shm_attributes *shm) { enum wl_shm_format wl_shm_format = convert_drm_format_to_wl_shm(shm->format); uint32_t size = shm->stride * shm->height; - struct wl_shm_pool *pool = wl_shm_create_pool(wl->shm, shm->fd, size); + struct wl_shm_pool *pool = wl_shm_create_pool(wl->shm, shm->fd, shm->offset + size); if (pool == NULL) { return NULL; } diff --git a/debian/changelog b/debian/changelog index cbb7804..3973bd5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +wlroots (0.18.2-1deepin1) unstable; urgency=medium + + * update 0.18.2. + + -- lichenggang Tue, 31 Dec 2024 17:25:02 +0800 + wlroots (0.18.1-1deepin3) unstable; urgency=medium * data-device: fix dnd handling during popup interactions diff --git a/include/types/wlr_keyboard.h b/include/types/wlr_keyboard.h index 7cd26e8..bdae09b 100644 --- a/include/types/wlr_keyboard.h +++ b/include/types/wlr_keyboard.h @@ -1,6 +1,6 @@ #include -void keyboard_key_update(struct wlr_keyboard *keyboard, +bool keyboard_key_update(struct wlr_keyboard *keyboard, struct wlr_keyboard_key_event *event); bool keyboard_modifier_update(struct wlr_keyboard *keyboard); diff --git a/include/wlr/types/wlr_data_device.h b/include/wlr/types/wlr_data_device.h index 85d661a..b0fa9fd 100644 --- a/include/wlr/types/wlr_data_device.h +++ b/include/wlr/types/wlr_data_device.h @@ -126,6 +126,7 @@ struct wlr_drag { struct wl_listener source_destroy; struct wl_listener seat_client_destroy; + struct wl_listener focus_destroy; struct wl_listener icon_destroy; void *data; diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h index 6e9eb7f..4386446 100644 --- a/include/xwayland/xwm.h +++ b/include/xwayland/xwm.h @@ -123,6 +123,7 @@ struct wlr_xwm { struct wlr_drag *drag; struct wlr_xwayland_surface *drag_focus; + struct wlr_xwayland_surface *drop_focus; const xcb_query_extension_reply_t *xfixes; const xcb_query_extension_reply_t *xres; @@ -144,6 +145,8 @@ struct wlr_xwm { struct wl_listener seat_drag_drop; struct wl_listener seat_drag_destroy; struct wl_listener seat_drag_source_destroy; + struct wl_listener drag_focus_destroy; + struct wl_listener drop_focus_destroy; }; struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland, int wm_fd); @@ -156,6 +159,7 @@ void xwm_set_cursor(struct wlr_xwm *xwm, const uint8_t *pixels, uint32_t stride, int xwm_handle_selection_event(struct wlr_xwm *xwm, xcb_generic_event_t *event); int xwm_handle_selection_client_message(struct wlr_xwm *xwm, xcb_client_message_event_t *ev); +void xwm_seat_unlink_drag_handlers(struct wlr_xwm *xwm); void xwm_set_seat(struct wlr_xwm *xwm, struct wlr_seat *seat); diff --git a/meson.build b/meson.build index 0291a50..f36411d 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project( 'wlroots', 'c', - version: '0.18.1', + version: '0.18.2', license: 'MIT', meson_version: '>=0.59.0', default_options: [ diff --git a/render/vulkan/renderer.c b/render/vulkan/renderer.c index 327f3b4..8c6cdf5 100644 --- a/render/vulkan/renderer.c +++ b/render/vulkan/renderer.c @@ -267,6 +267,8 @@ struct wlr_vk_buffer_span vulkan_get_stage_span(struct wlr_vk_renderer *r, goto error_alloc; } + wl_list_init(&buf->link); + VkResult res; VkBufferCreateInfo buf_info = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, diff --git a/types/data_device/wlr_drag.c b/types/data_device/wlr_drag.c index 9ccd53c..6338a43 100644 --- a/types/data_device/wlr_drag.c +++ b/types/data_device/wlr_drag.c @@ -19,6 +19,14 @@ static void drag_handle_seat_client_destroy(struct wl_listener *listener, wl_list_remove(&drag->seat_client_destroy.link); } +static void drag_set_focus(struct wlr_drag *drag, + struct wlr_surface *surface, double sx, double sy); + +static void drag_handle_focus_destroy(struct wl_listener *listener, void *data) { + struct wlr_drag *drag = wl_container_of(listener, drag, focus_destroy); + drag_set_focus(drag, NULL, 0, 0); +} + static void drag_set_focus(struct wlr_drag *drag, struct wlr_surface *surface, double sx, double sy) { if (drag->focus == surface) { @@ -48,9 +56,12 @@ static void drag_set_focus(struct wlr_drag *drag, } drag->focus_client = NULL; - drag->focus = NULL; } + wl_list_remove(&drag->focus_destroy.link); + wl_list_init(&drag->focus_destroy.link); + drag->focus = NULL; + if (!surface) { goto out; } @@ -99,6 +110,8 @@ static void drag_set_focus(struct wlr_drag *drag, drag->focus = surface; drag->focus_client = focus_client; + drag->focus_destroy.notify = drag_handle_focus_destroy; + wl_signal_add(&surface->events.destroy, &drag->focus_destroy); drag->seat_client_destroy.notify = drag_handle_seat_client_destroy; wl_signal_add(&focus_client->events.destroy, &drag->seat_client_destroy); @@ -150,6 +163,7 @@ static void drag_destroy(struct wlr_drag *drag) { if (drag->source) { wl_list_remove(&drag->source_destroy.link); } + wl_list_remove(&drag->focus_destroy.link); if (drag->icon != NULL) { drag_icon_destroy(drag->icon); @@ -410,6 +424,8 @@ struct wlr_drag *wlr_drag_create(struct wlr_seat_client *seat_client, wl_signal_init(&drag->events.drop); wl_signal_init(&drag->events.destroy); + wl_list_init(&drag->focus_destroy.link); + drag->seat = seat_client->seat; drag->seat_client = seat_client; diff --git a/types/wlr_keyboard.c b/types/wlr_keyboard.c index 98978ee..ad15032 100644 --- a/types/wlr_keyboard.c +++ b/types/wlr_keyboard.c @@ -65,8 +65,9 @@ bool keyboard_modifier_update(struct wlr_keyboard *keyboard) { return true; } -void keyboard_key_update(struct wlr_keyboard *keyboard, +bool keyboard_key_update(struct wlr_keyboard *keyboard, struct wlr_keyboard_key_event *event) { + size_t old_num_keycodes = keyboard->num_keycodes; if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { set_add(keyboard->keycodes, &keyboard->num_keycodes, WLR_KEYBOARD_KEYS_CAP, event->keycode); @@ -77,6 +78,8 @@ void keyboard_key_update(struct wlr_keyboard *keyboard, } assert(keyboard->num_keycodes <= WLR_KEYBOARD_KEYS_CAP); + + return old_num_keycodes != keyboard->num_keycodes; } void wlr_keyboard_notify_modifiers(struct wlr_keyboard *keyboard, @@ -98,8 +101,9 @@ void wlr_keyboard_notify_modifiers(struct wlr_keyboard *keyboard, void wlr_keyboard_notify_key(struct wlr_keyboard *keyboard, struct wlr_keyboard_key_event *event) { - keyboard_key_update(keyboard, event); - wl_signal_emit_mutable(&keyboard->events.key, event); + if (keyboard_key_update(keyboard, event)) { + wl_signal_emit_mutable(&keyboard->events.key, event); + } if (keyboard->xkb_state == NULL) { return; diff --git a/types/wlr_output_management_v1.c b/types/wlr_output_management_v1.c index ecc32de..16b771a 100644 --- a/types/wlr_output_management_v1.c +++ b/types/wlr_output_management_v1.c @@ -867,7 +867,7 @@ static void manager_send_head(struct wlr_output_manager_v1 *manager, head_send_mode(head, head_resource, mode); } - if (output->current_mode == NULL) { + if (head->state.mode == NULL && head->state.enabled) { // Output doesn't have a fixed mode set. Send a virtual one. head_send_mode(head, head_resource, NULL); } @@ -927,7 +927,7 @@ static bool manager_update_head(struct wlr_output_manager_v1 *manager, } } - if (next->mode == NULL && !head_has_custom_mode_resources(head)) { + if (next->mode == NULL && next->enabled && !head_has_custom_mode_resources(head)) { struct wl_resource *resource; wl_resource_for_each(resource, &head->resources) { head_send_mode(head, resource, NULL); diff --git a/xwayland/selection/dnd.c b/xwayland/selection/dnd.c index e9cc63d..d914dba 100644 --- a/xwayland/selection/dnd.c +++ b/xwayland/selection/dnd.c @@ -212,10 +212,10 @@ int xwm_handle_selection_client_message(struct wlr_xwm *xwm, bool performed = data->data32[1] & 1; xcb_atom_t action_atom = data->data32[2]; - if (xwm->drag_focus == NULL || - target_window != xwm->drag_focus->window_id) { + if (xwm->drop_focus == NULL || + target_window != xwm->drop_focus->window_id) { wlr_log(WLR_DEBUG, "ignoring XdndFinished client message because " - "it doesn't match the finished drag focus window ID"); + "it doesn't match the finished drop focus window ID"); return 1; } @@ -234,39 +234,56 @@ int xwm_handle_selection_client_message(struct wlr_xwm *xwm, } } -static void seat_handle_drag_focus(struct wl_listener *listener, void *data) { - struct wlr_drag *drag = data; - struct wlr_xwm *xwm = wl_container_of(listener, xwm, seat_drag_focus); +static void xwm_set_drag_focus(struct wlr_xwm *xwm, struct wlr_xwayland_surface *focus); - struct wlr_xwayland_surface *focus = NULL; - if (drag->focus != NULL) { - // TODO: check for subsurfaces? - struct wlr_xwayland_surface *surface; - wl_list_for_each(surface, &xwm->surfaces, link) { - if (surface->surface == drag->focus) { - focus = surface; - break; - } - } - } +static void drag_focus_handle_destroy(struct wl_listener *listener, void *data) { + struct wlr_xwm *xwm = wl_container_of(listener, xwm, drag_focus_destroy); + xwm_set_drag_focus(xwm, NULL); +} +static void drop_focus_handle_destroy(struct wl_listener *listener, void *data) { + struct wlr_xwm *xwm = wl_container_of(listener, xwm, drop_focus_destroy); + wl_list_remove(&xwm->drop_focus_destroy.link); + wl_list_init(&xwm->drop_focus_destroy.link); + xwm->drop_focus = NULL; +} + +static void xwm_set_drag_focus(struct wlr_xwm *xwm, struct wlr_xwayland_surface *focus) { if (focus == xwm->drag_focus) { return; } if (xwm->drag_focus != NULL) { - wlr_data_source_dnd_action(drag->source, + wlr_data_source_dnd_action(xwm->drag->source, WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE); xwm_dnd_send_leave(xwm); } + wl_list_remove(&xwm->drag_focus_destroy.link); + wl_list_init(&xwm->drag_focus_destroy.link); + xwm->drag_focus = focus; if (xwm->drag_focus != NULL) { + xwm->drag_focus_destroy.notify = drag_focus_handle_destroy; + wl_signal_add(&xwm->drag_focus->events.destroy, &xwm->drag_focus_destroy); + xwm_dnd_send_enter(xwm); } } +static void seat_handle_drag_focus(struct wl_listener *listener, void *data) { + struct wlr_drag *drag = data; + struct wlr_xwm *xwm = wl_container_of(listener, xwm, seat_drag_focus); + + struct wlr_xwayland_surface *focus = NULL; + if (drag->focus != NULL) { + focus = wlr_xwayland_surface_try_from_wlr_surface(drag->focus); + } + + xwm_set_drag_focus(xwm, focus); +} + static void seat_handle_drag_motion(struct wl_listener *listener, void *data) { struct wlr_xwm *xwm = wl_container_of(listener, xwm, seat_drag_motion); struct wlr_drag_motion_event *event = data; @@ -289,6 +306,12 @@ static void seat_handle_drag_drop(struct wl_listener *listener, void *data) { } wlr_log(WLR_DEBUG, "Wayland drag dropped over an Xwayland window"); + + xwm->drop_focus = xwm->drag_focus; + xwm->drop_focus_destroy.notify = drop_focus_handle_destroy; + wl_list_remove(&xwm->drop_focus_destroy.link); + wl_signal_add(&xwm->drop_focus->events.destroy, &xwm->drop_focus_destroy); + xwm_dnd_send_drop(xwm, event->time); } @@ -315,12 +338,25 @@ static void seat_handle_drag_source_destroy(struct wl_listener *listener, wl_container_of(listener, xwm, seat_drag_source_destroy); wl_list_remove(&xwm->seat_drag_source_destroy.link); + wl_list_init(&xwm->seat_drag_source_destroy.link); + wl_list_remove(&xwm->drag_focus_destroy.link); + wl_list_init(&xwm->drag_focus_destroy.link); xwm->drag_focus = NULL; + + wl_list_remove(&xwm->drop_focus_destroy.link); + wl_list_init(&xwm->drop_focus_destroy.link); + xwm->drop_focus = NULL; } void xwm_seat_handle_start_drag(struct wlr_xwm *xwm, struct wlr_drag *drag) { + wl_list_remove(&xwm->drag_focus_destroy.link); + wl_list_init(&xwm->drag_focus_destroy.link); + wl_list_remove(&xwm->drop_focus_destroy.link); + wl_list_init(&xwm->drop_focus_destroy.link); + xwm->drag = drag; xwm->drag_focus = NULL; + xwm->drop_focus = NULL; if (drag != NULL) { wl_signal_add(&drag->events.focus, &xwm->seat_drag_focus); @@ -337,3 +373,17 @@ void xwm_seat_handle_start_drag(struct wlr_xwm *xwm, struct wlr_drag *drag) { xwm->seat_drag_source_destroy.notify = seat_handle_drag_source_destroy; } } + +void xwm_seat_unlink_drag_handlers(struct wlr_xwm *xwm) { + wl_list_remove(&xwm->seat_drag_source_destroy.link); + wl_list_remove(&xwm->drag_focus_destroy.link); + wl_list_remove(&xwm->drop_focus_destroy.link); + + if (!xwm->drag) { + return; + } + wl_list_remove(&xwm->seat_drag_focus.link); + wl_list_remove(&xwm->seat_drag_motion.link); + wl_list_remove(&xwm->seat_drag_drop.link); + wl_list_remove(&xwm->seat_drag_destroy.link); +} diff --git a/xwayland/selection/outgoing.c b/xwayland/selection/outgoing.c index 3f2e2c7..f78146f 100644 --- a/xwayland/selection/outgoing.c +++ b/xwayland/selection/outgoing.c @@ -410,8 +410,11 @@ void xwm_handle_selection_request(struct wlr_xwm *xwm, return; } + bool dnd_allowed = selection == &xwm->dnd_selection + && (xwm->drag_focus != NULL || xwm->drop_focus != NULL); + // No xwayland surface focused, deny access to clipboard - if (xwm->focus_surface == NULL && xwm->drag_focus == NULL) { + if (xwm->focus_surface == NULL && !dnd_allowed) { if (wlr_log_get_verbosity() >= WLR_DEBUG) { char *selection_name = xwm_get_atom_name(xwm, selection->atom); wlr_log(WLR_DEBUG, "denying read access to selection %u (%s): " diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 0807d32..b315fa0 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -1879,6 +1879,8 @@ void xwm_destroy(struct wlr_xwm *xwm) { xwm_selection_finish(&xwm->primary_selection); xwm_selection_finish(&xwm->dnd_selection); + xwm_seat_unlink_drag_handlers(xwm); + if (xwm->seat) { if (xwm->seat->selection_source && data_source_is_xwayland(xwm->seat->selection_source)) { @@ -2173,6 +2175,10 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) { wl_list_init(&xwm->surfaces_in_stack_order); wl_list_init(&xwm->unpaired_surfaces); wl_list_init(&xwm->pending_startup_ids); + wl_list_init(&xwm->seat_drag_source_destroy.link); + wl_list_init(&xwm->drag_focus_destroy.link); + wl_list_init(&xwm->drop_focus_destroy.link); + xwm->ping_timeout = 10000; xwm->xcb_conn = xcb_connect_to_fd(wm_fd, NULL);