diff options
author | Owen W. Taylor <otaylor@fishsoup.net> | 2014-07-11 16:42:38 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2014-07-13 15:35:23 -0400 |
commit | fc6e2cc4b27403707bf2a9f4717442842914e626 (patch) | |
tree | 5d911997ef8c1ba99f257ab43198ec8fc4bc9ddc /gdk | |
parent | cef6f34fb7585fc423ec999822d515d6da0e6d6f (diff) | |
download | gtk+-fc6e2cc4b27403707bf2a9f4717442842914e626.tar.gz |
Handle resolution changes in the GDK backend code
gdk_x11_display_set_window_scale() affects the interpretation of the
Xft/DPI XSETTING - it is substituted inside GDK with the value of
Gdk/UnscaledDPI xsetting. However, this change is not propagated to
GTK+ and from GTK+ back to gdk_screen_set_resolution() until the
main loop is run.
Fix this by handling the screen resolution directly in gdk/x11.
This requires duplication of code between GDK and GTK+ since we still
have to handle DPI in GTK+ in the case that GdkSettings:gtk-xft-dpi
is set by the application.
https://bugzilla.gnome.org/show_bug.cgi?id=733076
Diffstat (limited to 'gdk')
-rw-r--r-- | gdk/gdkinternals.h | 2 | ||||
-rw-r--r-- | gdk/gdkscreen.c | 25 | ||||
-rw-r--r-- | gdk/gdkscreenprivate.h | 1 | ||||
-rw-r--r-- | gdk/quartz/gdkscreen-quartz.c | 4 | ||||
-rw-r--r-- | gdk/wayland/gdkscreen-wayland.c | 15 | ||||
-rw-r--r-- | gdk/x11/xsettings-client.c | 37 |
6 files changed, 82 insertions, 2 deletions
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 @@ -462,6 +462,31 @@ gdk_screen_set_resolution (GdkScreen *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(<GtkSetting>, "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; + if (screen->resolution != dpi) { screen->resolution = dpi; 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)) |