diff --git a/backend/drm/drm.c b/backend/drm/drm.c index dc442f6..07880c4 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -453,7 +453,7 @@ static bool drm_crtc_commit(struct wlr_drm_connector *conn, if (state->primary_fb != NULL) { crtc->primary->queued_fb = drm_fb_lock(state->primary_fb); } - if (crtc->cursor != NULL) { + if (crtc->cursor != NULL && conn->cursor_pending_fb != NULL) { drm_fb_move(&crtc->cursor->queued_fb, &conn->cursor_pending_fb); } @@ -463,6 +463,10 @@ static bool drm_crtc_commit(struct wlr_drm_connector *conn, } drm_connector_set_pending_page_flip(conn, page_flip); + + if (state->base->committed & WLR_OUTPUT_STATE_MODE) { + conn->refresh = calculate_refresh_rate(&state->mode); + } } else { // The set_cursor() hook is a bit special: it's not really synchronized // to commit() or test(). Once set_cursor() returns true, the new @@ -1454,6 +1458,7 @@ static bool connect_drm_connector(struct wlr_drm_connector *wlr_conn, wlr_conn->crtc->props.mode_id, &mode_id); wlr_conn->crtc->mode_id = mode_id; + wlr_conn->refresh = calculate_refresh_rate(current_modeinfo); } wlr_log(WLR_INFO, " %"PRId32"x%"PRId32" @ %.3f Hz %s", @@ -1753,7 +1758,7 @@ static void handle_page_flip(int fd, unsigned seq, .presented = drm->session->active, .when = &present_time, .seq = seq, - .refresh = mhz_to_nsec(conn->output.refresh), + .refresh = mhz_to_nsec(conn->refresh), .flags = present_flags, }; wlr_output_send_present(&conn->output, &present_event); @@ -1801,16 +1806,10 @@ int wlr_drm_backend_get_non_master_fd(struct wlr_backend *backend) { assert(backend); struct wlr_drm_backend *drm = get_drm_backend_from_backend(backend); - char *path = drmGetDeviceNameFromFd2(drm->fd); - if (!path) { - wlr_log(WLR_ERROR, "Failed to get device name from DRM fd"); - return -1; - } + int fd = open(drm->name, O_RDWR | O_CLOEXEC); - int fd = open(path, O_RDWR | O_CLOEXEC); if (fd < 0) { wlr_log_errno(WLR_ERROR, "Unable to clone DRM fd for client fd"); - free(path); return -1; } diff --git a/backend/drm/libliftoff.c b/backend/drm/libliftoff.c index cafae80..a3b6154 100644 --- a/backend/drm/libliftoff.c +++ b/backend/drm/libliftoff.c @@ -496,6 +496,7 @@ static bool crtc_commit(struct wlr_drm_connector *conn, wlr_log_errno(WLR_ERROR, "Failed to destroy FB_DAMAGE_CLIPS property blob"); } } + wl_array_release(&fb_damage_clips_arr); return ok; } diff --git a/backend/libinput/tablet_pad.c b/backend/libinput/tablet_pad.c index 2e74022..e532752 100644 --- a/backend/libinput/tablet_pad.c +++ b/backend/libinput/tablet_pad.c @@ -33,7 +33,7 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad, ++group->ring_count; } } - group->rings = calloc(sizeof(unsigned int), group->ring_count); + group->rings = calloc(group->ring_count, sizeof(unsigned int)); if (group->rings == NULL) { goto group_fail; } @@ -50,7 +50,7 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad, ++group->strip_count; } } - group->strips = calloc(sizeof(unsigned int), group->strip_count); + group->strips = calloc(group->strip_count, sizeof(unsigned int)); if (group->strips == NULL) { goto group_fail; } @@ -66,7 +66,7 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad, ++group->button_count; } } - group->buttons = calloc(sizeof(unsigned int), group->button_count); + group->buttons = calloc(group->button_count, sizeof(unsigned int)); if (group->buttons == NULL) { goto group_fail; } diff --git a/backend/x11/output.c b/backend/x11/output.c index f5dc527..2521795 100644 --- a/backend/x11/output.c +++ b/backend/x11/output.c @@ -64,6 +64,10 @@ static bool output_set_custom_mode(struct wlr_output *wlr_output, struct wlr_x11_output *output = get_x11_output_from_output(wlr_output); struct wlr_x11_backend *x11 = output->x11; + if (width == output->win_width && height == output->win_height) { + return true; + } + const uint32_t values[] = { width, height }; xcb_void_cookie_t cookie = xcb_configure_window_checked( x11->xcb, output->win, @@ -77,6 +81,9 @@ static bool output_set_custom_mode(struct wlr_output *wlr_output, return false; } + output->win_width = width; + output->win_height = height; + // Move the pointer to its new location update_x11_pointer_position(output, output->x11->time); @@ -114,6 +121,9 @@ static void output_destroy(struct wlr_output *wlr_output) { static bool output_test(struct wlr_output *wlr_output, const struct wlr_output_state *state) { + struct wlr_x11_output *output = get_x11_output_from_output(wlr_output); + struct wlr_x11_backend *x11 = output->x11; + uint32_t unsupported = state->committed & ~SUPPORTED_OUTPUT_STATE; if (unsupported != 0) { wlr_log(WLR_DEBUG, "Unsupported output state fields: 0x%"PRIx32, @@ -133,6 +143,22 @@ static bool output_test(struct wlr_output *wlr_output, } } + if (state->committed & WLR_OUTPUT_STATE_BUFFER) { + struct wlr_buffer *buffer = state->buffer; + struct wlr_dmabuf_attributes dmabuf_attrs; + struct wlr_shm_attributes shm_attrs; + uint32_t format = DRM_FORMAT_INVALID; + if (wlr_buffer_get_dmabuf(buffer, &dmabuf_attrs)) { + format = dmabuf_attrs.format; + } else if (wlr_buffer_get_shm(buffer, &shm_attrs)) { + format = shm_attrs.format; + } + if (format != x11->x11_format->drm) { + wlr_log(WLR_DEBUG, "Unsupported buffer format"); + return false; + } + } + if (state->committed & WLR_OUTPUT_STATE_MODE) { assert(state->mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM); @@ -579,6 +605,9 @@ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) { x11->screen->root, 0, 0, wlr_output->width, wlr_output->height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, x11->visualid, mask, values); + output->win_width = wlr_output->width; + output->win_height = wlr_output->height; + struct { xcb_input_event_mask_t head; xcb_input_xi_event_mask_t mask; @@ -640,6 +669,9 @@ void handle_x11_configure_notify(struct wlr_x11_output *output, return; } + output->win_width = ev->width; + output->win_height = ev->height; + struct wlr_output_state state; wlr_output_state_init(&state); wlr_output_state_set_custom_mode(&state, ev->width, ev->height, 0); diff --git a/debian/changelog b/debian/changelog index 8b7b8b8..bc2deed 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,20 +1,31 @@ -wlroots (0.17.0-2deepin2) unstable; urgency=medium +wlroots (0.17.2-1deepin1) unstable; urgency=medium - * Release new version to reslove conflict with wlroots-git + * Add deepin patchs - -- rewine Fri, 24 Nov 2023 20:00:00 +0800 + -- xiangzelong Wed, 08 May 2024 16:13:15 +0800 -wlroots (0.17.0-1deepin2) unstable; urgency=medium +wlroots (0.17.2-1) experimental; urgency=medium - * Remove unused patch + * Upload to experimental to not disturb ongoing transitions + * New upstream release + * [c097505] gles2: Avoid crash when glGetInteger64vEXT is missing + Backport of upstream commit 341b3c8bd2387d9d6fb684e006a4eb45dfe09efa + + -- Guido Günther Tue, 12 Mar 2024 19:16:00 +0100 + +wlroots (0.17.1-2) unstable; urgency=medium - -- rewine Fri, 24 Nov 2023 17:28:54 +0800 + * Upload to unstable. -wlroots (0.17.0-1deepin1) unstable; urgency=medium + -- Guido Günther Tue, 09 Jan 2024 19:39:59 +0100 - * Add deepin patch +wlroots (0.17.1-1) experimental; urgency=medium - -- xiangzelong Fri, 24 Nov 2023 10:17:53 +0800 + * New upstream release + * d/control: Drop superfluous version information + Thanks: Diederik de Haas + + -- Guido Günther Fri, 22 Dec 2023 15:32:00 +0100 wlroots (0.17.0-1~exp1) experimental; urgency=medium @@ -48,19 +59,6 @@ wlroots (0.16.2-3) unstable; urgency=medium -- Guido Günther Thu, 03 Aug 2023 21:25:19 +0200 -wlroots (0.16.2-2deepin2) unstable; urgency=medium - - * Upload to unstable - * fix error dependency on debian/control - - -- xiangzelong Mon, 03 Jul 2023 16:25:20 +0800 - -wlroots (0.16.2-2deepin1) UNRELEASED; urgency=medium - - * add new patch - - -- xiangzelong Mon, 24 Apr 2023 11:41:46 +0800 - wlroots (0.16.2-2) unstable; urgency=medium * Upload to unstable diff --git a/debian/control b/debian/control index f28d2c6..a83ac6c 100644 --- a/debian/control +++ b/debian/control @@ -9,19 +9,19 @@ Build-Depends: libcap-dev, libcairo2-dev, libdisplay-info-dev (>= 0.1.1), - libdrm-dev (>= 2.4.113), + libdrm-dev (>= 2.4.114), libegl1-mesa-dev, libegl-dev, - libgbm-dev (>= 17.1.0), + libgbm-dev, libgles2-mesa-dev, - libinput-dev (>= 1.9.0), + libinput-dev, libliftoff-dev (>= 0.4.1), libpixman-1-dev, libpng-dev, libseat-dev, libsystemd-dev, libvulkan-dev, - libwayland-dev (>= 1.21), + libwayland-dev (>= 1.22), libx11-xcb-dev, libxcb1-dev, libxcb-composite0-dev, @@ -37,9 +37,9 @@ Build-Depends: libxcb-xfixes0-dev, libxcb-xinput-dev, libxkbcommon-dev, - meson (>= 0.59.0), + meson, pkg-config, - wayland-protocols (>= 1.31), + wayland-protocols (>= 1.24), xwayland, Standards-Version: 4.6.2 Section: libs @@ -59,9 +59,9 @@ Depends: libdisplay-info-dev, libdrm-dev (>= 2.4.114), libegl-dev, - libgbm-dev (>= 17.1.0), + libgbm-dev, libgles2-mesa-dev, - libinput-dev (>= 1.14.0), + libinput-dev, libpixman-1-dev, libseat-dev, libsystemd-dev, diff --git a/debian/patches/Revert-layer-shell-error-on-0-dimension-without-anchors.patch b/debian/patches/Revert-layer-shell-error-on-0-dimension-without-anchors.patch new file mode 100644 index 0000000..f10721e --- /dev/null +++ b/debian/patches/Revert-layer-shell-error-on-0-dimension-without-anchors.patch @@ -0,0 +1,31 @@ +From: =?utf-8?q?Guido_G=C3=BCnther?= +Date: Fri, 1 Jan 2021 13:58:55 +0100 +Subject: Revert "layer-shell: error on 0 dimension without anchors" + +This reverts commit 8dec751a6d84335fb04288b8efab6dd5c90288d3. + +Revert this until phosh has a fixed release. +--- + types/wlr_layer_shell_v1.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/types/wlr_layer_shell_v1.c b/types/wlr_layer_shell_v1.c +index 37256db..2c722a7 100644 +--- a/types/wlr_layer_shell_v1.c ++++ b/types/wlr_layer_shell_v1.c +@@ -335,6 +335,7 @@ static void layer_surface_role_commit(struct wlr_surface *wlr_surface) { + return; + } + ++#if 0 + const uint32_t horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + if (surface->pending.desired_width == 0 && +@@ -354,6 +355,7 @@ static void layer_surface_role_commit(struct wlr_surface *wlr_surface) { + "height 0 requested without setting top and bottom anchors"); + return; + } ++#endif + + if (surface->surface->unmap_commit) { + layer_surface_reset(surface); diff --git a/debian/patches/emit-destroy-signal-in-destroy-function.patch b/debian/patches/emit-destroy-signal-in-destroy-function.patch new file mode 100644 index 0000000..cdc8414 --- /dev/null +++ b/debian/patches/emit-destroy-signal-in-destroy-function.patch @@ -0,0 +1,24 @@ +From 293b0aa502d2e64d68290b1b615e9bd6d203d818 Mon Sep 17 00:00:00 2001 +From: groveer +Date: Mon, 6 May 2024 15:42:18 +0800 +Subject: [PATCH] wlr_pointer_gestures_v1: emit destroy signal in destroy + function + +--- + types/wlr_pointer_gestures_v1.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/types/wlr_pointer_gestures_v1.c b/types/wlr_pointer_gestures_v1.c +index bd9e1f9eb..ebb1c8689 100644 +--- a/types/wlr_pointer_gestures_v1.c ++++ b/types/wlr_pointer_gestures_v1.c +@@ -396,6 +396,7 @@ static void pointer_gestures_v1_bind(struct wl_client *wl_client, void *data, + static void handle_display_destroy(struct wl_listener *listener, void *data) { + struct wlr_pointer_gestures_v1 *gestures = + wl_container_of(listener, gestures, display_destroy); ++ wl_signal_emit_mutable(&gestures->events.destroy, NULL); + wl_list_remove(&gestures->display_destroy.link); + wl_global_destroy(gestures->global); + free(gestures); +-- +GitLab diff --git a/debian/patches/gles2-Avoid-crash-when-glGetInteger64vEXT-is-missing.patch b/debian/patches/gles2-Avoid-crash-when-glGetInteger64vEXT-is-missing.patch new file mode 100644 index 0000000..a7582fd --- /dev/null +++ b/debian/patches/gles2-Avoid-crash-when-glGetInteger64vEXT-is-missing.patch @@ -0,0 +1,35 @@ +From: =?utf-8?q?Guido_G=C3=BCnther?= +Date: Tue, 12 Mar 2024 10:38:21 +0100 +Subject: gles2: Avoid crash when glGetInteger64vEXT is missing + +The spec for GL_EXT_disjoint_timer_query says + +> The GetInteger64vEXT command is required only if OpenGL ES 3.0 or later +> is not supported. + +Some GLES 3.2 implementations like the proprietary mali driver on the +rk3566 based OrangePi advertise GL_EXT_disjoint_timer_query but lack +glGetInteger64vEXT. Use glGetInteger64v instead. + +(cherry picked from commit 341b3c8bd2387d9d6fb684e006a4eb45dfe09efa) +--- + render/gles2/renderer.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c +index 4899cfc..215a5e4 100644 +--- a/render/gles2/renderer.c ++++ b/render/gles2/renderer.c +@@ -915,7 +915,11 @@ struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl) { + load_gl_proc(&renderer->procs.glQueryCounterEXT, "glQueryCounterEXT"); + load_gl_proc(&renderer->procs.glGetQueryObjectivEXT, "glGetQueryObjectivEXT"); + load_gl_proc(&renderer->procs.glGetQueryObjectui64vEXT, "glGetQueryObjectui64vEXT"); +- load_gl_proc(&renderer->procs.glGetInteger64vEXT, "glGetInteger64vEXT"); ++ if (eglGetProcAddress("glGetInteger64vEXT")) { ++ load_gl_proc(&renderer->procs.glGetInteger64vEXT, "glGetInteger64vEXT"); ++ } else { ++ load_gl_proc(&renderer->procs.glGetInteger64vEXT, "glGetInteger64v"); ++ } + } + + if (renderer->exts.KHR_debug) { diff --git a/debian/patches/init-destroy-signal.patch b/debian/patches/init-destroy-signal.patch new file mode 100644 index 0000000..021cd3b --- /dev/null +++ b/debian/patches/init-destroy-signal.patch @@ -0,0 +1,24 @@ +From dead0ebcc8cc0df26925b633040a39190eeb0c55 Mon Sep 17 00:00:00 2001 +From: groveer +Date: Mon, 6 May 2024 15:11:36 +0800 +Subject: [PATCH] wlr_pointer_gestures_v1: init destroy signal + +--- + types/wlr_pointer_gestures_v1.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/types/wlr_pointer_gestures_v1.c b/types/wlr_pointer_gestures_v1.c +index 0763f3ac34..bd9e1f9ebd 100644 +--- a/types/wlr_pointer_gestures_v1.c ++++ b/types/wlr_pointer_gestures_v1.c +@@ -420,6 +420,8 @@ struct wlr_pointer_gestures_v1 *wlr_pointer_gestures_v1_create( + return NULL; + } + ++ wl_signal_init(&gestures->events.destroy); ++ + gestures->display_destroy.notify = handle_display_destroy; + wl_display_add_destroy_listener(display, &gestures->display_destroy); + +-- +GitLab diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000..3263ad2 --- /dev/null +++ b/debian/patches/series @@ -0,0 +1,4 @@ +Revert-layer-shell-error-on-0-dimension-without-anchors.patch +gles2-Avoid-crash-when-glGetInteger64vEXT-is-missing.patch +emit-destroy-signal-in-destroy-function.patch +init-destroy-signal.patch diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index 88eacc6..39a247b 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -175,6 +175,8 @@ struct wlr_drm_connector { // Last committed page-flip struct wlr_drm_page_flip *pending_page_flip; + + int32_t refresh; }; struct wlr_drm_backend *get_drm_backend_from_backend( diff --git a/include/backend/x11.h b/include/backend/x11.h index 06834c1..9eb208b 100644 --- a/include/backend/x11.h +++ b/include/backend/x11.h @@ -35,6 +35,8 @@ struct wlr_x11_output { xcb_window_t win; xcb_present_event_t present_event_id; + int32_t win_width, win_height; + struct wlr_pointer pointer; struct wlr_touch touch; diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 28a5ebc..9de8dff 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -182,7 +182,7 @@ struct wlr_output { // Emitted after a client bound the wl_output global struct wl_signal bind; // struct wlr_output_event_bind struct wl_signal description; - struct wl_signal request_state; // struct wlr_output_state + struct wl_signal request_state; // struct wlr_output_event_request_state struct wl_signal destroy; } events; diff --git a/meson.build b/meson.build index 7e8b59d..0122500 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project( 'wlroots', 'c', - version: '0.17.0', + version: '0.17.2', license: 'MIT', meson_version: '>=0.59.0', default_options: [ diff --git a/render/egl.c b/render/egl.c index 8a1e6da..162634b 100644 --- a/render/egl.c +++ b/render/egl.c @@ -954,7 +954,7 @@ static char *get_render_name(const char *name) { return render_name; } -int wlr_egl_dup_drm_fd(struct wlr_egl *egl) { +static int dup_egl_device_drm_fd(struct wlr_egl *egl) { if (egl->device == EGL_NO_DEVICE_EXT || (!egl->exts.EXT_device_drm && !egl->exts.EXT_device_drm_render_node)) { return -1; @@ -1001,3 +1001,21 @@ int wlr_egl_dup_drm_fd(struct wlr_egl *egl) { return render_fd; } + +int wlr_egl_dup_drm_fd(struct wlr_egl *egl) { + int fd = dup_egl_device_drm_fd(egl); + if (fd >= 0) { + return fd; + } + + // Fallback to GBM's FD if we can't use EGLDevice + if (egl->gbm_device == NULL) { + return -1; + } + + fd = fcntl(gbm_device_get_fd(egl->gbm_device), F_DUPFD_CLOEXEC, 0); + if (fd < 0) { + wlr_log_errno(WLR_ERROR, "Failed to dup GBM FD"); + } + return fd; +} diff --git a/render/vulkan/shaders/texture.frag b/render/vulkan/shaders/texture.frag index eab2c2d..6f2f347 100644 --- a/render/vulkan/shaders/texture.frag +++ b/render/vulkan/shaders/texture.frag @@ -16,7 +16,9 @@ layout (constant_id = 0) const int TEXTURE_TRANSFORM = 0; #define TEXTURE_TRANSFORM_SRGB 1 float srgb_channel_to_linear(float x) { - return max(x / 12.92, pow((x + 0.055) / 1.055, 2.4)); + return mix(x / 12.92, + pow((x + 0.055) / 1.055, 2.4), + x > 0.04045); } vec4 srgb_color_to_linear(vec4 color) { diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c index d4043b4..2bdcff5 100644 --- a/render/wlr_renderer.c +++ b/render/wlr_renderer.c @@ -228,13 +228,10 @@ bool wlr_renderer_init_wl_display(struct wlr_renderer *r, return false; } - if (wlr_renderer_get_dmabuf_texture_formats(r) != NULL) { - if (wlr_renderer_get_drm_fd(r) >= 0) { - if (wlr_drm_create(wl_display, r) == NULL) { - return false; - } - } else { - wlr_log(WLR_INFO, "Cannot get renderer DRM FD, disabling wl_drm"); + if (wlr_renderer_get_dmabuf_texture_formats(r) != NULL && + wlr_renderer_get_drm_fd(r) >= 0) { + if (wlr_drm_create(wl_display, r) == NULL) { + return false; } if (wlr_linux_dmabuf_v1_create_with_renderer(wl_display, 4, r) == NULL) { diff --git a/tinywl/Makefile b/tinywl/Makefile index 0cfb3cd..8f1df20 100644 --- a/tinywl/Makefile +++ b/tinywl/Makefile @@ -1,7 +1,7 @@ WAYLAND_PROTOCOLS=$(shell pkg-config --variable=pkgdatadir wayland-protocols) WAYLAND_SCANNER=$(shell pkg-config --variable=wayland_scanner wayland-scanner) LIBS=\ - $(shell pkg-config --cflags --libs "wlroots >= 0.17.0-dev") \ + $(shell pkg-config --cflags --libs "wlroots >= 0.17.0") \ $(shell pkg-config --cflags --libs wayland-server) \ $(shell pkg-config --cflags --libs xkbcommon) diff --git a/tinywl/meson.build b/tinywl/meson.build index 82d31d2..e727145 100644 --- a/tinywl/meson.build +++ b/tinywl/meson.build @@ -1,5 +1,5 @@ executable( 'tinywl', - ['tinywl.c', protocols_client_header['xdg-shell']], + ['tinywl.c', protocols_server_header['xdg-shell']], dependencies: wlroots, ) diff --git a/types/output/output.c b/types/output/output.c index 08a71d8..af2fab5 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -450,11 +450,12 @@ void wlr_output_destroy(struct wlr_output *output) { return; } + wl_signal_emit_mutable(&output->events.destroy, output); + wl_list_remove(&output->display_destroy.link); wlr_output_destroy_global(output); output_clear_back_buffer(output); - wl_signal_emit_mutable(&output->events.destroy, output); wlr_addon_set_finish(&output->addons); // The backend is responsible for free-ing the list of modes diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index ee41337..c651565 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -264,6 +265,16 @@ static struct wlr_cursor_device *get_cursor_device(struct wlr_cursor *cur, return ret; } +static void output_cursor_move(struct wlr_cursor_output_cursor *output_cursor) { + struct wlr_cursor *cur = output_cursor->cursor; + + double output_x = cur->x, output_y = cur->y; + wlr_output_layout_output_coords(cur->state->layout, + output_cursor->output_cursor->output, &output_x, &output_y); + wlr_output_cursor_move(output_cursor->output_cursor, + output_x, output_y); +} + static void cursor_warp_unchecked(struct wlr_cursor *cur, double lx, double ly) { assert(cur->state->layout); @@ -272,17 +283,13 @@ static void cursor_warp_unchecked(struct wlr_cursor *cur, return; } + cur->x = lx; + cur->y = ly; + struct wlr_cursor_output_cursor *output_cursor; wl_list_for_each(output_cursor, &cur->state->output_cursors, link) { - double output_x = lx, output_y = ly; - wlr_output_layout_output_coords(cur->state->layout, - output_cursor->output_cursor->output, &output_x, &output_y); - wlr_output_cursor_move(output_cursor->output_cursor, - output_x, output_y); + output_cursor_move(output_cursor); } - - cur->x = lx; - cur->y = ly; } /** @@ -545,6 +552,16 @@ static void cursor_output_cursor_update(struct wlr_cursor_output_cursor *output_ } else { wlr_surface_send_leave(surface, output); } + + float scale = 1; + struct wlr_surface_output *surface_output; + wl_list_for_each(surface_output, &surface->current_outputs, link) { + if (surface_output->output->scale > scale) { + scale = surface_output->output->scale; + } + } + wlr_fractional_scale_v1_notify_scale(surface, scale); + wlr_surface_set_preferred_buffer_scale(surface, ceil(scale)); } else if (cur->state->xcursor_name != NULL) { struct wlr_xcursor_manager *manager = cur->state->xcursor_manager; const char *name = cur->state->xcursor_name; @@ -1094,6 +1111,7 @@ static void layout_add(struct wlr_cursor_state *state, &output_cursor->output_commit); output_cursor->output_commit.notify = output_cursor_output_handle_output_commit; + output_cursor_move(output_cursor); cursor_output_cursor_update(output_cursor); } @@ -1163,21 +1181,11 @@ void wlr_cursor_map_input_to_output(struct wlr_cursor *cur, void wlr_cursor_map_to_region(struct wlr_cursor *cur, const struct wlr_box *box) { - cur->state->mapped_box = (struct wlr_box){0}; - - if (box) { - if (wlr_box_empty(box)) { - wlr_log(WLR_ERROR, "cannot map cursor to an empty region"); - return; - } - cur->state->mapped_box = *box; - } + cur->state->mapped_box = wlr_box_empty(box) ? (struct wlr_box){0} : *box; } void wlr_cursor_map_input_to_region(struct wlr_cursor *cur, struct wlr_input_device *dev, const struct wlr_box *box) { - cur->state->mapped_box = (struct wlr_box){0}; - struct wlr_cursor_device *c_device = get_cursor_device(cur, dev); if (!c_device) { wlr_log(WLR_ERROR, "Cannot map device \"%s\" to geometry (not found in" @@ -1185,13 +1193,5 @@ void wlr_cursor_map_input_to_region(struct wlr_cursor *cur, return; } - if (box) { - if (wlr_box_empty(box)) { - wlr_log(WLR_ERROR, - "cannot map device \"%s\" input to an empty region", - dev->name); - return; - } - c_device->mapped_box = *box; - } + c_device->mapped_box = wlr_box_empty(box) ? (struct wlr_box){0} : *box; } diff --git a/types/wlr_cursor_shape_v1.c b/types/wlr_cursor_shape_v1.c index d9f26f9..ca33cf1 100644 --- a/types/wlr_cursor_shape_v1.c +++ b/types/wlr_cursor_shape_v1.c @@ -126,7 +126,10 @@ static void manager_handle_get_pointer(struct wl_client *client, struct wl_resou static void manager_handle_get_tablet_tool_v2(struct wl_client *client, struct wl_resource *manager_resource, uint32_t id, struct wl_resource *tablet_tool_resource) { struct wlr_tablet_tool_client_v2 *tablet_tool_client = tablet_tool_client_from_resource(tablet_tool_resource); - struct wlr_seat_client *seat_client = tablet_tool_client->seat->seat_client; + struct wlr_seat_client *seat_client = NULL; + if (tablet_tool_client != NULL) { + seat_client = tablet_tool_client->seat->seat_client; + } create_device(manager_resource, id, seat_client, WLR_CURSOR_SHAPE_MANAGER_V1_DEVICE_TYPE_TABLET_TOOL); } diff --git a/types/wlr_input_method_v2.c b/types/wlr_input_method_v2.c index 0e6a18b..512adb3 100644 --- a/types/wlr_input_method_v2.c +++ b/types/wlr_input_method_v2.c @@ -80,11 +80,17 @@ static void im_commit(struct wl_client *client, struct wl_resource *resource, if (!input_method) { return; } + if (serial != input_method->current_serial) { + free(input_method->pending.commit_text); + free(input_method->pending.preedit.text); + input_method->pending = (struct wlr_input_method_v2_state){0}; + return; + } + free(input_method->current.commit_text); + free(input_method->current.preedit.text); input_method->current = input_method->pending; - input_method->current_serial = serial; - struct wlr_input_method_v2_state default_state = {0}; - input_method->pending = default_state; - wl_signal_emit_mutable(&input_method->events.commit, (void*)input_method); + input_method->pending = (struct wlr_input_method_v2_state){0}; + wl_signal_emit_mutable(&input_method->events.commit, input_method); } static void im_commit_string(struct wl_client *client, diff --git a/types/wlr_layer_shell_v1.c b/types/wlr_layer_shell_v1.c index 37256db..fd19a67 100644 --- a/types/wlr_layer_shell_v1.c +++ b/types/wlr_layer_shell_v1.c @@ -130,6 +130,12 @@ static void layer_surface_handle_set_size(struct wl_client *client, return; } + if (width > INT32_MAX || height > INT32_MAX) { + wl_client_post_implementation_error(client, + "zwlr_layer_surface_v1.set_size: width and height can't be greater than INT32_MAX"); + return; + } + if (surface->current.desired_width == width && surface->current.desired_height == height) { surface->pending.committed &= ~WLR_LAYER_SURFACE_V1_STATE_DESIRED_SIZE; diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c index e0bd702..23d1334 100644 --- a/types/wlr_output_layout.c +++ b/types/wlr_output_layout.c @@ -106,7 +106,7 @@ static void output_layout_reconfigure(struct wlr_output_layout *layout) { static void output_update_global(struct wlr_output *output) { // Don't expose the output if it doesn't have a current mode - if (wl_list_empty(&output->modes) || output->current_mode != NULL) { + if (output->width > 0 && output->height > 0) { wlr_output_create_global(output); } else { wlr_output_destroy_global(output); diff --git a/types/wlr_pointer_constraints_v1.c b/types/wlr_pointer_constraints_v1.c index 03aea9f..9f4bb2e 100644 --- a/types/wlr_pointer_constraints_v1.c +++ b/types/wlr_pointer_constraints_v1.c @@ -176,17 +176,8 @@ static void pointer_constraint_create(struct wl_client *client, pointer_constraints_from_resource(pointer_constraints_resource); struct wlr_surface *surface = wlr_surface_from_resource(surface_resource); - struct wlr_seat *seat = - wlr_seat_client_from_pointer_resource(pointer_resource)->seat; - - if (wlr_pointer_constraints_v1_constraint_for_surface(pointer_constraints, - surface, seat)) { - wl_resource_post_error(pointer_constraints_resource, - ZWP_POINTER_CONSTRAINTS_V1_ERROR_ALREADY_CONSTRAINED, - "a pointer constraint with a wl_pointer of the same wl_seat" - " is already on this surface"); - return; - } + struct wlr_seat_client *seat_client = + wlr_seat_client_from_pointer_resource(pointer_resource); uint32_t version = wl_resource_get_version(pointer_constraints_resource); @@ -200,6 +191,28 @@ static void pointer_constraint_create(struct wl_client *client, return; } + void *impl = locked_pointer ? + (void *)&locked_pointer_impl : (void *)&confined_pointer_impl; + wl_resource_set_implementation(resource, impl, NULL, + pointer_constraint_destroy_resource); + + if (seat_client == NULL) { + // Leave the resource inert + return; + } + + struct wlr_seat *seat = seat_client->seat; + + if (wlr_pointer_constraints_v1_constraint_for_surface(pointer_constraints, + surface, seat)) { + wl_resource_destroy(resource); + wl_resource_post_error(pointer_constraints_resource, + ZWP_POINTER_CONSTRAINTS_V1_ERROR_ALREADY_CONSTRAINED, + "a pointer constraint with a wl_pointer of the same wl_seat" + " is already on this surface"); + return; + } + struct wlr_pointer_constraint_v1 *constraint = calloc(1, sizeof(*constraint)); if (constraint == NULL) { wl_resource_destroy(resource); @@ -234,10 +247,7 @@ static void pointer_constraint_create(struct wl_client *client, constraint->seat_destroy.notify = handle_seat_destroy; wl_signal_add(&seat->events.destroy, &constraint->seat_destroy); - void *impl = locked_pointer ? - (void *)&locked_pointer_impl : (void *)&confined_pointer_impl; - wl_resource_set_implementation(constraint->resource, impl, constraint, - pointer_constraint_destroy_resource); + wl_resource_set_user_data(resource, constraint); wlr_log(WLR_DEBUG, "new %s_pointer %p (res %p)", locked_pointer ? "locked" : "confined", diff --git a/types/wlr_viewporter.c b/types/wlr_viewporter.c index 9e743d5..0e5069b 100644 --- a/types/wlr_viewporter.c +++ b/types/wlr_viewporter.c @@ -13,7 +13,7 @@ struct wlr_viewport { struct wlr_addon addon; - struct wl_listener surface_commit; + struct wl_listener surface_client_commit; }; static const struct wp_viewport_interface viewport_impl; @@ -112,7 +112,7 @@ static void viewport_destroy(struct wlr_viewport *viewport) { wlr_addon_finish(&viewport->addon); wl_resource_set_user_data(viewport->resource, NULL); - wl_list_remove(&viewport->surface_commit.link); + wl_list_remove(&viewport->surface_client_commit.link); free(viewport); } @@ -131,27 +131,37 @@ static void viewport_handle_resource_destroy(struct wl_resource *resource) { viewport_destroy(viewport); } -static void viewport_handle_surface_commit(struct wl_listener *listener, +static bool check_src_buffer_bounds(const struct wlr_surface_state *state) { + int width = state->buffer_width / state->scale; + int height = state->buffer_height / state->scale; + if (state->transform & WL_OUTPUT_TRANSFORM_90) { + int tmp = width; + width = height; + height = tmp; + } + + struct wlr_fbox box = state->viewport.src; + return box.x + box.width <= width && box.y + box.height <= height; +} + +static void viewport_handle_surface_client_commit(struct wl_listener *listener, void *data) { struct wlr_viewport *viewport = - wl_container_of(listener, viewport, surface_commit); + wl_container_of(listener, viewport, surface_client_commit); - struct wlr_surface_state *current = &viewport->surface->pending; + struct wlr_surface_state *state = &viewport->surface->pending; - if (!current->viewport.has_dst && - (floor(current->viewport.src.width) != current->viewport.src.width || - floor(current->viewport.src.height) != current->viewport.src.height)) { + if (!state->viewport.has_dst && + (floor(state->viewport.src.width) != state->viewport.src.width || + floor(state->viewport.src.height) != state->viewport.src.height)) { wl_resource_post_error(viewport->resource, WP_VIEWPORT_ERROR_BAD_SIZE, "wl_viewport.set_source width and height must be integers " "when the destination rectangle is unset"); return; } - if (current->viewport.has_src && current->buffer != NULL && - (current->viewport.src.x + current->viewport.src.width > - current->buffer_width || - current->viewport.src.y + current->viewport.src.height > - current->buffer_height)) { + if (state->viewport.has_src && state->buffer != NULL && + !check_src_buffer_bounds(state)) { wl_resource_post_error(viewport->resource, WP_VIEWPORT_ERROR_OUT_OF_BUFFER, "source rectangle out of buffer bounds"); return; @@ -195,8 +205,8 @@ static void viewporter_handle_get_viewport(struct wl_client *client, wlr_addon_init(&viewport->addon, &surface->addons, NULL, &surface_addon_impl); - viewport->surface_commit.notify = viewport_handle_surface_commit; - wl_signal_add(&surface->events.commit, &viewport->surface_commit); + viewport->surface_client_commit.notify = viewport_handle_surface_client_commit; + wl_signal_add(&surface->events.client_commit, &viewport->surface_client_commit); } static const struct wp_viewporter_interface viewporter_impl = { diff --git a/xcursor/wlr_xcursor.c b/xcursor/wlr_xcursor.c index a946efd..620b6c7 100644 --- a/xcursor/wlr_xcursor.c +++ b/xcursor/wlr_xcursor.c @@ -170,10 +170,13 @@ static struct wlr_xcursor *xcursor_create_from_xcursor_images( return cursor; } +static struct wlr_xcursor *xcursor_theme_get_cursor(struct wlr_xcursor_theme *theme, + const char *name); + static void load_callback(struct xcursor_images *images, void *data) { struct wlr_xcursor_theme *theme = data; - if (wlr_xcursor_theme_get_cursor(theme, images->name)) { + if (xcursor_theme_get_cursor(theme, images->name)) { xcursor_images_destroy(images); return; } diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 2c437e8..7f19871 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -133,6 +133,34 @@ static int xwayland_surface_handle_ping_timeout(void *data) { return 1; } +static void read_surface_client_id(struct wlr_xwm *xwm, + struct wlr_xwayland_surface *xsurface, + xcb_res_query_client_ids_cookie_t cookie) { + xcb_res_query_client_ids_reply_t *reply = xcb_res_query_client_ids_reply( + xwm->xcb_conn, cookie, NULL); + if (reply == NULL) { + return; + } + + uint32_t *pid = NULL; + xcb_res_client_id_value_iterator_t iter = + xcb_res_query_client_ids_ids_iterator(reply); + while (iter.rem > 0) { + if (iter.data->spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID && + xcb_res_client_id_value_value_length(iter.data) > 0) { + pid = xcb_res_client_id_value_value(iter.data); + break; + } + xcb_res_client_id_value_next(&iter); + } + if (pid == NULL) { + free(reply); + return; + } + xsurface->pid = *pid; + free(reply); +} + static struct wlr_xwayland_surface *xwayland_surface_create( struct wlr_xwm *xwm, xcb_window_t window_id, int16_t x, int16_t y, uint16_t width, uint16_t height, bool override_redirect) { @@ -145,6 +173,15 @@ static struct wlr_xwayland_surface *xwayland_surface_create( xcb_get_geometry_cookie_t geometry_cookie = xcb_get_geometry(xwm->xcb_conn, window_id); + xcb_res_query_client_ids_cookie_t client_id_cookie; + if (xwm->xres) { + xcb_res_client_id_spec_t spec = { + .client = window_id, + .mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID + }; + client_id_cookie = xcb_res_query_client_ids(xwm->xcb_conn, 1, &spec); + } + uint32_t values[1]; values[0] = XCB_EVENT_MASK_FOCUS_CHANGE | @@ -205,6 +242,10 @@ static struct wlr_xwayland_surface *xwayland_surface_create( wl_list_insert(&xwm->surfaces, &surface->link); + if (xwm->xres) { + read_surface_client_id(xwm, surface, client_id_cookie); + } + wl_signal_emit_mutable(&xwm->xwayland->events.new_surface, surface); return surface; @@ -595,34 +636,6 @@ static void read_surface_parent(struct wlr_xwm *xwm, wl_signal_emit_mutable(&xsurface->events.set_parent, NULL); } -static void read_surface_client_id(struct wlr_xwm *xwm, - struct wlr_xwayland_surface *xsurface, - xcb_res_query_client_ids_cookie_t cookie) { - xcb_res_query_client_ids_reply_t *reply = xcb_res_query_client_ids_reply( - xwm->xcb_conn, cookie, NULL); - if (reply == NULL) { - return; - } - - uint32_t *pid = NULL; - xcb_res_client_id_value_iterator_t iter = - xcb_res_query_client_ids_ids_iterator(reply); - while (iter.rem > 0) { - if (iter.data->spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID && - xcb_res_client_id_value_value_length(iter.data) > 0) { - pid = xcb_res_client_id_value_value(iter.data); - break; - } - xcb_res_client_id_value_next(&iter); - } - if (pid == NULL) { - free(reply); - return; - } - xsurface->pid = *pid; - free(reply); -} - static void read_surface_window_type(struct wlr_xwm *xwm, struct wlr_xwayland_surface *xsurface, xcb_get_property_reply_t *reply) { @@ -921,30 +934,17 @@ static void xwayland_surface_associate(struct wlr_xwm *xwm, props[i], XCB_ATOM_ANY, 0, 2048); } - xcb_res_query_client_ids_cookie_t client_id_cookie; - if (xwm->xres) { - xcb_res_client_id_spec_t spec = { - .client = xsurface->window_id, - .mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID - }; - client_id_cookie = xcb_res_query_client_ids(xwm->xcb_conn, 1, &spec); - } - for (size_t i = 0; i < sizeof(props) / sizeof(props[0]); i++) { xcb_get_property_reply_t *reply = xcb_get_property_reply(xwm->xcb_conn, cookies[i], NULL); if (reply == NULL) { wlr_log(WLR_ERROR, "Failed to get window property"); - return; + continue; } read_surface_property(xwm, xsurface, props[i], reply); free(reply); } - if (xwm->xres) { - read_surface_client_id(xwm, xsurface, client_id_cookie); - } - wl_signal_emit_mutable(&xsurface->events.associate, NULL); }