diff --git a/gdk/mir/gdkmir-private.h b/gdk/mir/gdkmir-private.h index 84051a7ed7..53f5a66251 100644 --- a/gdk/mir/gdkmir-private.h +++ b/gdk/mir/gdkmir-private.h @@ -89,6 +89,8 @@ void _gdk_mir_window_impl_set_surface_state (GdkMirWindowImpl *impl, MirSurfaceS void _gdk_mir_window_impl_set_surface_type (GdkMirWindowImpl *impl, MirSurfaceType type); +void _gdk_mir_window_set_surface_output (GdkWindow *window, gdouble scale); + void _gdk_mir_window_impl_set_cursor_state (GdkMirWindowImpl *impl, gdouble x, gdouble y, gboolean cursor_inside, guint button_state); void _gdk_mir_window_impl_get_cursor_state (GdkMirWindowImpl *impl, gdouble *x, gdouble *y, gboolean *cursor_inside, guint *button_state); diff --git a/gdk/mir/gdkmireventsource.c b/gdk/mir/gdkmireventsource.c index 458228a246..b829c8f0ac 100644 --- a/gdk/mir/gdkmireventsource.c +++ b/gdk/mir/gdkmireventsource.c @@ -544,6 +544,13 @@ handle_close_event (GdkWindow *window) gdk_window_destroy_notify (window); } +static void +handle_surface_output_event (GdkWindow *window, + const MirSurfaceOutputEvent *event) +{ + _gdk_mir_window_set_surface_output (window, mir_surface_output_event_get_scale (event)); +} + typedef struct { GdkWindow *window; @@ -598,6 +605,9 @@ gdk_mir_event_source_queue_event (GdkDisplay *display, case mir_event_type_close_surface: handle_close_event (window); break; + case mir_event_type_surface_output: + handle_surface_output_event (window, mir_event_get_surface_output_event (event)); + break; default: g_warning ("Ignoring unknown Mir event %d", mir_event_get_type (event)); // FIXME? diff --git a/gdk/mir/gdkmirwindowimpl.c b/gdk/mir/gdkmirwindowimpl.c index 1a19ec9b61..3d234cd3b1 100644 --- a/gdk/mir/gdkmirwindowimpl.c +++ b/gdk/mir/gdkmirwindowimpl.c @@ -16,6 +16,7 @@ */ #include +#include #include "config.h" @@ -65,6 +66,7 @@ struct _GdkMirWindowImpl /* Surface being rendered to (only exists when window visible) */ MirSurface *surface; + MirBufferStream *buffer_stream; /* Cairo context for current frame */ cairo_surface_t *cairo_surface; @@ -80,6 +82,8 @@ struct _GdkMirWindowImpl /* TRUE if cursor is inside this window */ gboolean cursor_inside; + + gint output_scale; }; struct _GdkMirWindowImplClass @@ -91,6 +95,14 @@ G_DEFINE_TYPE (GdkMirWindowImpl, gdk_mir_window_impl, GDK_TYPE_WINDOW_IMPL) static cairo_surface_t *gdk_mir_window_impl_ref_cairo_surface (GdkWindow *window); +static void +drop_cairo_surface (GdkWindow *window) +{ + GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl); + + g_clear_pointer (&impl->cairo_surface, cairo_surface_destroy); +} + GdkWindowImpl * _gdk_mir_window_impl_new (void) { @@ -144,6 +156,7 @@ gdk_mir_window_impl_init (GdkMirWindowImpl *impl) { impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL; impl->surface_state = mir_surface_state_unknown; + impl->output_scale = 1; } static void @@ -356,6 +369,7 @@ ensure_surface_full (GdkWindow *window, impl->has_rect ? &impl->rect : NULL, impl->has_rect ? impl->edge : mir_edge_attachment_any, buffer_usage); + impl->buffer_stream = mir_surface_get_buffer_stream (impl->surface); /* FIXME: can't make an initial resize event */ // MirEvent *resize_event; @@ -448,6 +462,7 @@ gdk_mir_window_impl_ref_cairo_surface (GdkWindow *window) if (window->gl_paint_context) { cairo_surface = cairo_image_surface_create (pixel_format, window->width, window->height); + cairo_surface_set_device_scale (cairo_surface, (double) impl->output_scale, (double) impl->output_scale); } else if (impl->visible) { @@ -496,6 +511,7 @@ gdk_mir_window_impl_ref_cairo_surface (GdkWindow *window) region.width, region.height, region.stride); + cairo_surface_set_device_scale (cairo_surface, (double) impl->output_scale, (double) impl->output_scale); } else cairo_surface = cairo_image_surface_create (pixel_format, 0, 0); @@ -1344,8 +1360,8 @@ static gint gdk_mir_window_impl_get_scale_factor (GdkWindow *window) { //g_printerr ("gdk_mir_window_impl_get_scale_factor window=%p\n", window); - /* Don't support monitor scaling */ - return 1; + GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl); + return impl->output_scale; } static void @@ -1603,6 +1619,30 @@ gdk_mir_window_get_mir_surface (GdkWindow *window) return impl->surface; } +void +_gdk_mir_window_set_surface_output (GdkWindow *window, gdouble scale) +{ + // g_printerr ("_gdk_mir_window_impl_set_surface_output impl=%p\n", impl); + GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl); + GdkRectangle area = {0, 0, window->width, window->height}; + cairo_region_t *region; + gint new_scale = (gint) round (scale); + + if (impl->output_scale != new_scale) + { + impl->output_scale = new_scale; + + drop_cairo_surface (window); + + if (impl->buffer_stream) + mir_buffer_stream_set_scale (impl->buffer_stream, (float) new_scale); + + region = cairo_region_create_rectangle (&area); + _gdk_window_invalidate_for_expose (window, region); + cairo_region_destroy (region); + } +} + static void gdk_mir_window_impl_class_init (GdkMirWindowImplClass *klass) {