[gtk+/wip/window-scales2: 17/40] x11: Support the Gdk/WindowScalingFactor xsetting



commit d89a98e31e6105a2194e41524d80c577cb014067
Author: Alexander Larsson <alexl redhat com>
Date:   Thu Jun 27 22:45:40 2013 +0200

    x11: Support the Gdk/WindowScalingFactor xsetting
    
    This xsetting can be used to tell Gtk to use a specific window
    scaling for the screen.

 gdk/x11/gdkscreen-x11.c    |   21 ++++++++++++
 gdk/x11/gdkscreen-x11.h    |    2 +
 gdk/x11/gdksettings.c      |    6 +++-
 gdk/x11/gdkwindow-x11.c    |   79 ++++++++++++++++++++++++++++++++++++++++++--
 gdk/x11/gdkwindow-x11.h    |    7 +++-
 gdk/x11/xsettings-client.c |   10 +++++
 6 files changed, 120 insertions(+), 5 deletions(-)
---
diff --git a/gdk/x11/gdkscreen-x11.c b/gdk/x11/gdkscreen-x11.c
index cddb3de..c615098 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 7b27657..f37b61a 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 5f4119f..b86a17e 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 4141d33..6f8527d 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 5a9b31d..1c50cf4 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 41bfaeb..4cafb93 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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]