diff --git a/gdk/x11/gdkscreen-x11.c b/gdk/x11/gdkscreen-x11.c index cddb3de853..c615098e4a 100644 --- a/gdk/x11/gdkscreen-x11.c +++ b/gdk/x11/gdkscreen-x11.c @@ -1090,6 +1090,27 @@ _gdk_x11_screen_new (GdkDisplay *display, return screen; } +void +_gdk_x11_screen_set_window_scale (GdkX11Screen *x11_screen, + int scale) +{ + GList *toplevels, *l; + + if (x11_screen->window_scale == scale) + return; + + x11_screen->window_scale = scale; + + toplevels = gdk_screen_get_toplevel_windows (GDK_SCREEN (x11_screen)); + + for (l = toplevels; l != NULL; l = l->next) + { + GdkWindow *window = l->data; + + _gdk_x11_window_set_window_scale (window, scale); + } +} + /* * It is important that we first request the selection * notification, and then setup the initial state of diff --git a/gdk/x11/gdkscreen-x11.h b/gdk/x11/gdkscreen-x11.h index 7b276578bd..f37b61a542 100644 --- a/gdk/x11/gdkscreen-x11.h +++ b/gdk/x11/gdkscreen-x11.h @@ -121,6 +121,8 @@ void _gdk_x11_screen_get_edge_monitors (GdkScreen *screen, gint *bottom, gint *left, gint *right); +void _gdk_x11_screen_set_window_scale (GdkX11Screen *x11_screen, + int scale); G_END_DECLS diff --git a/gdk/x11/gdksettings.c b/gdk/x11/gdksettings.c index 5f4119fd7d..b86a17ebad 100644 --- a/gdk/x11/gdksettings.c +++ b/gdk/x11/gdksettings.c @@ -59,7 +59,11 @@ static const struct { {"Gtk/ShellShowsMenubar", "gtk-shell-shows-menubar"}, {"Gtk/EnablePrimaryPaste", "gtk-enable-primary-paste"}, {"Gtk/RecentFilesMaxAge", "gtk-recent-files-max-age"}, - {"Gtk/RecentFilesEnabled", "gtk-recent-files-enabled"} + {"Gtk/RecentFilesEnabled", "gtk-recent-files-enabled"}, + + /* These are here in order to be recognized, but are not sent to + gtk as they are handled internally by gdk: */ + {"Gdk/WindowScalingFactor", "gdk-window-scaling-factor"} }; static const char * diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index 4141d33d64..6f8527d412 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -1821,8 +1821,6 @@ window_x11_resize (GdkWindow *window, window->resize_count += 1; } } - - _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl)); } static inline void @@ -1891,6 +1889,73 @@ gdk_window_x11_move_resize (GdkWindow *window, } } +static void +set_scale_recursive (GdkWindow *window, int scale) +{ + GdkWindow *child; + GList *l; + + for (l = window->children; l; l = l->next) + { + child = l->data; + + if (child->impl != window->impl) + _gdk_x11_window_set_window_scale (child, scale); + else + set_scale_recursive (child, scale); + } +} + +void +_gdk_x11_window_set_window_scale (GdkWindow *window, + int scale) +{ + GdkWindowImplX11 *impl; + GdkToplevelX11 *toplevel; + GdkWindowHints geom_mask; + + if (window->window_type == GDK_WINDOW_OFFSCREEN) + return; + + impl = GDK_WINDOW_IMPL_X11 (window->impl); + + impl->window_scale = scale; + + toplevel = _gdk_x11_window_get_toplevel (window); + if (toplevel && window->window_type != GDK_WINDOW_FOREIGN) + { + /* These are affected by window scale: */ + geom_mask = toplevel->last_geometry_hints_mask & + (GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE | GDK_HINT_BASE_SIZE | GDK_HINT_RESIZE_INC); + if (geom_mask) + gdk_window_set_geometry_hints (window, + &toplevel->last_geometry_hints, + geom_mask); + } + + if (window->window_type == GDK_WINDOW_FOREIGN) + XMoveWindow (GDK_WINDOW_XDISPLAY (window), + GDK_WINDOW_XID (window), + (window->x + window->parent->abs_x) * impl->window_scale, + (window->y + window->parent->abs_y) * impl->window_scale); + else if (WINDOW_IS_TOPLEVEL(window)) + XResizeWindow (GDK_WINDOW_XDISPLAY (window), + GDK_WINDOW_XID (window), + window->width * impl->window_scale, + window->height * impl->window_scale); + else + XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window), + GDK_WINDOW_XID (window), + (window->x + window->parent->abs_x) * impl->window_scale, + (window->y + window->parent->abs_y) * impl->window_scale, + window->width * impl->window_scale, + window->height * impl->window_scale); + + gdk_window_invalidate_rect (window, NULL, TRUE); + + set_scale_recursive (window, scale); +} + static gboolean gdk_window_x11_reparent (GdkWindow *window, GdkWindow *new_parent, @@ -2401,10 +2466,18 @@ gdk_x11_window_set_geometry_hints (GdkWindow *window, { GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl); XSizeHints size_hints; - + GdkToplevelX11 *toplevel; + if (GDK_WINDOW_DESTROYED (window) || !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window)) return; + + toplevel = _gdk_x11_window_get_toplevel (window); + if (toplevel) + { + toplevel->last_geometry_hints = *geometry; + toplevel->last_geometry_hints_mask = geom_mask; + } size_hints.flags = 0; diff --git a/gdk/x11/gdkwindow-x11.h b/gdk/x11/gdkwindow-x11.h index 5a9b31d2b7..1c50cf4861 100644 --- a/gdk/x11/gdkwindow-x11.h +++ b/gdk/x11/gdkwindow-x11.h @@ -152,7 +152,10 @@ struct _GdkToplevelX11 * that might not even be part of this app */ Window focus_window; - + + GdkWindowHints last_geometry_hints_mask; + GdkGeometry last_geometry_hints; + #ifdef HAVE_XSYNC XID update_counter; XID extended_update_counter; @@ -185,6 +188,8 @@ void _gdk_x11_window_tmp_reset_parent_bg (GdkWindow *window); GdkCursor *_gdk_x11_window_get_cursor (GdkWindow *window); void _gdk_x11_window_update_size (GdkWindowImplX11 *impl); +void _gdk_x11_window_set_window_scale (GdkWindow *window, + int scale); G_END_DECLS diff --git a/gdk/x11/xsettings-client.c b/gdk/x11/xsettings-client.c index 41bfaeb800..4cafb9339e 100644 --- a/gdk/x11/xsettings-client.c +++ b/gdk/x11/xsettings-client.c @@ -68,6 +68,9 @@ gdk_xsettings_notify (GdkX11Screen *x11_screen, { GdkEvent new_event; + if (!g_str_has_prefix (name, "gtk-")) + return; + new_event.type = GDK_SETTING; new_event.setting.window = gdk_screen_get_root_window (GDK_SCREEN (x11_screen)); new_event.setting.send_event = FALSE; @@ -406,6 +409,7 @@ read_settings (GdkX11Screen *x11_screen, int result; GHashTable *old_list = x11_screen->xsettings; + GValue value = G_VALUE_INIT; x11_screen->xsettings = NULL; @@ -443,6 +447,12 @@ read_settings (GdkX11Screen *x11_screen, notify_changes (x11_screen, old_list); if (old_list) g_hash_table_unref (old_list); + + g_value_init (&value, G_TYPE_INT); + if (gdk_screen_get_setting (GDK_SCREEN (x11_screen), + "gdk-window-scaling-factor", &value)) + _gdk_x11_screen_set_window_scale (x11_screen, + g_value_get_int (&value)); } static Atom