diff --git a/src/backends/meta-output.c b/src/backends/meta-output.c index f198752f7..ed4807507 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 10ed947b9..6c90d7e69 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 f4a207a6d..9774a9e65 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 1daa1d8be..c127c46ca 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 a0e36a4b9..ac53e6d15 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 93d351237..97eff0ee6 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; }