diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h index a2c4e53a51..f58ccb0084 100644 --- a/gdk/gdkinternals.h +++ b/gdk/gdkinternals.h @@ -345,6 +345,8 @@ gboolean _gdk_window_update_viewable (GdkWindow *window); void _gdk_window_process_updates_recurse (GdkWindow *window, cairo_region_t *expose_region); +void _gdk_screen_set_resolution (GdkScreen *screen, + gdouble dpi); void _gdk_screen_close (GdkScreen *screen); /***************************************** diff --git a/gdk/gdkscreen.c b/gdk/gdkscreen.c index e2cbfb7d0d..cc170c5b4b 100644 --- a/gdk/gdkscreen.c +++ b/gdk/gdkscreen.c @@ -459,6 +459,31 @@ gdk_screen_set_resolution (GdkScreen *screen, { g_return_if_fail (GDK_IS_SCREEN (screen)); + if (dpi < 0) + dpi = -1.0; + + screen->resolution_set = TRUE; + + if (screen->resolution != dpi) + { + screen->resolution = dpi; + + g_object_notify (G_OBJECT (screen), "resolution"); + } +} + +/* Just like gdk_screen_set_resolution(), but doesn't change + * screen->resolution. This is us to allow us to distinguish + * resolution changes that the backend picks up from resolution + * changes made through the public API - perhaps using + * g_object_set(, "gtk-xft-dpi", ...); + */ +void +_gdk_screen_set_resolution (GdkScreen *screen, + gdouble dpi) +{ + g_return_if_fail (GDK_IS_SCREEN (screen)); + if (dpi < 0) dpi = -1.0; diff --git a/gdk/gdkscreenprivate.h b/gdk/gdkscreenprivate.h index 23cf1bdae2..15c405604c 100644 --- a/gdk/gdkscreenprivate.h +++ b/gdk/gdkscreenprivate.h @@ -35,6 +35,7 @@ struct _GdkScreen cairo_font_options_t *font_options; gdouble resolution; /* pixels/points scale factor for fonts */ + guint resolution_set : 1; /* resolution set through public API */ guint closed : 1; }; diff --git a/gdk/quartz/gdkscreen-quartz.c b/gdk/quartz/gdkscreen-quartz.c index e4d409023f..ca655a5a6a 100644 --- a/gdk/quartz/gdkscreen-quartz.c +++ b/gdk/quartz/gdkscreen-quartz.c @@ -75,8 +75,8 @@ gdk_quartz_screen_init (GdkQuartzScreen *quartz_screen) NSScreen *nsscreen; nsscreen = [[NSScreen screens] objectAtIndex:0]; - gdk_screen_set_resolution (screen, - 72.0 * [nsscreen userSpaceScaleFactor]); + _gdk_screen_set_resolution (screen, + 72.0 * [nsscreen userSpaceScaleFactor]); gdk_quartz_screen_calculate_layout (quartz_screen); diff --git a/gdk/wayland/gdkscreen-wayland.c b/gdk/wayland/gdkscreen-wayland.c index 4cbc51e493..baa1bc888c 100644 --- a/gdk/wayland/gdkscreen-wayland.c +++ b/gdk/wayland/gdkscreen-wayland.c @@ -477,7 +477,22 @@ update_xft_settings (GdkScreen *screen) if (screen_wayland->xft_settings.dpi != xft_settings.dpi) { + double dpi = xft_settings.dpi / 1024.; + const char *scale_env; + double scale; + screen_wayland->xft_settings.dpi = xft_settings.dpi; + + scale_env = g_getenv ("GDK_DPI_SCALE"); + if (scale_env) + { + scale = g_ascii_strtod (scale_env, NULL); + if (scale != 0 && dpi > 0) + dpi *= scale; + } + + _gdk_screen_set_resolution (screen, dpi); + notify_setting (screen, "gtk-xft-dpi"); } } diff --git a/gdk/x11/xsettings-client.c b/gdk/x11/xsettings-client.c index 87b4addbea..f807e52880 100644 --- a/gdk/x11/xsettings-client.c +++ b/gdk/x11/xsettings-client.c @@ -402,6 +402,8 @@ static void read_settings (GdkX11Screen *x11_screen, gboolean do_notify) { + GdkScreen *screen = GDK_SCREEN (x11_screen); + Atom type; int format; unsigned long n_items; @@ -466,6 +468,41 @@ read_settings (GdkX11Screen *x11_screen, g_hash_table_unref (old_list); g_value_init (&value, G_TYPE_INT); + + if (!screen->resolution_set) + { + /* This code is duplicated with gtksettings.c:settings_update_resolution(). + * The update of the screen resolution needs to happen immediately when + * gdk_x11_display_set_window_scale() is called, and not wait for events + * to be processed, so we can't always handling it in gtksettings.c. + * But we can't always handle it here because the DPI can be set through + * GtkSettings, which we don't have access to. + */ + int dpi_int = 0; + double dpi; + const char *scale_env; + double scale; + + if (gdk_screen_get_setting (GDK_SCREEN (x11_screen), + "gtk-xft-dpi", &value)) + dpi_int = g_value_get_int (&value); + + if (dpi_int > 0) + dpi = dpi_int / 1024.; + else + dpi = -1.; + + scale_env = g_getenv ("GDK_DPI_SCALE"); + if (scale_env) + { + scale = g_ascii_strtod (scale_env, NULL); + if (scale != 0 && dpi > 0) + dpi *= scale; + } + + _gdk_screen_set_resolution (screen, dpi); + } + if (!x11_screen->fixed_window_scale && gdk_screen_get_setting (GDK_SCREEN (x11_screen), "gdk-window-scaling-factor", &value)) diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c index 64912ceeaf..7549c8d9ab 100644 --- a/gtk/gtksettings.c +++ b/gtk/gtksettings.c @@ -2944,24 +2944,31 @@ settings_update_resolution (GtkSettings *settings) const char *scale_env; double scale; - g_object_get (settings, - "gtk-xft-dpi", &dpi_int, - NULL); - - if (dpi_int > 0) - dpi = dpi_int / 1024.; - else - dpi = -1.; - - scale_env = g_getenv ("GDK_DPI_SCALE"); - if (scale_env) + /* We handle this here in the case that the dpi was set on the GtkSettings + * object by the application. Other cases are handled in + * xsettings-client.c:read-settings(). See comment there for the rationale. + */ + if (priv->property_values[PROP_XFT_DPI - 1].source == GTK_SETTINGS_SOURCE_APPLICATION) { - scale = g_ascii_strtod (scale_env, NULL); - if (scale != 0 && dpi > 0) - dpi *= scale; - } + g_object_get (settings, + "gtk-xft-dpi", &dpi_int, + NULL); - gdk_screen_set_resolution (priv->screen, dpi); + if (dpi_int > 0) + dpi = dpi_int / 1024.; + else + dpi = -1.; + + scale_env = g_getenv ("GDK_DPI_SCALE"); + if (scale_env) + { + scale = g_ascii_strtod (scale_env, NULL); + if (scale != 0 && dpi > 0) + dpi *= scale; + } + + gdk_screen_set_resolution (priv->screen, dpi); + } } static void