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