Skip to content
Snippets Groups Projects
0019-display-Support-UI-scaled-logical-monitor-mode.patch 9.8 KiB
Newer Older
From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
Subject: [PATCH 19/26] display: Support UI scaled logical monitor mode

When this mode is selected we need to assume that all the monitors are scaled
by their scaling and the global UI scale.

Origin: https://gitlab.gnome.org/3v1n0/gnome-control-center/commits/layout-global-scale
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/mutter/+bug/1820850
Forwarded: No, MPs will follow shortly
---
 panels/display/cc-display-arrangement.c | 25 ++++++++++++++++----
 panels/display/cc-display-config-dbus.c | 41 ++++++++++++++++++++++++++++++---
 panels/display/cc-display-config.c      | 26 +++++++++++++++++++++
 panels/display/cc-display-config.h      |  4 ++++
 4 files changed, 88 insertions(+), 8 deletions(-)
diff --git a/panels/display/cc-display-arrangement.c b/panels/display/cc-display-arrangement.c
--- a/panels/display/cc-display-arrangement.c
+++ b/panels/display/cc-display-arrangement.c
@@ -99,6 +99,7 @@ apply_rotation_to_geometry (CcDisplayMonitor *output,
 static void
 get_scaled_geometry (CcDisplayConfig  *config,
                      CcDisplayMonitor *output,
+                     double            max_scale,
                      int              *x,
                      int              *y,
                      int              *w,
@@ -117,6 +118,10 @@ get_scaled_geometry (CcDisplayConfig  *config,
   if (cc_display_config_is_layout_logical (config))
     {
       double scale = cc_display_monitor_get_scale (output);
+
+      if (cc_display_config_layout_use_ui_scale (config))
+
       *w = round (*w / scale);
       *h = round (*h / scale);
     }
@@ -134,6 +139,7 @@ get_bounding_box (CcDisplayConfig *config,
                   gint            *max_h)
 {
   GList *outputs, *l;
+  gdouble max_scale;
 
   g_assert (x1 && y1 && x2 && y2);
 
@@ -141,6 +147,7 @@ get_bounding_box (CcDisplayConfig *config,
+  max_scale = cc_display_config_get_maximum_scaling (config);
 
   outputs = cc_display_config_get_monitors (config);
   for (l = outputs; l; l = l->next)
@@ -151,7 +158,7 @@ get_bounding_box (CcDisplayConfig *config,
       if (!cc_display_monitor_is_useful (output))
         continue;
 
-      get_scaled_geometry (config, output, &x, &y, &w, &h);
+      get_scaled_geometry (config, output, max_scale, &x, &y, &w, &h);
 
       *x1 = MIN (*x1, x);
       *y1 = MIN (*y1, y);
@@ -171,8 +178,10 @@ monitor_get_drawing_rect (CcDisplayArrangement *self,
                           gint                 *y2)
 {
   gdouble x, y;
+  gdouble max_scale;
 
-  get_scaled_geometry (self->config, output, x1, y1, x2, y2);
+  max_scale = cc_display_config_get_maximum_scaling (self->config);
+  get_scaled_geometry (self->config, output, max_scale, x1, y1, x2, y2);
 
   /* get_scaled_geometry returns the width and height */
   *x2 = *x1 + *x2;
@@ -325,10 +334,12 @@ find_best_snapping (CcDisplayConfig   *config,
   GList *outputs, *l;
   gint x1, y1, x2, y2;
   gint w, h;
+  double max_scale;
 
   g_assert (snap_data != NULL);
 
-  get_scaled_geometry (config, snap_output, &x1, &y1, &w, &h);
+  max_scale = cc_display_config_get_maximum_scaling (config);
+  get_scaled_geometry (config, snap_output, max_scale, &x1, &y1, &w, &h);
   x2 = x1 + w;
   y2 = y1 + h;
 
@@ -344,6 +355,7 @@ find_best_snapping (CcDisplayConfig   *config,
       gint left_snap_pos;
       gint right_snap_pos;
       gdouble dist_x, dist_y;
+      gdouble max_scale;
       gdouble tmp;
 
       if (output == snap_output)
@@ -352,7 +364,8 @@ find_best_snapping (CcDisplayConfig   *config,
       if (!cc_display_monitor_is_useful (output))
         continue;
 
-      get_scaled_geometry (config, output, &_x1, &_y1, &_w, &_h);
+      max_scale = cc_display_config_get_maximum_scaling (config);
+      get_scaled_geometry (config, output, max_scale, &_x1, &_y1, &_w, &_h);
       _x2 = _x1 + _w;
       _y2 = _y1 + _h;
 
@@ -965,6 +978,7 @@ cc_display_config_snap_output (CcDisplayConfig  *config,
 {
   SnapData snap_data;
   gint x, y, w, h;
+  gdouble max_scale;
 
   if (!cc_display_monitor_is_useful (output))
     return;
@@ -972,7 +986,8 @@ cc_display_config_snap_output (CcDisplayConfig  *config,
   if (cc_display_config_count_useful_monitors (config) <= 1)
     return;
 
-  get_scaled_geometry (config, output, &x, &y, &w, &h);
+  max_scale = cc_display_config_get_maximum_scaling (config);
+  get_scaled_geometry (config, output, max_scale, &x, &y, &w, &h);
 
   snap_data.snapped = SNAP_DIR_NONE;
   snap_data.mon_x = x;
diff --git a/panels/display/cc-display-config-dbus.c b/panels/display/cc-display-config-dbus.c
index aa7c673..fc050a3 100644
--- a/panels/display/cc-display-config-dbus.c
+++ b/panels/display/cc-display-config-dbus.c
@@ -861,7 +861,8 @@ cc_display_monitor_dbus_new (GVariant *variant,
 typedef enum _CcDisplayLayoutMode
 {
   CC_DISPLAY_LAYOUT_MODE_LOGICAL = 1,
-  CC_DISPLAY_LAYOUT_MODE_PHYSICAL = 2
+  CC_DISPLAY_LAYOUT_MODE_PHYSICAL = 2,
+  CC_DISPLAY_LAYOUT_MODE_GLOBAL_UI_LOGICAL = 3
 } CcDisplayLayoutMode;
 
 typedef enum _CcDisplayConfigMethod
@@ -1203,7 +1204,15 @@ cc_display_config_dbus_is_layout_logical (CcDisplayConfig *pself)
 {
   CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself);
 
-  return self->layout_mode == CC_DISPLAY_LAYOUT_MODE_LOGICAL;
+  return self->layout_mode == CC_DISPLAY_LAYOUT_MODE_LOGICAL ||
+         self->layout_mode == CC_DISPLAY_LAYOUT_MODE_GLOBAL_UI_LOGICAL;
+}
+
+static gboolean
+cc_display_config_dbus_layout_use_ui_scale (CcDisplayConfig *pself)
+{
+  CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself);
+  return self->layout_mode == CC_DISPLAY_LAYOUT_MODE_GLOBAL_UI_LOGICAL;
 }
 
 static gboolean
@@ -1465,7 +1474,7 @@ cc_display_config_dbus_constructed (GObject *object)
           guint32 u = 0;
           g_variant_get (v, "u", &u);
           if (u >= CC_DISPLAY_LAYOUT_MODE_LOGICAL &&
-              u <= CC_DISPLAY_LAYOUT_MODE_PHYSICAL)
+              u <= CC_DISPLAY_LAYOUT_MODE_GLOBAL_UI_LOGICAL)
             self->layout_mode = u;
         }
     }
@@ -1555,6 +1564,7 @@ cc_display_config_dbus_class_init (CcDisplayConfigDBusClass *klass)
   parent_class->is_layout_logical = cc_display_config_dbus_is_layout_logical;
   parent_class->is_scaled_mode_valid = cc_display_config_dbus_is_scaled_mode_valid;
   parent_class->set_minimum_size = cc_display_config_dbus_set_minimum_size;
+  parent_class->layout_use_ui_scale = cc_display_config_dbus_layout_use_ui_scale;
 
   pspec = g_param_spec_variant ("state",
                                 "GVariant",
@@ -1615,6 +1625,26 @@ logical_monitor_is_rotated (CcDisplayLogicalMonitor *lm)
     }
 }
 
+static double
+get_maximum_scale (CcDisplayConfig *config)
+{
+  GList *outputs, *l;
+  double max_scale = 1.0;
+  outputs = cc_display_config_get_monitors (config);
+
+  for (l = outputs; l; l = l->next)
+    {
+      CcDisplayMonitor *output = l->data;
+
+      if (!cc_display_monitor_is_useful (output))
+        continue;
+
+      max_scale = MAX (max_scale, cc_display_monitor_get_scale (output));
+    }
+
+  return max_scale;
+}
+
 static int
 logical_monitor_width (CcDisplayLogicalMonitor *lm)
 {
@@ -1633,6 +1663,11 @@ logical_monitor_width (CcDisplayLogicalMonitor *lm)
 
   if (monitor->config->layout_mode == CC_DISPLAY_LAYOUT_MODE_LOGICAL)
     return round (width / lm->scale);
+  if (monitor->config->layout_mode == CC_DISPLAY_LAYOUT_MODE_GLOBAL_UI_LOGICAL)
+    {
+      double max_scale = get_maximum_scale(CC_DISPLAY_CONFIG (monitor->config));
+      return round ((width * ceil (max_scale)) / lm->scale);
+    }
   else
     return width;
 }
diff --git a/panels/display/cc-display-config.c b/panels/display/cc-display-config.c
--- a/panels/display/cc-display-config.c
+++ b/panels/display/cc-display-config.c
@@ -627,3 +627,29 @@ cc_display_config_is_scaled_mode_valid (CcDisplayConfig *self,
Sebastien Bacher's avatar
Sebastien Bacher committed
   g_return_val_if_fail (CC_IS_DISPLAY_MODE (mode), FALSE);
   return CC_DISPLAY_CONFIG_GET_CLASS (self)->is_scaled_mode_valid (self, mode, scale);
 }
+
+gboolean
+cc_display_config_layout_use_ui_scale (CcDisplayConfig *self)
+{
+  return CC_DISPLAY_CONFIG_GET_CLASS (self)->layout_use_ui_scale (self);
+}
+
+double
+cc_display_config_get_maximum_scaling (CcDisplayConfig *self)
+{
+  GList *outputs, *l;
+  double max_scale = 1.0;
+  outputs = cc_display_config_get_monitors (self);
+
+  for (l = outputs; l; l = l->next)
+    {
+      CcDisplayMonitor *output = l->data;
+
+      if (!cc_display_monitor_is_useful (output))
+        continue;
+
+      max_scale = MAX (max_scale, cc_display_monitor_get_scale (output));
+    }
+
+  return max_scale;
+}
diff --git a/panels/display/cc-display-config.h b/panels/display/cc-display-config.h
--- a/panels/display/cc-display-config.h
+++ b/panels/display/cc-display-config.h
@@ -160,6 +160,7 @@ struct _CcDisplayConfigClass
   gboolean (*is_scaled_mode_valid) (CcDisplayConfig  *self,
                                     CcDisplayMode    *mode,
                                     double            scale);
+  gboolean (*layout_use_ui_scale) (CcDisplayConfig  *self);
 };
 
 
@@ -186,6 +187,9 @@ void              cc_display_config_set_minimum_size        (CcDisplayConfig
 gboolean          cc_display_config_is_scaled_mode_valid    (CcDisplayConfig    *self,
                                                              CcDisplayMode      *mode,
                                                              double              scale);
+gboolean          cc_display_config_layout_use_ui_scale     (CcDisplayConfig    *self);
+
+double            cc_display_config_get_maximum_scaling     (CcDisplayConfig    *self);
 
 const char*       cc_display_monitor_get_display_name       (CcDisplayMonitor   *monitor);
 gboolean          cc_display_monitor_is_active              (CcDisplayMonitor   *monitor);