[metacity] libmetacity: scale window decorations on HiDPI displays As we opt out of GTK+/Clutter's HiDPI handli



commit e6cf7fd3f8edd74eadf38ff0ccf326817605850c
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Thu Mar 24 19:43:50 2016 +0200

    libmetacity: scale window decorations on HiDPI displays
    As we opt out of GTK+/Clutter's HiDPI handling, we need to apply the
    window scaling factor manually to decorations, both the geometry and
    when drawing.
    
    Based on mutter commit:
    https://git.gnome.org/browse/mutter/commit/?id=57c1078ee742d9f01e80e7fe05c88adfec4b4ac3

 libmetacity/meta-draw-op.c        |   17 +++--
 libmetacity/meta-frame-style.c    |    2 +-
 libmetacity/meta-style-info.c     |    2 +
 libmetacity/meta-theme-gtk.c      |  130 +++++++++++++++++++++------------
 libmetacity/meta-theme-metacity.c |  146 +++++++++++++++++++++++-------------
 5 files changed, 191 insertions(+), 106 deletions(-)
---
diff --git a/libmetacity/meta-draw-op.c b/libmetacity/meta-draw-op.c
index 23c3c9d..03bd305 100644
--- a/libmetacity/meta-draw-op.c
+++ b/libmetacity/meta-draw-op.c
@@ -22,6 +22,7 @@
 #include <math.h>
 
 #include "meta-draw-op-private.h"
+#include "meta-theme-impl-private.h"
 
 #define GDK_COLOR_RGBA(color)                            \
         ((guint32) (0xff                               | \
@@ -58,18 +59,22 @@ fill_env (MetaPositionExprEnv *env,
           const MetaDrawInfo  *info,
           GdkRectangle         logical_region)
 {
+  int scale;
+
+  scale = get_window_scaling_factor ();
+
   /* FIXME this stuff could be raised into draw_op_list_draw() probably
    */
   env->rect = logical_region;
   env->object_width = -1;
   env->object_height = -1;
 
-  env->left_width = info->borders.visible.left;
-  env->right_width = info->borders.visible.right;
-  env->top_height = info->borders.visible.top;
-  env->bottom_height = info->borders.visible.bottom;
-  env->frame_x_center = info->width / 2 - logical_region.x;
-  env->frame_y_center = info->height / 2 - logical_region.y;
+  env->left_width = info->borders.visible.left / scale;
+  env->right_width = info->borders.visible.right / scale;
+  env->top_height = info->borders.visible.top / scale;
+  env->bottom_height = info->borders.visible.bottom / scale;
+  env->frame_x_center = info->width / scale / 2 - logical_region.x;
+  env->frame_y_center = info->height / scale / 2 - logical_region.y;
 
   env->mini_icon_width = info->mini_icon ? gdk_pixbuf_get_width (info->mini_icon) : 0;
   env->mini_icon_height = info->mini_icon ? gdk_pixbuf_get_height (info->mini_icon) : 0;
diff --git a/libmetacity/meta-frame-style.c b/libmetacity/meta-frame-style.c
index 15bd4f5..32ee34a 100644
--- a/libmetacity/meta-frame-style.c
+++ b/libmetacity/meta-frame-style.c
@@ -303,7 +303,7 @@ meta_frame_style_apply_scale (const MetaFrameStyle *style,
                               PangoFontDescription *font_desc)
 {
   int size = pango_font_description_get_size (font_desc);
-  double scale = style->layout->title_scale;
+  double scale = style->layout->title_scale / get_window_scaling_factor ();
 
   pango_font_description_set_size (font_desc, MAX (size * scale, 1));
 }
diff --git a/libmetacity/meta-style-info.c b/libmetacity/meta-style-info.c
index e415b8c..d4af873 100644
--- a/libmetacity/meta-style-info.c
+++ b/libmetacity/meta-style-info.c
@@ -20,6 +20,7 @@
 
 #include "meta-frame-enums.h"
 #include "meta-style-info-private.h"
+#include "meta-theme-impl-private.h"
 
 static void
 add_toplevel_class (GtkStyleContext *style,
@@ -83,6 +84,7 @@ create_style_context (GtkStyleContext *parent,
   context = gtk_style_context_new ();
   gtk_style_context_set_path (context, path);
   gtk_style_context_set_parent (context, parent);
+  gtk_style_context_set_scale (context, get_window_scaling_factor ());
   gtk_widget_path_unref (path);
 
   gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (provider),
diff --git a/libmetacity/meta-theme-gtk.c b/libmetacity/meta-theme-gtk.c
index 11e5664..21f093e 100644
--- a/libmetacity/meta-theme-gtk.c
+++ b/libmetacity/meta-theme-gtk.c
@@ -287,6 +287,7 @@ meta_theme_gtk_get_frame_borders (MetaThemeImpl    *impl,
 {
   gint buttons_height;
   gint content_height;
+  gint scale;
 
   frame_layout_sync_with_style (layout, style_info, composited, flags);
 
@@ -344,6 +345,13 @@ meta_theme_gtk_get_frame_borders (MetaThemeImpl    *impl,
   borders->total.right = borders->invisible.right + borders->visible.right;
   borders->total.bottom = borders->invisible.bottom + borders->visible.bottom;
   borders->total.top = borders->invisible.top + borders->visible.top;
+
+  /* Scale geometry for HiDPI, see comment in meta_theme_gtk_draw_frame () */
+  scale = get_window_scaling_factor ();
+
+  scale_border (&borders->visible, scale);
+  scale_border (&borders->invisible, scale);
+  scale_border (&borders->total, scale);
 }
 
 static MetaButtonSpace *
@@ -479,6 +487,7 @@ meta_theme_gtk_calc_geometry (MetaThemeImpl          *impl,
   int button_y;
   int title_right_edge;
   int width, height;
+  int scale;
   int content_width, content_height;
   int button_width, button_height;
   int min_size_for_rounding;
@@ -507,16 +516,22 @@ meta_theme_gtk_calc_geometry (MetaThemeImpl          *impl,
   fgeom->width = width;
   fgeom->height = height;
 
+  /* Scale geometry for HiDPI, see comment in meta_theme_gtk_draw_frame () */
+  scale = get_window_scaling_factor ();
+
   content_width = width -
-                  borders.invisible.left - layout->gtk.frame_border.left -
-                  borders.invisible.right - layout->gtk.frame_border.right;
-  content_height = borders.visible.top - layout->gtk.frame_border.top;
+                  borders.invisible.left - layout->gtk.frame_border.left * scale -
+                  borders.invisible.right - layout->gtk.frame_border.right * scale;
+  content_height = borders.visible.top - layout->gtk.frame_border.top * scale;
 
   button_width = MAX ((gint) layout->gtk.icon_size, layout->gtk.button_min_size.width) +
                  layout->button_border.left + layout->button_border.right;
   button_height = MAX ((gint) layout->gtk.icon_size, layout->gtk.button_min_size.height) +
                   layout->button_border.top + layout->button_border.bottom;
 
+  button_width *= scale;
+  button_height *= scale;
+
   /* FIXME all this code sort of pretends that duplicate buttons
    * with the same function are allowed, but that breaks the
    * code in frames.c, so isn't really allowed right now.
@@ -571,17 +586,17 @@ meta_theme_gtk_calc_geometry (MetaThemeImpl          *impl,
 
       space_used_by_buttons = 0;
 
-      space_used_by_buttons += layout->gtk.button_margin.left /** scale*/ * n_left;
+      space_used_by_buttons += layout->gtk.button_margin.left * scale * n_left;
       space_used_by_buttons += button_width * n_left;
-      space_used_by_buttons += layout->gtk.button_margin.right /** scale*/ * n_left;
+      space_used_by_buttons += layout->gtk.button_margin.right * scale * n_left;
       space_used_by_buttons += (button_width * 0.75) * n_left_spacers;
-      space_used_by_buttons += layout->gtk.titlebar_spacing * MAX (n_left - 1, 0);
+      space_used_by_buttons += layout->gtk.titlebar_spacing * scale * MAX (n_left - 1, 0);
 
-      space_used_by_buttons += layout->gtk.button_margin.left /** scale*/ * n_right;
+      space_used_by_buttons += layout->gtk.button_margin.left * scale * n_right;
       space_used_by_buttons += button_width * n_right;
-      space_used_by_buttons += layout->gtk.button_margin.right /** scale*/ * n_right;
+      space_used_by_buttons += layout->gtk.button_margin.right * scale * n_right;
       space_used_by_buttons += (button_width * 0.75) * n_right_spacers;
-      space_used_by_buttons += layout->gtk.titlebar_spacing * MAX (n_right - 1, 0);
+      space_used_by_buttons += layout->gtk.titlebar_spacing * scale * MAX (n_right - 1, 0);
 
       if (space_used_by_buttons <= content_width)
         break; /* Everything fits, bail out */
@@ -647,12 +662,12 @@ meta_theme_gtk_calc_geometry (MetaThemeImpl          *impl,
   fgeom->n_right_buttons = n_right;
 
   /* center buttons vertically */
-  button_y = borders.invisible.top + layout->gtk.frame_border.top +
+  button_y = borders.invisible.top + layout->gtk.frame_border.top * scale +
              (content_height - button_height) / 2;
 
   /* right edge of farthest-right button */
-  x = width - borders.invisible.right - layout->gtk.frame_border.right -
-      layout->gtk.titlebar_border.right;
+  x = width - borders.invisible.right - layout->gtk.frame_border.right * scale -
+      layout->gtk.titlebar_border.right * scale;
 
   i = n_right - 1;
   while (i >= 0)
@@ -662,7 +677,7 @@ meta_theme_gtk_calc_geometry (MetaThemeImpl          *impl,
       if (x < 0) /* if we go negative, leave the buttons we don't get to as 0-width */
         break;
 
-      x -= layout->gtk.button_margin.right /** scale*/;
+      x -= layout->gtk.button_margin.right * scale;
 
       rect = right_func_rects[i];
 
@@ -684,16 +699,16 @@ meta_theme_gtk_calc_geometry (MetaThemeImpl          *impl,
           rect->clickable.height = button_height;
 
           if (i == n_right - 1)
-            rect->clickable.width += layout->gtk.frame_border.right +
-                                     layout->gtk.titlebar_border.right;
+            rect->clickable.width += layout->gtk.frame_border.right * scale +
+                                     layout->gtk.titlebar_border.right * scale;
         }
       else
         g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable));
 
-      x = rect->visible.x - layout->gtk.button_margin.left /** scale*/;
+      x = rect->visible.x - layout->gtk.button_margin.left * scale;
 
       if (i > 0)
-        x -= layout->gtk.titlebar_spacing;
+        x -= layout->gtk.titlebar_spacing * scale;
 
       --i;
     }
@@ -704,14 +719,14 @@ meta_theme_gtk_calc_geometry (MetaThemeImpl          *impl,
   /* Now x changes to be position from the left and we go through
    * the left-side buttons
    */
-  x = borders.invisible.left + layout->gtk.frame_border.left +
-      layout->gtk.titlebar_border.left;
+  x = borders.invisible.left + layout->gtk.frame_border.left * scale +
+      layout->gtk.titlebar_border.left * scale;
 
   for (i = 0; i < n_left; i++)
     {
       MetaButtonSpace *rect;
 
-      x += layout->gtk.button_margin.left /** scale*/;
+      x += layout->gtk.button_margin.left * scale;
 
       rect = left_func_rects[i];
 
@@ -730,16 +745,16 @@ meta_theme_gtk_calc_geometry (MetaThemeImpl          *impl,
       else
         g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable));
 
-      x = rect->visible.x + rect->visible.width + layout->gtk.button_margin.right /** scale*/;
+      x = rect->visible.x + rect->visible.width + layout->gtk.button_margin.right * scale;
       if (i < n_left - 1)
-        x += layout->gtk.titlebar_spacing;
+        x += layout->gtk.titlebar_spacing * scale;
       if (left_buttons_has_spacer[i])
         x += (button_width * 0.75);
     }
 
   /* Center vertically in the available content area */
   fgeom->title_rect.x = x;
-  fgeom->title_rect.y = borders.invisible.top + layout->gtk.frame_border.top +
+  fgeom->title_rect.y = borders.invisible.top + layout->gtk.frame_border.top * scale +
                         (content_height - text_height) / 2;
   fgeom->title_rect.width = title_right_edge - fgeom->title_rect.x;
   fgeom->title_rect.height = text_height;
@@ -755,7 +770,7 @@ meta_theme_gtk_calc_geometry (MetaThemeImpl          *impl,
   if (flags & META_FRAME_SHADED)
     min_size_for_rounding = 0;
   else
-    min_size_for_rounding = 5;
+    min_size_for_rounding = 5 * scale;
 
   fgeom->top_left_corner_rounded_radius = 0;
   fgeom->top_right_corner_rounded_radius = 0;
@@ -763,14 +778,14 @@ meta_theme_gtk_calc_geometry (MetaThemeImpl          *impl,
   fgeom->bottom_right_corner_rounded_radius = 0;
 
   if (borders.visible.top + borders.visible.left >= min_size_for_rounding)
-    fgeom->top_left_corner_rounded_radius = layout->top_left_corner_rounded_radius;
+    fgeom->top_left_corner_rounded_radius = layout->top_left_corner_rounded_radius * scale;
   if (borders.visible.top + borders.visible.right >= min_size_for_rounding)
-    fgeom->top_right_corner_rounded_radius = layout->top_right_corner_rounded_radius;
+    fgeom->top_right_corner_rounded_radius = layout->top_right_corner_rounded_radius * scale;
 
   if (borders.visible.bottom + borders.visible.left >= min_size_for_rounding)
-    fgeom->bottom_left_corner_rounded_radius = layout->bottom_left_corner_rounded_radius;
+    fgeom->bottom_left_corner_rounded_radius = layout->bottom_left_corner_rounded_radius * scale;
   if (borders.visible.bottom + borders.visible.right >= min_size_for_rounding)
-    fgeom->bottom_right_corner_rounded_radius = layout->bottom_right_corner_rounded_radius;
+    fgeom->bottom_right_corner_rounded_radius = layout->bottom_right_corner_rounded_radius * scale;
 }
 
 static const char *
@@ -798,6 +813,7 @@ meta_theme_gtk_draw_frame (MetaThemeImpl           *impl,
                            GdkPixbuf               *mini_icon,
                            GdkPixbuf               *icon)
 {
+  int scale;
   GtkStyleContext *context;
   GtkStateFlags state;
   MetaButtonType button_type;
@@ -806,12 +822,26 @@ meta_theme_gtk_draw_frame (MetaThemeImpl           *impl,
   GdkRectangle button_rect;
   const MetaFrameBorders *borders;
 
+  /* We opt out of GTK+ HiDPI handling, so we have to do the scaling
+   * ourselves; the nitty-gritty is a bit confusing, so here is an overview:
+   *  - the values in MetaFrameLayout are always as they appear in the theme,
+   *    i.e. unscaled
+   *  - calculated values (borders, MetaFrameGeometry) include the scale - as
+   *    the geometry is comprised of scaled decorations and the client size
+   *    which we must not scale, we don't have another option
+   *  - for drawing, we scale the canvas to have GTK+ render elements (borders,
+   *    radii, ...) at the correct scale - as a result, we have to "unscale"
+   *    the geometry again to not apply the scaling twice
+   */
+  scale = get_window_scaling_factor ();
+  cairo_scale (cr, scale, scale);
+
   borders = &fgeom->borders;
 
-  visible_rect.x = borders->invisible.left;
-  visible_rect.y = borders->invisible.top;
-  visible_rect.width = fgeom->width - borders->invisible.left - borders->invisible.right;
-  visible_rect.height = fgeom->height - borders->invisible.top - borders->invisible.bottom;
+  visible_rect.x = borders->invisible.left / scale;
+  visible_rect.y = borders->invisible.top / scale;
+  visible_rect.width = (fgeom->width - borders->invisible.left - borders->invisible.right) / scale;
+  visible_rect.height = (fgeom->height - borders->invisible.top - borders->invisible.bottom) / scale;
 
   meta_style_info_set_flags (style_info, flags);
 
@@ -826,10 +856,10 @@ meta_theme_gtk_draw_frame (MetaThemeImpl           *impl,
   if (flags & META_FRAME_FULLSCREEN)
     return;
 
-  titlebar_rect.x = visible_rect.x + borders->visible.left;
+  titlebar_rect.x = visible_rect.x + borders->visible.left / scale;
   titlebar_rect.y = visible_rect.y + style->layout->gtk.frame_border.top;
-  titlebar_rect.width = visible_rect.width - borders->visible.left - borders->visible.right;
-  titlebar_rect.height = borders->visible.top - style->layout->gtk.frame_border.top;
+  titlebar_rect.width = visible_rect.width - (borders->visible.left + borders->visible.right) / scale;
+  titlebar_rect.height = (borders->visible.top / scale) - style->layout->gtk.frame_border.top;
 
   context = style_info->styles[META_STYLE_ELEMENT_TITLEBAR];
   gtk_render_background (context, cr,
@@ -847,7 +877,7 @@ meta_theme_gtk_draw_frame (MetaThemeImpl           *impl,
       pango_layout_set_width (title_layout, -1);
       pango_layout_get_pixel_extents (title_layout, NULL, &logical);
 
-      text_width = MIN(fgeom->title_rect.width, logical.width);
+      text_width = MIN(fgeom->title_rect.width / scale, logical.width);
 
       if (text_width < logical.width)
         pango_layout_set_width (title_layout, PANGO_SCALE * text_width);
@@ -856,10 +886,10 @@ meta_theme_gtk_draw_frame (MetaThemeImpl           *impl,
       x = titlebar_rect.x + (titlebar_rect.width - text_width) / 2;
       y = titlebar_rect.y + (titlebar_rect.height - logical.height) / 2;
 
-      if (x < fgeom->title_rect.x)
-        x = fgeom->title_rect.x;
-      else if (x + text_width > fgeom->title_rect.x + fgeom->title_rect.width)
-        x = fgeom->title_rect.x + fgeom->title_rect.width - text_width;
+      if (x < fgeom->title_rect.x / scale)
+        x = fgeom->title_rect.x / scale;
+      else if (x + text_width > (fgeom->title_rect.x + fgeom->title_rect.width) / scale)
+        x = (fgeom->title_rect.x + fgeom->title_rect.width) / scale - text_width;
 
       context = style_info->styles[META_STYLE_ELEMENT_TITLE];
       gtk_render_layout (context, cr, x, y, title_layout);
@@ -879,6 +909,11 @@ meta_theme_gtk_draw_frame (MetaThemeImpl           *impl,
 
       get_button_rect (button_type, fgeom, 0, &button_rect);
 
+      button_rect.x /= scale;
+      button_rect.y /= scale;
+      button_rect.width /= scale;
+      button_rect.height /= scale;
+
       button_state = map_button_state (button_type, fgeom, 0, button_states);
 
       if (button_state == META_BUTTON_STATE_PRELIGHT)
@@ -947,7 +982,10 @@ meta_theme_gtk_draw_frame (MetaThemeImpl           *impl,
               GtkIconTheme *theme = gtk_icon_theme_get_default ();
               GtkIconInfo *info;
 
-              info = gtk_icon_theme_lookup_icon (theme, icon_name, style->layout->gtk.icon_size, 0);
+              info = gtk_icon_theme_lookup_icon_for_scale (theme, icon_name,
+                                                           style->layout->gtk.icon_size,
+                                                           scale, 0);
+
               pixbuf = gtk_icon_info_load_symbolic_for_context (info, context, NULL, NULL);
             }
 
@@ -956,17 +994,17 @@ meta_theme_gtk_draw_frame (MetaThemeImpl           *impl,
               float width, height;
               int x, y;
 
-              width = gdk_pixbuf_get_width (pixbuf);
-              height = gdk_pixbuf_get_height (pixbuf);
+              width = gdk_pixbuf_get_width (pixbuf) / scale;
+              height = gdk_pixbuf_get_height (pixbuf) / scale;
               x = button_rect.x + (button_rect.width - width) / 2;
               y = button_rect.y + (button_rect.height - height) / 2;
 
               cairo_translate (cr, x, y);
               cairo_scale (cr,
-                           width / style->layout->gtk.icon_size,
-                           height / style->layout->gtk.icon_size);
+                           width / style->layout->gtk.icon_size / scale,
+                           height / style->layout->gtk.icon_size / scale);
               gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
-                                           cairo_paint (cr);
+              cairo_paint (cr);
 
               g_object_unref (pixbuf);
             }
diff --git a/libmetacity/meta-theme-metacity.c b/libmetacity/meta-theme-metacity.c
index 92e87fd..72a2ac5 100644
--- a/libmetacity/meta-theme-metacity.c
+++ b/libmetacity/meta-theme-metacity.c
@@ -4610,6 +4610,7 @@ meta_theme_metacity_get_frame_borders (MetaThemeImpl    *impl,
                                        MetaFrameBorders *borders)
 {
   int buttons_height, title_height;
+  int scale;
 
   meta_frame_borders_clear (borders);
 
@@ -4654,6 +4655,13 @@ meta_theme_metacity_get_frame_borders (MetaThemeImpl    *impl,
   borders->total.right = borders->invisible.right + borders->visible.right;
   borders->total.bottom = borders->invisible.bottom + borders->visible.bottom;
   borders->total.top = borders->invisible.top + borders->visible.top;
+
+  /* Scale geometry for HiDPI, see comment in meta_theme_metacity_draw_frame () */
+  scale = get_window_scaling_factor ();
+
+  scale_border (&borders->visible, scale);
+  scale_border (&borders->invisible, scale);
+  scale_border (&borders->total, scale);
 }
 
 static MetaButtonSpace *
@@ -4825,6 +4833,7 @@ meta_theme_metacity_calc_geometry (MetaThemeImpl          *impl,
   int width, height;
   int button_width, button_height;
   int min_size_for_rounding;
+  int scale;
 
   /* the left/right rects in order; the max # of rects
    * is the number of button functions
@@ -4855,15 +4864,18 @@ meta_theme_metacity_calc_geometry (MetaThemeImpl          *impl,
   button_width = -1;
   button_height = -1;
 
+  /* Scale geometry for HiDPI, see comment in meta_theme_metacity_draw_frame () */
+  scale = get_window_scaling_factor ();
+
   switch (layout->metacity.button_sizing)
     {
     case META_BUTTON_SIZING_ASPECT:
-      button_height = borders.visible.top - layout->button_border.top - layout->button_border.bottom;
+      button_height = borders.visible.top - layout->button_border.top * scale - layout->button_border.bottom 
* scale;
       button_width = button_height / layout->metacity.button_aspect;
       break;
     case META_BUTTON_SIZING_FIXED:
-      button_width = layout->metacity.button_width;
-      button_height = layout->metacity.button_height;
+      button_width = layout->metacity.button_width * scale;
+      button_height = layout->metacity.button_height * scale;
       break;
     case META_BUTTON_SIZING_LAST:
     default:
@@ -4956,20 +4968,21 @@ meta_theme_metacity_calc_geometry (MetaThemeImpl          *impl,
       int space_used_by_buttons;
       int space_available;
 
-      space_available = fgeom->width - layout->metacity.left_titlebar_edge -
-                        layout->metacity.right_titlebar_edge;
+      space_available = fgeom->width -
+                        layout->metacity.left_titlebar_edge * scale -
+                        layout->metacity.right_titlebar_edge * scale;
 
       space_used_by_buttons = 0;
 
       space_used_by_buttons += button_width * n_left;
       space_used_by_buttons += (button_width * 0.75) * n_left_spacers;
-      space_used_by_buttons += layout->button_border.left * n_left;
-      space_used_by_buttons += layout->button_border.right * n_left;
+      space_used_by_buttons += layout->button_border.left * scale * n_left;
+      space_used_by_buttons += layout->button_border.right * scale * n_left;
 
       space_used_by_buttons += button_width * n_right;
       space_used_by_buttons += (button_width * 0.75) * n_right_spacers;
-      space_used_by_buttons += layout->button_border.left * n_right;
-      space_used_by_buttons += layout->button_border.right * n_right;
+      space_used_by_buttons += layout->button_border.left * scale * n_right;
+      space_used_by_buttons += layout->button_border.right * scale * n_right;
 
       if (space_used_by_buttons <= space_available)
         break; /* Everything fits, bail out */
@@ -5052,10 +5065,10 @@ meta_theme_metacity_calc_geometry (MetaThemeImpl          *impl,
 
   /* center buttons vertically */
   button_y = (borders.visible.top -
-              (button_height + layout->button_border.top + layout->button_border.bottom)) / 2 + 
layout->button_border.top + borders.invisible.top;
+              (button_height + layout->button_border.top * scale + layout->button_border.bottom * scale)) / 
2 + layout->button_border.top * scale + borders.invisible.top;
 
   /* right edge of farthest-right button */
-  x = width - layout->metacity.right_titlebar_edge - borders.invisible.right;
+  x = width - layout->metacity.right_titlebar_edge * scale - borders.invisible.right;
 
   i = n_right - 1;
   while (i >= 0)
@@ -5066,7 +5079,7 @@ meta_theme_metacity_calc_geometry (MetaThemeImpl          *impl,
         break;
 
       rect = right_func_rects[i];
-      rect->visible.x = x - layout->button_border.right - button_width;
+      rect->visible.x = x - layout->button_border.right * scale - button_width;
       if (right_buttons_has_spacer[i])
         rect->visible.x -= (button_width * 0.75);
 
@@ -5084,34 +5097,34 @@ meta_theme_metacity_calc_geometry (MetaThemeImpl          *impl,
           rect->clickable.height = button_height;
 
           if (i == n_right - 1)
-            rect->clickable.width += layout->metacity.right_titlebar_edge +
-                                     layout->metacity.right_width +
-                                     layout->button_border.right;
+            rect->clickable.width += layout->metacity.right_titlebar_edge * scale +
+                                     layout->metacity.right_width * scale +
+                                     layout->button_border.right * scale;
         }
       else
         g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable));
 
       *(right_bg_rects[i]) = rect->visible;
 
-      x = rect->visible.x - layout->button_border.left;
+      x = rect->visible.x - layout->button_border.left * scale;
 
       --i;
     }
 
   /* save right edge of titlebar for later use */
-  title_right_edge = x - layout->metacity.title_border.right;
+  title_right_edge = x - layout->metacity.title_border.right * scale;
 
   /* Now x changes to be position from the left and we go through
    * the left-side buttons
    */
-  x = layout->metacity.left_titlebar_edge + borders.invisible.left;
+  x = layout->metacity.left_titlebar_edge * scale + borders.invisible.left;
   for (i = 0; i < n_left; i++)
     {
       MetaButtonSpace *rect;
 
       rect = left_func_rects[i];
 
-      rect->visible.x = x + layout->button_border.left;
+      rect->visible.x = x + layout->button_border.left * scale;
       rect->visible.y = button_y;
       rect->visible.width = button_width;
       rect->visible.height = button_height;
@@ -5126,7 +5139,7 @@ meta_theme_metacity_calc_geometry (MetaThemeImpl          *impl,
       else
         g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable));
 
-      x = rect->visible.x + rect->visible.width + layout->button_border.right;
+      x = rect->visible.x + rect->visible.width + layout->button_border.right * scale;
       if (left_buttons_has_spacer[i])
         x += (button_width * 0.75);
 
@@ -5136,12 +5149,12 @@ meta_theme_metacity_calc_geometry (MetaThemeImpl          *impl,
   /* We always fill as much vertical space as possible with title rect,
    * rather than centering it like the buttons
    */
-  fgeom->title_rect.x = x + layout->metacity.title_border.left;
-  fgeom->title_rect.y = layout->metacity.title_border.top + borders.invisible.top;
+  fgeom->title_rect.x = x + layout->metacity.title_border.left * scale;
+  fgeom->title_rect.y = layout->metacity.title_border.top * scale + borders.invisible.top;
   fgeom->title_rect.width = title_right_edge - fgeom->title_rect.x;
   fgeom->title_rect.height = borders.visible.top -
-                             layout->metacity.title_border.top -
-                             layout->metacity.title_border.bottom;
+                             layout->metacity.title_border.top * scale -
+                             layout->metacity.title_border.bottom * scale;
 
   /* Nuke title if it won't fit */
   if (fgeom->title_rect.width < 0 ||
@@ -5154,7 +5167,7 @@ meta_theme_metacity_calc_geometry (MetaThemeImpl          *impl,
   if (flags & META_FRAME_SHADED)
     min_size_for_rounding = 0;
   else
-    min_size_for_rounding = 5;
+    min_size_for_rounding = 5 * scale;
 
   fgeom->top_left_corner_rounded_radius = 0;
   fgeom->top_right_corner_rounded_radius = 0;
@@ -5162,14 +5175,14 @@ meta_theme_metacity_calc_geometry (MetaThemeImpl          *impl,
   fgeom->bottom_right_corner_rounded_radius = 0;
 
   if (borders.visible.top + borders.visible.left >= min_size_for_rounding)
-    fgeom->top_left_corner_rounded_radius = layout->top_left_corner_rounded_radius;
+    fgeom->top_left_corner_rounded_radius = layout->top_left_corner_rounded_radius * scale;
   if (borders.visible.top + borders.visible.right >= min_size_for_rounding)
-    fgeom->top_right_corner_rounded_radius = layout->top_right_corner_rounded_radius;
+    fgeom->top_right_corner_rounded_radius = layout->top_right_corner_rounded_radius * scale;
 
   if (borders.visible.bottom + borders.visible.left >= min_size_for_rounding)
-    fgeom->bottom_left_corner_rounded_radius = layout->bottom_left_corner_rounded_radius;
+    fgeom->bottom_left_corner_rounded_radius = layout->bottom_left_corner_rounded_radius * scale;
   if (borders.visible.bottom + borders.visible.right >= min_size_for_rounding)
-    fgeom->bottom_right_corner_rounded_radius = layout->bottom_right_corner_rounded_radius;
+    fgeom->bottom_right_corner_rounded_radius = layout->bottom_right_corner_rounded_radius * scale;
 }
 
 static void
@@ -5181,6 +5194,7 @@ clip_to_rounded_corners (cairo_t                 *cr,
   gint y;
   gint width;
   gint height;
+  int scale;
   gint radius;
 
   x = rect.x;
@@ -5190,10 +5204,12 @@ clip_to_rounded_corners (cairo_t                 *cr,
 
   cairo_new_path (cr);
 
+  scale = get_window_scaling_factor ();
+
   if (fgeom->top_left_corner_rounded_radius != 0)
     {
-      radius = fgeom->top_left_corner_rounded_radius;
-      radius += sqrt(fgeom->top_left_corner_rounded_radius);
+      radius = fgeom->top_left_corner_rounded_radius / scale;
+      radius += sqrt(fgeom->top_left_corner_rounded_radius / scale);
 
       cairo_line_to (cr, x, y + radius);
       cairo_arc (cr, x + radius, y + radius, radius,
@@ -5204,8 +5220,8 @@ clip_to_rounded_corners (cairo_t                 *cr,
 
   if (fgeom->top_right_corner_rounded_radius != 0)
     {
-      radius = fgeom->top_right_corner_rounded_radius;
-      radius += sqrt(fgeom->top_right_corner_rounded_radius);
+      radius = fgeom->top_right_corner_rounded_radius / scale;
+      radius += sqrt(fgeom->top_right_corner_rounded_radius / scale);
 
       cairo_line_to (cr, x + width - radius, y);
       cairo_arc (cr, x + width - radius, y + radius, radius,
@@ -5216,8 +5232,8 @@ clip_to_rounded_corners (cairo_t                 *cr,
 
   if (fgeom->bottom_right_corner_rounded_radius != 0)
     {
-      radius = fgeom->bottom_right_corner_rounded_radius;
-      radius += sqrt(fgeom->bottom_right_corner_rounded_radius);
+      radius = fgeom->bottom_right_corner_rounded_radius / scale;
+      radius += sqrt(fgeom->bottom_right_corner_rounded_radius / scale);
 
       cairo_line_to (cr, x + width, y + height - radius);
       cairo_arc (cr, x + width - radius, y + height - radius, radius,
@@ -5228,8 +5244,8 @@ clip_to_rounded_corners (cairo_t                 *cr,
 
   if (fgeom->bottom_left_corner_rounded_radius != 0)
     {
-      radius = fgeom->bottom_left_corner_rounded_radius;
-      radius += sqrt(fgeom->bottom_left_corner_rounded_radius);
+      radius = fgeom->bottom_left_corner_rounded_radius / scale;
+      radius += sqrt(fgeom->bottom_left_corner_rounded_radius / scale);
 
       cairo_line_to (cr, x + radius, y + height);
       cairo_arc (cr, x + radius, y + height - radius, radius,
@@ -5254,6 +5270,7 @@ meta_theme_metacity_draw_frame (MetaThemeImpl           *impl,
                                 GdkPixbuf               *mini_icon,
                                 GdkPixbuf               *icon)
 {
+  int scale;
   int i, j;
   GdkRectangle visible_rect;
   GdkRectangle titlebar_rect;
@@ -5266,17 +5283,31 @@ meta_theme_metacity_draw_frame (MetaThemeImpl           *impl,
   MetaDrawInfo draw_info;
   const MetaFrameBorders *borders;
 
+  /* We opt out of GTK+ HiDPI handling, so we have to do the scaling
+   * ourselves; the nitty-gritty is a bit confusing, so here is an overview:
+   *  - the values in MetaFrameLayout are always as they appear in the theme,
+   *    i.e. unscaled
+   *  - calculated values (borders, MetaFrameGeometry) include the scale - as
+   *    the geometry is comprised of scaled decorations and the client size
+   *    which we must not scale, we don't have another option
+   *  - for drawing, we scale the canvas to have GTK+ render elements (borders,
+   *    radii, ...) at the correct scale - as a result, we have to "unscale"
+   *    the geometry again to not apply the scaling twice
+   */
+  scale = get_window_scaling_factor ();
+  cairo_scale (cr, scale, scale);
+
   borders = &fgeom->borders;
 
-  visible_rect.x = borders->invisible.left;
-  visible_rect.y = borders->invisible.top;
-  visible_rect.width = fgeom->width - borders->invisible.left - borders->invisible.right;
-  visible_rect.height = fgeom->height - borders->invisible.top - borders->invisible.bottom;
+  visible_rect.x = borders->invisible.left / scale;
+  visible_rect.y = borders->invisible.top / scale;
+  visible_rect.width = (fgeom->width - borders->invisible.left - borders->invisible.right) / scale;
+  visible_rect.height = (fgeom->height - borders->invisible.top - borders->invisible.bottom) / scale;
 
   titlebar_rect.x = visible_rect.x;
   titlebar_rect.y = visible_rect.y;
   titlebar_rect.width = visible_rect.width;
-  titlebar_rect.height = borders->visible.top;
+  titlebar_rect.height = borders->visible.top / scale;
 
   left_titlebar_edge.x = titlebar_rect.x;
   left_titlebar_edge.y = titlebar_rect.y + style->layout->metacity.title_border.top;
@@ -5300,19 +5331,19 @@ meta_theme_metacity_draw_frame (MetaThemeImpl           *impl,
   bottom_titlebar_edge.y = titlebar_rect.y + titlebar_rect.height - bottom_titlebar_edge.height;
 
   left_edge.x = visible_rect.x;
-  left_edge.y = visible_rect.y + borders->visible.top;
-  left_edge.width = borders->visible.left;
-  left_edge.height = visible_rect.height - borders->visible.top - borders->visible.bottom;
+  left_edge.y = visible_rect.y + borders->visible.top / scale;
+  left_edge.width = borders->visible.left / scale;
+  left_edge.height = visible_rect.height - borders->visible.top / scale - borders->visible.bottom / scale;
 
-  right_edge.x = visible_rect.x + visible_rect.width - borders->visible.right;
-  right_edge.y = visible_rect.y + borders->visible.top;
-  right_edge.width = borders->visible.right;
-  right_edge.height = visible_rect.height - borders->visible.top - borders->visible.bottom;
+  right_edge.x = visible_rect.x + visible_rect.width - borders->visible.right / scale;
+  right_edge.y = visible_rect.y + borders->visible.top / scale;
+  right_edge.width = borders->visible.right / scale;
+  right_edge.height = visible_rect.height - borders->visible.top / scale - borders->visible.bottom / scale;
 
   bottom_edge.x = visible_rect.x;
-  bottom_edge.y = visible_rect.y + visible_rect.height - borders->visible.bottom;
+  bottom_edge.y = visible_rect.y + visible_rect.height - borders->visible.bottom / scale;
   bottom_edge.width = visible_rect.width;
-  bottom_edge.height = borders->visible.bottom;
+  bottom_edge.height = borders->visible.bottom / scale;
 
   if (title_layout)
     pango_layout_get_pixel_extents (title_layout,
@@ -5366,13 +5397,17 @@ meta_theme_metacity_draw_frame (MetaThemeImpl           *impl,
         case META_FRAME_PIECE_TITLEBAR_MIDDLE:
           rect.x = left_titlebar_edge.x + left_titlebar_edge.width;
           rect.y = top_titlebar_edge.y + top_titlebar_edge.height;
-          rect.width = titlebar_rect.width - left_titlebar_edge.width -
-            right_titlebar_edge.width;
+          rect.width = titlebar_rect.width - left_titlebar_edge.width - right_titlebar_edge.width;
           rect.height = titlebar_rect.height - top_titlebar_edge.height - bottom_titlebar_edge.height;
           break;
 
         case META_FRAME_PIECE_TITLE:
           rect = fgeom->title_rect;
+
+          rect.x /= scale;
+          rect.y /= scale;
+          rect.width /= scale;
+          rect.height /= scale;
           break;
 
         case META_FRAME_PIECE_LEFT_EDGE:
@@ -5441,6 +5476,11 @@ meta_theme_metacity_draw_frame (MetaThemeImpl           *impl,
 
               get_button_rect (j, fgeom, middle_bg_offset, &rect);
 
+              rect.x /= scale;
+              rect.y /= scale;
+              rect.width /= scale;
+              rect.height /= scale;
+
               button_state = map_button_state (j, fgeom, middle_bg_offset, button_states);
               op_list = meta_frame_style_get_button (style, j, button_state);
 


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