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>
This commit is contained in:
Jonas Ådahl 2021-12-16 11:25:37 +01:00 committed by Marge Bot
parent a97b6560d7
commit 34d0e68aef
6 changed files with 114 additions and 2 deletions

View File

@ -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;
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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)

View File

@ -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);

View File

@ -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;
}