[mutter] cursor-sprite-xcursor: Emulate Wayland hotspot limitations



commit 40c345d6f3b5cfba19464e0b0e5732a194eaac3d
Author: Jonas Ådahl <jadahl gmail com>
Date:   Fri Mar 6 11:50:38 2020 +0100

    cursor-sprite-xcursor: Emulate Wayland hotspot limitations
    
    For HiDPI pointer cursors backed by Wayland surfaces, the hotspot must
    be placed using integers on the logical pixel grid. In practice what
    this means is that if the client loads a cursor sprite with the buffer
    scale 2, and it's hotspot is not dividable by 2, it will be rounded
    down to an integer that can. E.g. a wl_surface with buffer scale 2 and a
    cursor image with hotspot coordinate (7, 7) will have the coordinate
    (3.5, 3.5) in surface coordinate space, and will in practice be rounded
    down to (3, 3) as the hotspot position in wl_pointer only takes
    integers.
    
    To not potentially shift by 1 pixel on HiDPI monitors when switching
    between wl_surface backend cursor sprites and built-in ones, make the
    built in one emulate the restrictions put up by the Wayland protocol.
    
    This also initializes the theme scale of the xcursor sprite instances to
    1, as they may not have been set prior to being used, it'll only happen
    in response to "prepare-at" signals being emitted prior to rendering.
    
    Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/1092
    
    https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1107

 src/backends/meta-cursor-sprite-xcursor.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)
---
diff --git a/src/backends/meta-cursor-sprite-xcursor.c b/src/backends/meta-cursor-sprite-xcursor.c
index 120ccb598..599d0e697 100644
--- a/src/backends/meta-cursor-sprite-xcursor.c
+++ b/src/backends/meta-cursor-sprite-xcursor.c
@@ -25,6 +25,7 @@
 #include "clutter/clutter.h"
 #include "cogl/cogl.h"
 #include "meta/prefs.h"
+#include "meta/util.h"
 
 struct _MetaCursorSpriteXcursor
 {
@@ -124,6 +125,7 @@ load_from_current_xcursor_image (MetaCursorSpriteXcursor *sprite_xcursor)
   CoglContext *cogl_context;
   CoglTexture2D *texture;
   GError *error = NULL;
+  int hotspot_x, hotspot_y;
 
   g_assert (!meta_cursor_sprite_get_cogl_texture (sprite));
 
@@ -152,9 +154,21 @@ load_from_current_xcursor_image (MetaCursorSpriteXcursor *sprite_xcursor)
       g_error_free (error);
     }
 
+  if (meta_is_wayland_compositor ())
+    {
+      hotspot_x = ((int) (xc_image->xhot / sprite_xcursor->theme_scale) *
+                   sprite_xcursor->theme_scale);
+      hotspot_y = ((int) (xc_image->yhot / sprite_xcursor->theme_scale) *
+                   sprite_xcursor->theme_scale);
+    }
+  else
+    {
+      hotspot_x = xc_image->xhot;
+      hotspot_y = xc_image->yhot;
+    }
   meta_cursor_sprite_set_texture (sprite,
                                   COGL_TEXTURE (texture),
-                                  xc_image->xhot, xc_image->yhot);
+                                  hotspot_x, hotspot_y);
 
   g_clear_pointer (&texture, cogl_object_unref);
 }
@@ -272,6 +286,7 @@ meta_cursor_sprite_xcursor_finalize (GObject *object)
 static void
 meta_cursor_sprite_xcursor_init (MetaCursorSpriteXcursor *sprite_xcursor)
 {
+  sprite_xcursor->theme_scale = 1;
   sprite_xcursor->theme_dirty = TRUE;
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]