From 42d614f6fadfc432f4a3f83bcb72b39c5150cd09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com> Date: Thu, 5 Mar 2020 21:35:57 +0100 Subject: [PATCH] backend-native: Add non-functional 'headless' mode Make it possible to pass --headless as a command line argument in order to turn the native backend "headless". This currently doesn't do anything, but the intention is that it should not use logind nor KMS, and work completely headless with only virtual outputs. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1698> --- src/backends/meta-backend-private.h | 5 +- src/backends/meta-backend.c | 10 +++- src/backends/native/meta-backend-native.c | 43 ++++++++++++++++ src/core/main.c | 63 ++++++++++++++++++++--- 4 files changed, 110 insertions(+), 11 deletions(-) diff --git a/src/backends/meta-backend-private.h b/src/backends/meta-backend-private.h index 80df654bc..3926a3c63 100644 --- a/src/backends/meta-backend-private.h +++ b/src/backends/meta-backend-private.h @@ -104,7 +104,10 @@ struct _MetaBackendClass MetaPointerConstraint *constraint); }; -void meta_init_backend (GType backend_gtype); +void meta_init_backend (GType backend_gtype, + unsigned int n_properties, + const char *names[], + const GValue *values); void meta_release_backend (void); #ifdef HAVE_WAYLAND diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c index 9e525957e..6b2780eeb 100644 --- a/src/backends/meta-backend.c +++ b/src/backends/meta-backend.c @@ -1458,14 +1458,20 @@ meta_backend_get_clutter_backend (MetaBackend *backend) } void -meta_init_backend (GType backend_gtype) +meta_init_backend (GType backend_gtype, + unsigned int n_properties, + const char *names[], + const GValue *values) { MetaBackend *backend; GError *error = NULL; /* meta_backend_init() above install the backend globally so * so meta_get_backend() works even during initialization. */ - backend = g_object_new (backend_gtype, NULL); + backend = META_BACKEND (g_object_new_with_properties (backend_gtype, + n_properties, + names, + values)); if (!g_initable_init (G_INITABLE (backend), NULL, &error)) { g_warning ("Failed to create backend: %s", error->message); diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c index bf270c3ff..8a83f0bc8 100644 --- a/src/backends/native/meta-backend-native.c +++ b/src/backends/native/meta-backend-native.c @@ -65,6 +65,17 @@ #include "backends/meta-screen-cast.h" #endif +enum +{ + PROP_0, + + PROP_HEADLESS, + + N_PROPS +}; + +static GParamSpec *obj_props[N_PROPS]; + struct _MetaBackendNative { MetaBackend parent; @@ -73,6 +84,8 @@ struct _MetaBackendNative MetaUdev *udev; MetaKms *kms; + gboolean is_headless; + gulong udev_device_added_handler_id; }; @@ -520,6 +533,25 @@ meta_backend_native_initable_init (GInitable *initable, return initable_parent_iface->init (initable, cancellable, error); } +static void +meta_backend_native_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MetaBackendNative *backend_native = META_BACKEND_NATIVE (object); + + switch (prop_id) + { + case PROP_HEADLESS: + backend_native->is_headless = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + static void initable_iface_init (GInitableIface *initable_iface) { @@ -534,6 +566,7 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass) MetaBackendClass *backend_class = META_BACKEND_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass); + object_class->set_property = meta_backend_native_set_property; object_class->dispose = meta_backend_native_dispose; backend_class->create_clutter_backend = meta_backend_native_create_clutter_backend; @@ -554,6 +587,16 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass) backend_class->update_screen_size = meta_backend_native_update_screen_size; backend_class->set_pointer_constraint = meta_backend_native_set_pointer_constraint; + + obj_props[PROP_HEADLESS] = + g_param_spec_boolean ("headless", + "headless", + "Headless", + FALSE, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, N_PROPS, obj_props); } static void diff --git a/src/core/main.c b/src/core/main.c index 4bcfd7a5d..f908fd217 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -208,6 +208,7 @@ static char *opt_wayland_display; #endif #ifdef HAVE_NATIVE_BACKEND static gboolean opt_display_server; +static gboolean opt_headless; #endif static gboolean opt_x11; @@ -279,6 +280,11 @@ static GOptionEntry meta_options[] = { &opt_display_server, N_("Run as a full display server, rather than nested") }, + { + "headless", 0, 0, G_OPTION_ARG_NONE, + &opt_headless, + N_("Run as a headless display server") + }, #endif { "x11", 0, 0, G_OPTION_ARG_NONE, @@ -468,14 +474,21 @@ check_for_wayland_session_type (void) * Wayland compositor, then the X11 Compositing Manager backend is used. */ static void -calculate_compositor_configuration (MetaCompositorType *compositor_type, - GType *backend_gtype) +calculate_compositor_configuration (MetaCompositorType *compositor_type, + GType *backend_gtype, + unsigned int *n_properties, + const char **prop_names[], + GValue *prop_values[]) { #ifdef HAVE_WAYLAND - gboolean run_as_wayland_compositor = opt_wayland && !opt_x11; + gboolean run_as_wayland_compositor = ((opt_wayland || + opt_display_server || + opt_headless) && + !opt_x11); #ifdef HAVE_NATIVE_BACKEND - if ((opt_wayland || opt_nested || opt_display_server) && opt_x11) + if ((opt_wayland || opt_nested || opt_display_server || opt_headless) && + opt_x11) #else if ((opt_wayland || opt_nested) && opt_x11) #endif @@ -485,7 +498,7 @@ calculate_compositor_configuration (MetaCompositorType *compositor_type, } #ifdef HAVE_NATIVE_BACKEND - if (opt_nested && opt_display_server) + if (opt_nested && (opt_display_server || opt_headless)) { meta_warning ("Can't run both as nested and as a display server"); meta_exit (META_EXIT_ERROR); @@ -507,6 +520,10 @@ calculate_compositor_configuration (MetaCompositorType *compositor_type, #endif /* HAVE_WAYLAND */ *compositor_type = META_COMPOSITOR_TYPE_X11; + *n_properties = 0; + *prop_names = NULL; + *prop_values = NULL; + #ifdef HAVE_WAYLAND if (opt_nested) { @@ -516,9 +533,25 @@ calculate_compositor_configuration (MetaCompositorType *compositor_type, #endif /* HAVE_WAYLAND */ #ifdef HAVE_NATIVE_BACKEND - if (opt_display_server) + if (opt_display_server || opt_headless) { *backend_gtype = META_TYPE_BACKEND_NATIVE; + if (opt_headless) + { + static const char *headless_prop_names[] = { + "headless", + }; + static GValue headless_prop_values[] = { + G_VALUE_INIT, + }; + + g_value_init (&headless_prop_values[0], G_TYPE_BOOLEAN); + g_value_set_boolean (&headless_prop_values[0], TRUE); + + *n_properties = G_N_ELEMENTS (headless_prop_values); + *prop_names = headless_prop_names; + *prop_values = headless_prop_values; + } return; } @@ -572,6 +605,10 @@ meta_init (void) const char *debug_env; MetaCompositorType compositor_type; GType backend_gtype; + unsigned int n_properties; + const char **prop_names; + GValue *prop_values; + int i; #ifdef HAVE_SYS_PRCTL prctl (PR_SET_DUMPABLE, 1); @@ -610,10 +647,17 @@ meta_init (void) { compositor_type = _compositor_type_override; backend_gtype = _backend_gtype_override; + n_properties = 0; + prop_names = NULL; + prop_values = NULL; } else { - calculate_compositor_configuration (&compositor_type, &backend_gtype); + calculate_compositor_configuration (&compositor_type, + &backend_gtype, + &n_properties, + &prop_names, + &prop_values); } #ifdef HAVE_WAYLAND @@ -644,7 +688,10 @@ meta_init (void) if (!meta_is_wayland_compositor ()) meta_select_display (opt_display_name); - meta_init_backend (backend_gtype); + meta_init_backend (backend_gtype, n_properties, prop_names, prop_values); + + for (i = 0; i < n_properties; i++) + g_value_reset (&prop_values[i]); meta_set_syncing (opt_sync || (g_getenv ("MUTTER_SYNC") != NULL));