]> git.mdlowis.com Git - proto/labwc.git/commitdiff
desktop: work around client-side rounding issues at right/bottom pixel
authorJohn Lindgren <john@jlindgren.net>
Mon, 20 Oct 2025 02:15:37 +0000 (22:15 -0400)
committerJohan Malm <johanmalm@users.noreply.github.com>
Mon, 20 Oct 2025 19:11:08 +0000 (20:11 +0100)
This also avoids a similar server-side rounding issue with some
combinations of wlroots and libwayland versions. See:

- https://gitlab.freedesktop.org/wayland/wayland/-/issues/555
- https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5159

Tested with qmpanel (similar to lxqt-panel) at 1x and 2x output scale.
Does not help if scaling is done client-side, e.g. QT_SCALE_FACTOR=2.

Fixes: #2379
Fixes: #3099
src/desktop.c

index bac6c06566dc6ea642b5c3326cc584dbae36df48..2d883445295064d09096e6504c3751694d930a7f 100644 (file)
@@ -242,6 +242,39 @@ desktop_update_top_layer_visibility(struct server *server)
        }
 }
 
+/*
+ * Work around rounding issues in some clients (notably Qt apps) where
+ * cursor coordinates in the rightmost or bottom pixel are incorrectly
+ * rounded up, putting them outside the surface bounds. The effect is
+ * especially noticeable in right/bottom desktop panels, since driving
+ * the cursor to the edge of the screen no longer works.
+ *
+ * Under X11, such rounding issues went unnoticed since cursor positions
+ * were always integers (i.e. whole pixel boundaries) anyway. Until more
+ * clients/toolkits are fractional-pixel clean, limit surface cursor
+ * coordinates to (w - 1, h - 1) as a workaround.
+ */
+static void
+avoid_edge_rounding_issues(struct cursor_context *ctx)
+{
+       if (!ctx->surface) {
+               return;
+       }
+
+       int w = ctx->surface->current.width;
+       int h = ctx->surface->current.height;
+       /*
+        * The cursor isn't expected to be outside the surface bounds
+        * here, but check (sx < w, sy < h) just in case.
+        */
+       if (ctx->sx > w - 1 && ctx->sx < w) {
+               ctx->sx = w - 1;
+       }
+       if (ctx->sy > h - 1 && ctx->sy < h) {
+               ctx->sy = h - 1;
+       }
+}
+
 /* TODO: make this less big and scary */
 struct cursor_context
 get_cursor_context(struct server *server)
@@ -269,6 +302,8 @@ get_cursor_context(struct server *server)
        ret.node = node;
        ret.surface = lab_wlr_surface_from_node(node);
 
+       avoid_edge_rounding_issues(&ret);
+
 #if HAVE_XWAYLAND
        /* TODO: attach LAB_NODE_UNMANAGED node-descriptor to unmanaged surfaces */
        if (node->type == WLR_SCENE_NODE_BUFFER) {