diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h index 5ce3deb488..7aefedb253 100644 --- a/gdk/wayland/gdkprivate-wayland.h +++ b/gdk/wayland/gdkprivate-wayland.h @@ -164,6 +164,8 @@ void _gdk_wayland_screen_add_output (GdkScreen *screen, struct wl_output *output); void _gdk_wayland_screen_remove_output (GdkScreen *screen, guint32 id); +int _gdk_wayland_screen_get_output_refresh_rate (GdkScreen *screen, + struct wl_output *output); void _gdk_wayland_display_manager_add_display (GdkDisplayManager *manager, GdkDisplay *display); diff --git a/gdk/wayland/gdkscreen-wayland.c b/gdk/wayland/gdkscreen-wayland.c index 7153eaf7b1..5d621bbb98 100644 --- a/gdk/wayland/gdkscreen-wayland.c +++ b/gdk/wayland/gdkscreen-wayland.c @@ -87,6 +87,7 @@ struct _GdkWaylandMonitor int height_mm; char * output_name; char * manufacturer; + int refresh_rate; }; G_DEFINE_TYPE (GdkWaylandScreen, _gdk_wayland_screen, GDK_TYPE_SCREEN) @@ -917,6 +918,7 @@ output_handle_mode(void *data, monitor->geometry.width = width; monitor->geometry.height = height; + monitor->refresh_rate = refresh; g_signal_emit_by_name (monitor->screen, "monitors-changed"); update_screen_size (monitor->screen); @@ -965,3 +967,21 @@ _gdk_wayland_screen_remove_output (GdkScreen *screen, } } } + +int +_gdk_wayland_screen_get_output_refresh_rate (GdkScreen *screen, + struct wl_output *output) +{ + GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen); + int i; + + for (i = 0; i < screen_wayland->monitors->len; i++) + { + GdkWaylandMonitor *monitor = screen_wayland->monitors->pdata[i]; + + if (monitor->output == output) + return monitor->refresh_rate; + } + + return 0; +} diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c index e1a490ecbf..32c23e7620 100644 --- a/gdk/wayland/gdkwindow-wayland.c +++ b/gdk/wayland/gdkwindow-wayland.c @@ -96,6 +96,9 @@ struct _GdkWindowImplWayland GdkCursor *cursor; + /* The wl_outputs that this window currently touches */ + GSList *outputs; + struct wl_surface *surface; struct wl_shell_surface *shell_surface; unsigned int mapped : 1; @@ -267,6 +270,7 @@ frame_callback (void *data, { GdkWindow *window = data; GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window)); GdkFrameClock *clock = gdk_window_get_frame_clock (window); GdkFrameTimings *timings; @@ -279,6 +283,17 @@ frame_callback (void *data, if (timings == NULL) return; + timings->refresh_interval = 16667; /* default to 1/60th of a second */ + if (impl->outputs) + { + /* We pick a random output out of the outputs that the window touches + * The rate here is in milli-hertz */ + int refresh_rate = _gdk_wayland_screen_get_output_refresh_rate (wayland_display->screen, + impl->outputs->data); + if (refresh_rate != 0) + timings->refresh_interval = G_GINT64_CONSTANT(1000000000) / refresh_rate; + } + timings->complete = TRUE; #ifdef G_ENABLE_DEBUG @@ -712,6 +727,28 @@ gdk_wayland_window_map (GdkWindow *window) } } +static void +surface_enter (void *data, + struct wl_surface *wl_surface, + struct wl_output *output) +{ + GdkWindow *window = GDK_WINDOW (data); + GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + + impl->outputs = g_slist_prepend (impl->outputs, output); +} + +static void +surface_leave (void *data, + struct wl_surface *wl_surface, + struct wl_output *output) +{ + GdkWindow *window = GDK_WINDOW (data); + GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + + impl->outputs = g_slist_remove (impl->outputs, output); +} + static void shell_surface_handle_configure(void *data, struct wl_shell_surface *shell_surface, @@ -760,6 +797,11 @@ shell_surface_ping (void *data, wl_shell_surface_pong(shell_surface, serial); } +static const struct wl_surface_listener surface_listener = { + surface_enter, + surface_leave +}; + static const struct wl_shell_surface_listener shell_surface_listener = { shell_surface_ping, shell_surface_handle_configure, @@ -775,6 +817,8 @@ gdk_wayland_window_create_surface (GdkWindow *window) impl->surface = wl_compositor_create_surface (display_wayland->compositor); wl_surface_set_user_data(impl->surface, window); + wl_surface_add_listener(impl->surface, + &surface_listener, window); } static void @@ -838,6 +882,9 @@ gdk_wayland_window_hide_surface (GdkWindow *window, { wl_surface_destroy(impl->surface); impl->surface = NULL; + + g_slist_free (impl->outputs); + impl->outputs = NULL; } impl->shell_surface = NULL; cairo_surface_destroy(impl->server_surface);