[gtk+/wip/window-scales: 37/69] wayland: Support gdk_window_get_scale



commit 42342d73b5ebf1bc73e501225a00af9c9b04de0a
Author: Alexander Larsson <alexl redhat com>
Date:   Tue Jun 4 11:39:36 2013 +0200

    wayland: Support gdk_window_get_scale
    
    We track the list of outputs each window is on, and set the
    scale to the largest scale value of the outputs. Any time the scale
    changes we also emit a configure event.

 gdk/wayland/gdkwindow-wayland.c |   96 +++++++++++++++++++++++++++++++++++----
 1 files changed, 86 insertions(+), 10 deletions(-)
---
diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c
index 1e7eba1..f872049 100644
--- a/gdk/wayland/gdkwindow-wayland.c
+++ b/gdk/wayland/gdkwindow-wayland.c
@@ -145,6 +145,7 @@ struct _GdkWindowImplWayland
 
   gboolean use_custom_surface;
 
+  guint32 scale;
   gboolean pending_commit;
   gint64 pending_frame_counter;
 };
@@ -154,11 +155,15 @@ struct _GdkWindowImplWaylandClass
   GdkWindowImplClass parent_class;
 };
 
+static void gdk_wayland_window_configure (GdkWindow *window,
+                                         int width, int height, int edges);
+
 G_DEFINE_TYPE (GdkWindowImplWayland, _gdk_window_impl_wayland, GDK_TYPE_WINDOW_IMPL)
 
 static void
 _gdk_window_impl_wayland_init (GdkWindowImplWayland *impl)
 {
+  impl->scale = 1;
 }
 
 void
@@ -391,6 +396,7 @@ typedef struct _GdkWaylandCairoSurfaceData {
   struct wl_buffer *buffer;
   GdkWaylandDisplay *display;
   int32_t width, height;
+  uint32_t scale;
   gboolean busy;
 } GdkWaylandCairoSurfaceData;
 
@@ -419,6 +425,44 @@ on_frame_clock_after_paint (GdkFrameClock *clock,
   data->busy = TRUE;
 }
 
+static void
+window_update_scale (GdkWindow *window)
+{
+  GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
+  GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
+  guint32 scale;
+  GSList *l;
+
+  scale = 1;
+  for (l = impl->outputs; l != NULL; l = l->next)
+    {
+      guint32 output_scale =
+       _gdk_wayland_screen_get_output_scale (wayland_display->screen,
+                                             l->data);
+      scale = MAX (scale, output_scale);
+    }
+
+#ifndef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
+  /* Don't announce a scale if we can't support it */
+  scale = 1;
+#endif
+
+  if (scale != impl->scale)
+    {
+      impl->scale = scale;
+
+      /* Notify app that scale changed */
+      gdk_wayland_window_configure (window, window->width, window->height, impl->resize_edges);
+    }
+}
+
+static void
+on_monitors_changed (GdkScreen *screen,
+                    GdkWindow *window)
+{
+  window_update_scale (window);
+}
+
 void
 _gdk_wayland_display_create_window_impl (GdkDisplay    *display,
                                         GdkWindow     *window,
@@ -449,6 +493,9 @@ _gdk_wayland_display_create_window_impl (GdkDisplay    *display,
 
   g_object_ref (window);
 
+  /* More likely to be right than just assuming 1 */
+  impl->scale = gdk_screen_get_monitor_scale_factor (screen, 0);
+
   impl->title = NULL;
 
   switch (GDK_WINDOW_TYPE (window))
@@ -477,6 +524,9 @@ _gdk_wayland_display_create_window_impl (GdkDisplay    *display,
                     G_CALLBACK (on_frame_clock_before_paint), window);
   g_signal_connect (frame_clock, "after-paint",
                     G_CALLBACK (on_frame_clock_after_paint), window);
+
+  g_signal_connect (screen, "monitors-changed",
+                    G_CALLBACK (on_monitors_changed), window);
 }
 
 static void
@@ -528,6 +578,8 @@ gdk_wayland_window_attach_image (GdkWindow *window)
 
   /* Attach this new buffer to the surface */
   wl_surface_attach (impl->surface, data->buffer, dx, dy);
+  wl_surface_set_buffer_scale (impl->surface, data->scale);
+
   impl->pending_commit = TRUE;
 }
 
@@ -609,7 +661,7 @@ static const struct wl_buffer_listener buffer_listener = {
 
 static cairo_surface_t *
 gdk_wayland_create_cairo_surface (GdkWaylandDisplay *display,
-                                 int width, int height)
+                                 int width, int height, guint scale)
 {
   GdkWaylandCairoSurfaceData *data;
   cairo_surface_t *surface = NULL;
@@ -621,29 +673,34 @@ gdk_wayland_create_cairo_surface (GdkWaylandDisplay *display,
   data->buffer = NULL;
   data->width = width;
   data->height = height;
+  data->scale = scale;
   data->busy = FALSE;
 
   stride = width * 4;
 
   data->pool = _create_shm_pool (display->shm,
-                                 width, height,
+                                 width*scale, height*scale,
                                  &data->buf_length,
                                  &data->buf);
 
   data->buffer = wl_shm_pool_create_buffer (data->pool, 0,
-                                            width, height,
-                                            stride, WL_SHM_FORMAT_ARGB8888);
+                                            width*scale, height*scale,
+                                            stride*scale, WL_SHM_FORMAT_ARGB8888);
   wl_buffer_add_listener (data->buffer, &buffer_listener, data);
 
   surface = cairo_image_surface_create_for_data (data->buf,
                                                  CAIRO_FORMAT_ARGB32,
-                                                 width,
-                                                 height,
-                                                 stride);
+                                                 width*scale,
+                                                 height*scale,
+                                                 stride*scale);
 
   cairo_surface_set_user_data (surface, &gdk_wayland_cairo_key,
                                data, gdk_wayland_cairo_surface_destroy);
 
+#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
+  cairo_surface_set_device_scale (surface, scale, scale);
+#endif
+
   status = cairo_surface_status (surface);
   if (status != CAIRO_STATUS_SUCCESS)
     {
@@ -665,8 +722,9 @@ gdk_wayland_window_ensure_cairo_surface (GdkWindow *window)
 
       impl->cairo_surface =
        gdk_wayland_create_cairo_surface (display_wayland,
-                                     impl->wrapper->width,
-                                     impl->wrapper->height);
+                                         impl->wrapper->width,
+                                         impl->wrapper->height,
+                                         impl->scale);
     }
 }
 
@@ -727,7 +785,7 @@ gdk_wayland_window_configure (GdkWindow *window,
 
   display = gdk_window_get_display (window);
 
-  /* TODO: Only generate a configure event if width or height have actually
+  /* TODO: Only generate a configure event if width/height/scale have actually
    * changed?
    */
   event = gdk_event_new (GDK_CONFIGURE);
@@ -841,6 +899,8 @@ surface_enter (void *data,
   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
 
   impl->outputs = g_slist_prepend (impl->outputs, output);
+
+  window_update_scale (window);
 }
 
 static void
@@ -852,8 +912,11 @@ surface_leave (void *data,
   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
 
   impl->outputs = g_slist_remove (impl->outputs, output);
+
+  window_update_scale (window);
 }
 
+
 static void
 shell_surface_handle_configure(void *data,
                                struct wl_shell_surface *shell_surface,
@@ -1905,6 +1968,18 @@ gdk_wayland_window_delete_property (GdkWindow *window,
 {
 }
 
+static gint
+gdk_wayland_window_get_scale_factor (GdkWindow *window)
+{
+  GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return 1;
+
+  return impl->scale;
+}
+
+
 static void
 _gdk_window_impl_wayland_class_init (GdkWindowImplWaylandClass *klass)
 {
@@ -1991,6 +2066,7 @@ _gdk_window_impl_wayland_class_init (GdkWindowImplWaylandClass *klass)
   impl_class->get_property = gdk_wayland_window_get_property;
   impl_class->change_property = gdk_wayland_window_change_property;
   impl_class->delete_property = gdk_wayland_window_delete_property;
+  impl_class->get_scale_factor = gdk_wayland_window_get_scale_factor;
 }
 
 


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