[mutter] virtual-monitor: Add way to change virtual monitor mode



commit 34d0e68aef8623d2e21cf7f29d70729cee8d7d1f
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Thu Dec 16 11:25:37 2021 +0100

    virtual-monitor: Add way to change virtual monitor mode
    
    This can be used to change the size of the virtual monitor without
    recreating it.
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2270>

 src/backends/meta-output.c                        | 18 ++++++++++++
 src/backends/meta-output.h                        |  5 ++++
 src/backends/meta-virtual-monitor.c               | 16 ++++++++--
 src/backends/meta-virtual-monitor.h               | 11 +++++++
 src/backends/native/meta-monitor-manager-native.c | 36 +++++++++++++++++++++++
 src/backends/native/meta-virtual-monitor-native.c | 30 +++++++++++++++++++
 6 files changed, 114 insertions(+), 2 deletions(-)
---
diff --git a/src/backends/meta-output.c b/src/backends/meta-output.c
index f198752f7a..ed48075072 100644
--- a/src/backends/meta-output.c
+++ b/src/backends/meta-output.c
@@ -541,3 +541,21 @@ meta_tile_info_equal (MetaTileInfo *a,
 
   return TRUE;
 }
+
+void
+meta_output_update_modes (MetaOutput    *output,
+                          MetaCrtcMode  *preferred_mode,
+                          MetaCrtcMode **modes,
+                          int            n_modes)
+{
+  MetaOutputPrivate *priv = meta_output_get_instance_private (output);
+  int i;
+
+  for (i = 0; i < priv->info->n_modes; i++)
+    g_object_unref (priv->info->modes[i]);
+  g_free (priv->info->modes);
+
+  priv->info->preferred_mode = preferred_mode;
+  priv->info->modes = modes;
+  priv->info->n_modes = n_modes;
+}
diff --git a/src/backends/meta-output.h b/src/backends/meta-output.h
index 10ed947b9c..6c90d7e69e 100644
--- a/src/backends/meta-output.h
+++ b/src/backends/meta-output.h
@@ -212,4 +212,9 @@ MetaMonitorTransform meta_output_logical_to_crtc_transform (MetaOutput
 MetaMonitorTransform meta_output_crtc_to_logical_transform (MetaOutput           *output,
                                                             MetaMonitorTransform  transform);
 
+void meta_output_update_modes (MetaOutput    *output,
+                               MetaCrtcMode  *preferred_mode,
+                               MetaCrtcMode **modes,
+                               int            n_modes);
+
 #endif /* META_OUTPUT_H */
diff --git a/src/backends/meta-virtual-monitor.c b/src/backends/meta-virtual-monitor.c
index f4a207a6d8..9774a9e650 100644
--- a/src/backends/meta-virtual-monitor.c
+++ b/src/backends/meta-virtual-monitor.c
@@ -135,7 +135,8 @@ meta_virtual_monitor_set_property (GObject      *object,
       priv->crtc = g_value_get_object (value);
       break;
     case PROP_CRTC_MODE:
-      priv->crtc_mode = g_value_get_object (value);
+      g_set_object (&priv->crtc_mode,
+                    g_value_get_object (value));
       break;
     case PROP_OUTPUT:
       priv->output = g_value_get_object (value);
@@ -219,7 +220,6 @@ meta_virtual_monitor_class_init (MetaVirtualMonitorClass *klass)
                          "The virtual CRTC mode",
                          META_TYPE_CRTC_MODE,
                          G_PARAM_READWRITE |
-                         G_PARAM_CONSTRUCT_ONLY |
                          G_PARAM_STATIC_STRINGS);
   obj_props[PROP_OUTPUT] =
     g_param_spec_object ("output",
@@ -238,3 +238,15 @@ meta_virtual_monitor_class_init (MetaVirtualMonitorClass *klass)
                   NULL, NULL, NULL,
                   G_TYPE_NONE, 0);
 }
+
+void
+meta_virtual_monitor_set_mode (MetaVirtualMonitor *virtual_monitor,
+                               int                 width,
+                               int                 height,
+                               float               refresh_rate)
+{
+  MetaVirtualMonitorClass *klass =
+    META_VIRTUAL_MONITOR_GET_CLASS (virtual_monitor);
+
+  klass->set_mode (virtual_monitor, width, height, refresh_rate);
+}
diff --git a/src/backends/meta-virtual-monitor.h b/src/backends/meta-virtual-monitor.h
index 1daa1d8bee..c127c46cad 100644
--- a/src/backends/meta-virtual-monitor.h
+++ b/src/backends/meta-virtual-monitor.h
@@ -50,6 +50,11 @@ G_DECLARE_DERIVABLE_TYPE (MetaVirtualMonitor, meta_virtual_monitor,
 struct _MetaVirtualMonitorClass
 {
   GObjectClass parent_class;
+
+  void (* set_mode) (MetaVirtualMonitor *virtual_monitor,
+                     int                 width,
+                     int                 height,
+                     float               refresh_rate);
 };
 
 META_EXPORT_TEST
@@ -70,6 +75,12 @@ MetaCrtcMode * meta_virtual_monitor_get_crtc_mode (MetaVirtualMonitor *virtual_m
 META_EXPORT_TEST
 MetaOutput * meta_virtual_monitor_get_output (MetaVirtualMonitor *virtual_monitor);
 
+META_EXPORT_TEST
+void meta_virtual_monitor_set_mode (MetaVirtualMonitor *virtual_monitor,
+                                    int                 width,
+                                    int                 height,
+                                    float               refresh_rate);
+
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaVirtualMonitorInfo,
                                meta_virtual_monitor_info_free)
 
diff --git a/src/backends/native/meta-monitor-manager-native.c 
b/src/backends/native/meta-monitor-manager-native.c
index a0e36a4b93..ac53e6d157 100644
--- a/src/backends/native/meta-monitor-manager-native.c
+++ b/src/backends/native/meta-monitor-manager-native.c
@@ -83,6 +83,8 @@ struct _MetaMonitorManagerNative
   GHashTable *crtc_gamma_cache;
 
   gboolean needs_outputs;
+
+  guint rebuild_virtual_idle_id;
 };
 
 struct _MetaMonitorManagerNativeClass
@@ -778,6 +780,35 @@ meta_monitor_manager_native_set_privacy_screen_enabled (MetaMonitorManager *mana
   return TRUE;
 }
 
+static gboolean
+rebuild_virtual_idle_cb (gpointer user_data)
+{
+  MetaMonitorManager *manager = user_data;
+  MetaMonitorManagerNative *manager_native =
+    META_MONITOR_MANAGER_NATIVE (manager);
+
+  manager_native->rebuild_virtual_idle_id = 0;
+
+  meta_monitor_manager_reconfigure (manager);
+
+  return G_SOURCE_REMOVE;
+}
+
+static void
+on_virtual_monitor_mode_changed (MetaVirtualMonitor *virtual_monitor,
+                                 GParamSpec         *pspec,
+                                 MetaMonitorManager *manager)
+{
+  MetaMonitorManagerNative *manager_native =
+    META_MONITOR_MANAGER_NATIVE (manager);
+
+  if (manager_native->rebuild_virtual_idle_id)
+    return;
+
+  manager_native->rebuild_virtual_idle_id =
+    g_idle_add (rebuild_virtual_idle_cb, manager);
+}
+
 static MetaVirtualMonitor *
 meta_monitor_manager_native_create_virtual_monitor (MetaMonitorManager            *manager,
                                                     const MetaVirtualMonitorInfo  *info,
@@ -790,6 +821,10 @@ meta_monitor_manager_native_create_virtual_monitor (MetaMonitorManager
 
   id = allocate_virtual_monitor_id (manager_native);
   virtual_monitor_native = meta_virtual_monitor_native_new (id, info);
+  g_signal_connect (virtual_monitor_native, "notify::crtc-mode",
+                    G_CALLBACK (on_virtual_monitor_mode_changed),
+                    manager);
+
   return META_VIRTUAL_MONITOR (virtual_monitor_native);
 }
 
@@ -819,6 +854,7 @@ meta_monitor_manager_native_dispose (GObject *object)
   MetaMonitorManagerNative *manager_native =
     META_MONITOR_MANAGER_NATIVE (object);
 
+  g_clear_handle_id (&manager_native->rebuild_virtual_idle_id, g_source_remove);
   g_clear_pointer (&manager_native->crtc_gamma_cache,
                    g_hash_table_unref);
 
diff --git a/src/backends/native/meta-virtual-monitor-native.c 
b/src/backends/native/meta-virtual-monitor-native.c
index 93d351237f..97eff0ee6c 100644
--- a/src/backends/native/meta-virtual-monitor-native.c
+++ b/src/backends/native/meta-virtual-monitor-native.c
@@ -38,6 +38,33 @@ static uint64_t mode_id = 1;
 G_DEFINE_TYPE (MetaVirtualMonitorNative, meta_virtual_monitor_native,
                META_TYPE_VIRTUAL_MONITOR)
 
+static void
+meta_virtual_monitor_native_set_mode (MetaVirtualMonitor *virtual_monitor,
+                                      int                 width,
+                                      int                 height,
+                                      float               refresh_rate)
+{
+  MetaOutput *output = meta_virtual_monitor_get_output (virtual_monitor);
+  MetaVirtualModeInfo info;
+  MetaCrtcModeVirtual *crtc_mode_virtual;
+  MetaCrtcMode **modes;
+
+  info = (MetaVirtualModeInfo) {
+    .width = width,
+    .height = height,
+    .refresh_rate = refresh_rate,
+  };
+  crtc_mode_virtual = meta_crtc_mode_virtual_new (mode_id++, &info);
+
+  modes = g_new0 (MetaCrtcMode *, 1);
+  modes[0] = META_CRTC_MODE (crtc_mode_virtual);
+  meta_output_update_modes (output, modes[0], modes, 1);
+
+  g_object_set (virtual_monitor,
+                "crtc-mode", crtc_mode_virtual,
+                NULL);
+}
+
 uint64_t
 meta_virtual_monitor_native_get_id (MetaVirtualMonitorNative *virtual_monitor_native)
 {
@@ -77,4 +104,7 @@ meta_virtual_monitor_native_init (MetaVirtualMonitorNative *virtual_monitor_nati
 static void
 meta_virtual_monitor_native_class_init (MetaVirtualMonitorNativeClass *klass)
 {
+  MetaVirtualMonitorClass *virtual_monitor_class = META_VIRTUAL_MONITOR_CLASS (klass);
+
+  virtual_monitor_class->set_mode = meta_virtual_monitor_native_set_mode;
 }


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