Commit ed4fcee4 authored by Alexander Larsson's avatar Alexander Larsson

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.
parent 031cf86b
......@@ -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;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment