wayland: Add support for the fractional scale protocol
authorBenjamin Otte <otte@redhat.com>
Sat, 1 Apr 2023 10:48:26 +0000 (12:48 +0200)
committerBenjamin Otte <otte@redhat.com>
Sat, 1 Apr 2023 10:57:03 +0000 (12:57 +0200)
April fools!

No, really.
The fractional scale protocol is just a way to track the surface scale,
but not a way to draw fractional content.
This commit uses it for that, so tht we don't rely on tracking outputs.

This also allows magnifiers etc to send us a larger (integer) scale if
they would like that, that is not represented by the outputs.

gdk/wayland/gdkdisplay-wayland.c
gdk/wayland/gdkdisplay-wayland.h
gdk/wayland/gdksurface-wayland-private.h
gdk/wayland/gdksurface-wayland.c
gdk/wayland/meson.build

index 5a5533badbd807c90493ce23c579a238f55ef61e..541f34789cffcfd5c695dbe61b5f50475b578f38 100644 (file)
@@ -509,6 +509,14 @@ gdk_registry_handle_global (void               *data,
                           &xdg_activation_v1_interface,
                           MIN (version, XDG_ACTIVATION_VERSION));
     }
+  else if (strcmp (interface, "wp_fractional_scale_manager_v1") == 0)
+    {
+      display_wayland->fractional_scale =
+        wl_registry_bind (display_wayland->wl_registry, id,
+                          &wp_fractional_scale_manager_v1_interface,
+                          MIN (version, 1));
+    }
+
 
   g_hash_table_insert (display_wayland->known_globals,
                        GUINT_TO_POINTER (id), g_strdup (interface));
index 332e30259d2f2e46348c77d81202412244524e3d..6dbe7931579adb0edf2936444b16962f170a019c 100644 (file)
@@ -37,6 +37,7 @@
 #include <gdk/wayland/idle-inhibit-unstable-v1-client-protocol.h>
 #include <gdk/wayland/primary-selection-unstable-v1-client-protocol.h>
 #include <gdk/wayland/xdg-activation-v1-client-protocol.h>
+#include <gdk/wayland/fractional-scale-v1-client-protocol.h>
 
 #include <glib.h>
 #include <gdk/gdkkeys.h>
@@ -111,6 +112,7 @@ struct _GdkWaylandDisplay
   struct zxdg_output_manager_v1 *xdg_output_manager;
   struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager;
   struct xdg_activation_v1 *xdg_activation;
+  struct wp_fractional_scale_manager_v1 *fractional_scale;
 
   GList *async_roundtrips;
 
index 0ecd0763f3c083b61edddf7edb20bbd47599ee44..4689945cc778b8fe98f370b738b6ebf9ecd55e83 100644 (file)
@@ -35,6 +35,7 @@ struct _GdkWaylandSurface
     struct xdg_surface *xdg_surface;
     struct zxdg_surface_v6 *zxdg_surface_v6;
     struct wl_egl_window *egl_window;
+    struct wp_fractional_scale_v1 *fractional_scale;
   } display_server;
 
   struct wl_event_queue *event_queue;
index 38d3cb54e0dd6fa13495d7b52d44976118a74791..7c952af08317805a41a83665d2a9a433e0b98560 100644 (file)
@@ -28,7 +28,6 @@
 #include "gdkmonitor-wayland.h"
 #include "gdkpopupprivate.h"
 #include "gdkprivate-wayland.h"
-#include "gdkprivate-wayland.h"
 #include "gdkseat-wayland.h"
 #include "gdksurfaceprivate.h"
 #include "gdktoplevelprivate.h"
@@ -426,12 +425,14 @@ gdk_wayland_surface_update_scale (GdkSurface *surface)
   guint32 scale;
   GSList *l;
 
+  /* We can't set the scale on this surface */
   if (!impl->display_server.wl_surface ||
       wl_surface_get_version (impl->display_server.wl_surface) < WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION)
-    {
-      /* We can't set the scale on this surface */
-      return;
-    }
+    return;
+
+  /* scale is tracked by the fractional scale extension */
+  if (impl->display_server.fractional_scale)
+    return;
 
   if (!impl->display_server.outputs)
     {
@@ -797,6 +798,24 @@ gdk_wayland_surface_sync_buffer_scale (GdkSurface *surface)
   impl->buffer_scale_dirty = FALSE;
 }
 
+static void
+gdk_wayland_surface_fractional_scale_preferred_scale_cb (void *data,
+                                                         struct wp_fractional_scale_v1 *fractional_scale,
+                                                         uint32_t scale)
+{
+  GdkWaylandSurface *self = GDK_WAYLAND_SURFACE (data);
+  GdkSurface *surface = GDK_SURFACE (self);
+  
+  /* Notify app that scale changed */
+  gdk_wayland_surface_maybe_resize (surface,
+                                    surface->width, surface->height,
+                                    ceil (scale / 120.0));
+}
+
+static const struct wp_fractional_scale_v1_listener fractional_scale_listener = {
+  gdk_wayland_surface_fractional_scale_preferred_scale_cb,
+};
+
 static void
 surface_enter (void              *data,
                struct wl_surface *wl_surface,
@@ -848,15 +867,23 @@ static const struct wl_surface_listener surface_listener = {
 void
 gdk_wayland_surface_create_wl_surface (GdkSurface *surface)
 {
-  GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
+  GdkWaylandSurface *self = GDK_WAYLAND_SURFACE (surface);
   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
   struct wl_surface *wl_surface;
 
   wl_surface = wl_compositor_create_surface (display_wayland->compositor);
-  wl_proxy_set_queue ((struct wl_proxy *) wl_surface, impl->event_queue);
-  wl_surface_add_listener (wl_surface, &surface_listener, surface);
+  wl_proxy_set_queue ((struct wl_proxy *) wl_surface, self->event_queue);
+  wl_surface_add_listener (wl_surface, &surface_listener, self);
+  if (display_wayland->fractional_scale)
+    {
+      self->display_server.fractional_scale =
+          wp_fractional_scale_manager_v1_get_fractional_scale (display_wayland->fractional_scale,
+                                                               wl_surface);
+      wp_fractional_scale_v1_add_listener (self->display_server.fractional_scale,
+                                           &fractional_scale_listener, self);
+    }
 
-  impl->display_server.wl_surface = wl_surface;
+  self->display_server.wl_surface = wl_surface;
 }
 
 static void
@@ -1024,6 +1051,8 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
             impl->initial_configure_received = FALSE;
         }
 
+      g_clear_pointer (&impl->display_server.fractional_scale, wp_fractional_scale_v1_destroy);
+
       g_clear_pointer (&impl->display_server.wl_surface, wl_surface_destroy);
 
       g_slist_free (impl->display_server.outputs);
index e5ca9ae02ff6a386adcffe47acc6c9ece214d185..67d16e01f5675c17c61efdf8cb94afc94ed4bf0c 100644 (file)
@@ -65,6 +65,7 @@ proto_sources = [
   ['xdg-output', 'unstable', 'v1', ],
   ['idle-inhibit', 'unstable', 'v1', ],
   ['xdg-activation', 'staging', 'v1', ],
+  ['fractional-scale', 'staging', 'v1', ],
 ]
 
 gdk_wayland_gen_headers = []