diff --git a/src/backends/meta-backend-private.h b/src/backends/meta-backend-private.h index 4678f7768..5b0c849ec 100644 --- a/src/backends/meta-backend-private.h +++ b/src/backends/meta-backend-private.h @@ -108,6 +108,14 @@ struct _MetaBackendClass void meta_init_backend (GType backend_gtype); +#ifdef HAVE_WAYLAND +MetaWaylandCompositor * meta_backend_get_wayland_compositor (MetaBackend *backend); + +void meta_backend_init_wayland_display (MetaBackend *backend); + +void meta_backend_init_wayland (MetaBackend *backend); +#endif + ClutterBackend * meta_backend_get_clutter_backend (MetaBackend *backend); MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend, diff --git a/src/backends/meta-backend-types.h b/src/backends/meta-backend-types.h index 98cac8b9e..2961a8b20 100644 --- a/src/backends/meta-backend-types.h +++ b/src/backends/meta-backend-types.h @@ -54,4 +54,6 @@ typedef struct _MetaScreenCast MetaScreenCast; typedef struct _MetaScreenCastSession MetaScreenCastSession; typedef struct _MetaScreenCastStream MetaScreenCastStream; +typedef struct _MetaWaylandCompositor MetaWaylandCompositor; + #endif /* META_BACKEND_TYPE_H */ diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c index 1c6a6783a..d6892f5bb 100644 --- a/src/backends/meta-backend.c +++ b/src/backends/meta-backend.c @@ -81,6 +81,10 @@ #include "backends/native/meta-backend-native.h" #endif +#ifdef HAVE_WAYLAND +#include "wayland/meta-wayland.h" +#endif + enum { KEYMAP_CHANGED, @@ -130,6 +134,10 @@ struct _MetaBackendPrivate MetaRemoteDesktop *remote_desktop; #endif +#ifdef HAVE_WAYLAND + MetaWaylandCompositor *wayland_compositor; +#endif + #ifdef HAVE_PROFILER MetaProfiler *profiler; #endif @@ -864,6 +872,120 @@ system_bus_gotten_cb (GObject *object, NULL); } +#ifdef HAVE_WAYLAND +MetaWaylandCompositor * +meta_backend_get_wayland_compositor (MetaBackend *backend) +{ + MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); + + return priv->wayland_compositor; +} + +void +meta_backend_init_wayland_display (MetaBackend *backend) +{ + MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); + + priv->wayland_compositor = meta_wayland_compositor_new (); +} + +void +meta_backend_init_wayland (MetaBackend *backend) +{ + MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); + + meta_wayland_compositor_setup (priv->wayland_compositor); +} +#endif + +/* Mutter is responsible for pulling events off the X queue, so Clutter + * doesn't need (and shouldn't) run its normal event source which polls + * the X fd, but we do have to deal with dispatching events that accumulate + * in the clutter queue. This happens, for example, when clutter generate + * enter/leave events on mouse motion - several events are queued in the + * clutter queue but only one dispatched. It could also happen because of + * explicit calls to clutter_event_put(). We add a very simple custom + * event loop source which is simply responsible for pulling events off + * of the queue and dispatching them before we block for new events. + */ + +static gboolean +clutter_source_prepare (GSource *source, + int *timeout) +{ + *timeout = -1; + + return clutter_events_pending (); +} + +static gboolean +clutter_source_check (GSource *source) +{ + return clutter_events_pending (); +} + +static gboolean +clutter_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + ClutterEvent *event = clutter_event_get (); + + if (event) + { + clutter_do_event (event); + clutter_event_free (event); + } + + return TRUE; +} + +static GSourceFuncs clutter_source_funcs = { + clutter_source_prepare, + clutter_source_check, + clutter_source_dispatch +}; + +static ClutterBackend * +meta_get_clutter_backend (void) +{ + MetaBackend *backend = meta_get_backend (); + + return meta_backend_get_clutter_backend (backend); +} + +static gboolean +init_clutter (MetaBackend *backend, + GError **error) +{ + GSource *source; + + clutter_set_custom_backend_func (meta_get_clutter_backend); + + if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Unable to initialize Clutter"); + return FALSE; + } + + source = g_source_new (&clutter_source_funcs, sizeof (GSource)); + g_source_attach (source, NULL); + g_source_unref (source); + + return TRUE; +} + +static void +meta_backend_post_init (MetaBackend *backend) +{ + MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); + + META_BACKEND_GET_CLASS (backend)->post_init (backend); + + meta_settings_post_init (priv->settings); +} + static gboolean meta_backend_initable_init (GInitable *initable, GCancellable *cancellable, @@ -902,6 +1024,11 @@ meta_backend_initable_init (GInitable *initable, priv->profiler = meta_profiler_new (); #endif + if (!init_clutter (backend, error)) + return FALSE; + + meta_backend_post_init (backend); + return TRUE; } @@ -917,16 +1044,6 @@ meta_backend_init (MetaBackend *backend) _backend = backend; } -static void -meta_backend_post_init (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - META_BACKEND_GET_CLASS (backend)->post_init (backend); - - meta_settings_post_init (priv->settings); -} - /** * meta_backend_get_idle_monitor: (skip) */ @@ -1258,54 +1375,6 @@ meta_backend_set_client_pointer_constraint (MetaBackend *backend, priv->client_pointer_constraint = g_object_ref (constraint); } -/* Mutter is responsible for pulling events off the X queue, so Clutter - * doesn't need (and shouldn't) run its normal event source which polls - * the X fd, but we do have to deal with dispatching events that accumulate - * in the clutter queue. This happens, for example, when clutter generate - * enter/leave events on mouse motion - several events are queued in the - * clutter queue but only one dispatched. It could also happen because of - * explicit calls to clutter_event_put(). We add a very simple custom - * event loop source which is simply responsible for pulling events off - * of the queue and dispatching them before we block for new events. - */ - -static gboolean -event_prepare (GSource *source, - gint *timeout_) -{ - *timeout_ = -1; - - return clutter_events_pending (); -} - -static gboolean -event_check (GSource *source) -{ - return clutter_events_pending (); -} - -static gboolean -event_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - ClutterEvent *event = clutter_event_get (); - - if (event) - { - clutter_do_event (event); - clutter_event_free (event); - } - - return TRUE; -} - -static GSourceFuncs event_funcs = { - event_prepare, - event_check, - event_dispatch -}; - ClutterBackend * meta_backend_get_clutter_backend (MetaBackend *backend) { @@ -1320,14 +1389,6 @@ meta_backend_get_clutter_backend (MetaBackend *backend) return priv->clutter_backend; } -static ClutterBackend * -meta_get_clutter_backend (void) -{ - MetaBackend *backend = meta_get_backend (); - - return meta_backend_get_clutter_backend (backend); -} - void meta_init_backend (GType backend_gtype) { @@ -1344,29 +1405,6 @@ meta_init_backend (GType backend_gtype) } } -/** - * meta_clutter_init: (skip) - */ -void -meta_clutter_init (void) -{ - GSource *source; - - clutter_set_custom_backend_func (meta_get_clutter_backend); - - if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS) - { - g_warning ("Unable to initialize Clutter.\n"); - exit (1); - } - - source = g_source_new (&event_funcs, sizeof (GSource)); - g_source_attach (source, NULL); - g_source_unref (source); - - meta_backend_post_init (_backend); -} - /** * meta_is_stage_views_enabled: * diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c index 6c4a474e2..e5a16f337 100644 --- a/src/backends/native/meta-backend-native.c +++ b/src/backends/native/meta-backend-native.c @@ -366,6 +366,10 @@ meta_backend_native_post_init (MetaBackend *backend) if (retval != 0) g_warning ("Failed to set RT scheduler: %m"); } + +#ifdef HAVE_WAYLAND + meta_backend_init_wayland (backend); +#endif } static MetaMonitorManager * @@ -647,6 +651,10 @@ meta_backend_native_initable_init (GInitable *initable, if (!native->launcher) return FALSE; +#ifdef HAVE_WAYLAND + meta_backend_init_wayland_display (META_BACKEND (native)); +#endif + native->udev = meta_udev_new (native); native->barrier_manager = meta_barrier_manager_native_new (); diff --git a/src/backends/x11/nested/meta-backend-x11-nested.c b/src/backends/x11/nested/meta-backend-x11-nested.c index b9e7ff3b8..def74bb74 100644 --- a/src/backends/x11/nested/meta-backend-x11-nested.c +++ b/src/backends/x11/nested/meta-backend-x11-nested.c @@ -33,8 +33,16 @@ typedef struct _MetaBackendX11NestedPrivate MetaGpu *gpu; } MetaBackendX11NestedPrivate; -G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendX11Nested, meta_backend_x11_nested, - META_TYPE_BACKEND_X11) +static GInitableIface *initable_parent_iface; + +static void +initable_iface_init (GInitableIface *initable_iface); + +G_DEFINE_TYPE_WITH_CODE (MetaBackendX11Nested, meta_backend_x11_nested, + META_TYPE_BACKEND_X11, + G_ADD_PRIVATE (MetaBackendX11Nested) + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + initable_iface_init)); static MetaRenderer * meta_backend_x11_nested_create_renderer (MetaBackend *backend, @@ -201,6 +209,39 @@ meta_backend_x11_nested_real_init_gpus (MetaBackendX11Nested *backend_x11_nested meta_backend_add_gpu (META_BACKEND (backend_x11_nested), priv->gpu); } +static void +meta_backend_x11_nested_post_init (MetaBackend *backend) +{ + MetaBackendClass *backend_class = + META_BACKEND_CLASS (meta_backend_x11_nested_parent_class); + + backend_class->post_init (backend); + +#ifdef HAVE_WAYLAND + meta_backend_init_wayland (backend); +#endif +} + +static gboolean +meta_backend_x11_nested_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ +#ifdef HAVE_WAYLAND + meta_backend_init_wayland_display (META_BACKEND (initable)); +#endif + + return initable_parent_iface->init (initable, cancellable, error); +} + +static void +initable_iface_init (GInitableIface *initable_iface) +{ + initable_parent_iface = g_type_interface_peek_parent (initable_iface); + + initable_iface->init = meta_backend_x11_nested_initable_init; +} + static void meta_backend_x11_nested_constructed (GObject *object) { @@ -229,6 +270,7 @@ meta_backend_x11_nested_class_init (MetaBackendX11NestedClass *klass) object_class->constructed = meta_backend_x11_nested_constructed; + backend_class->post_init = meta_backend_x11_nested_post_init; backend_class->create_renderer = meta_backend_x11_nested_create_renderer; backend_class->create_monitor_manager = meta_backend_x11_nested_create_monitor_manager; backend_class->create_cursor_renderer = meta_backend_x11_nested_create_cursor_renderer; diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c index 338817127..d45d50743 100644 --- a/src/compositor/compositor.c +++ b/src/compositor/compositor.c @@ -502,11 +502,6 @@ after_stage_paint (ClutterStage *stage, for (l = priv->windows; l; l = l->next) meta_window_actor_post_paint (l->data); - -#ifdef HAVE_WAYLAND - if (meta_is_wayland_compositor ()) - meta_wayland_compositor_paint_finished (meta_wayland_compositor_get_default ()); -#endif } static void @@ -1154,6 +1149,11 @@ meta_compositor_real_post_paint (MetaCompositor *compositor) meta_compositor_get_instance_private (compositor); CoglGraphicsResetStatus status; +#ifdef HAVE_WAYLAND + if (meta_is_wayland_compositor ()) + meta_wayland_compositor_paint_finished (meta_wayland_compositor_get_default ()); +#endif + status = cogl_get_graphics_reset_status (priv->context); switch (status) { diff --git a/src/core/main.c b/src/core/main.c index 16aa8736a..16ab6e81f 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -586,11 +586,6 @@ meta_init (void) g_irepository_prepend_search_path (MUTTER_PKGLIBDIR); #endif -#ifdef HAVE_WAYLAND - if (meta_is_wayland_compositor ()) - meta_wayland_pre_clutter_init (); -#endif - /* NB: When running as a hybrid wayland compositor we run our own headless X * server so the user can't control the X display to connect too. */ if (!meta_is_wayland_compositor ()) @@ -598,14 +593,6 @@ meta_init (void) meta_init_backend (backend_gtype); - meta_clutter_init (); - -#ifdef HAVE_WAYLAND - /* Bring up Wayland. This also launches Xwayland and sets DISPLAY as well... */ - if (meta_is_wayland_compositor ()) - meta_wayland_init (); -#endif - meta_set_syncing (opt_sync || (g_getenv ("MUTTER_SYNC") != NULL)); if (opt_replace_wm) diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c index f3f922635..a7bf9158c 100644 --- a/src/wayland/meta-wayland.c +++ b/src/wayland/meta-wayland.c @@ -47,7 +47,6 @@ #include "wayland/meta-xwayland-private.h" #include "wayland/meta-xwayland.h" -static MetaWaylandCompositor *_meta_wayland_compositor = NULL; static char *_display_name_override; G_DEFINE_TYPE (MetaWaylandCompositor, meta_wayland_compositor, G_TYPE_OBJECT) @@ -55,9 +54,14 @@ G_DEFINE_TYPE (MetaWaylandCompositor, meta_wayland_compositor, G_TYPE_OBJECT) MetaWaylandCompositor * meta_wayland_compositor_get_default (void) { - g_assert (_meta_wayland_compositor); + MetaBackend *backend; + MetaWaylandCompositor *wayland_compositor; - return _meta_wayland_compositor; + backend = meta_get_backend (); + wayland_compositor = meta_backend_get_wayland_compositor (backend); + g_assert (wayland_compositor); + + return wayland_compositor; } typedef struct @@ -318,6 +322,8 @@ meta_wayland_compositor_init (MetaWaylandCompositor *compositor) compositor->wayland_display = wl_display_create (); if (compositor->wayland_display == NULL) g_error ("Failed to create the global wl_display"); + + clutter_wayland_set_compositor_display (compositor->wayland_display); } static void @@ -325,19 +331,6 @@ meta_wayland_compositor_class_init (MetaWaylandCompositorClass *klass) { } -void -meta_wayland_pre_clutter_init (void) -{ - MetaWaylandCompositor *compositor; - - g_assert (!_meta_wayland_compositor); - - compositor = g_object_new (META_TYPE_WAYLAND_COMPOSITOR, NULL); - clutter_wayland_set_compositor_display (compositor->wayland_display); - - _meta_wayland_compositor = compositor; -} - static bool meta_xwayland_global_filter (const struct wl_client *client, const struct wl_global *global, @@ -368,8 +361,14 @@ meta_wayland_get_xwayland_auth_file (MetaWaylandCompositor *compositor) return compositor->xwayland_manager.auth_file; } +MetaWaylandCompositor * +meta_wayland_compositor_new (void) +{ + return g_object_new (META_TYPE_WAYLAND_COMPOSITOR, NULL); +} + void -meta_wayland_init (void) +meta_wayland_compositor_setup (MetaWaylandCompositor *wayland_compositor) { MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); GSource *wayland_event_source; diff --git a/src/wayland/meta-wayland.h b/src/wayland/meta-wayland.h index c5690c34e..15b7310ba 100644 --- a/src/wayland/meta-wayland.h +++ b/src/wayland/meta-wayland.h @@ -37,8 +37,10 @@ void meta_wayland_init (void); void meta_wayland_finalize (void); -/* We maintain a singleton MetaWaylandCompositor which can be got at via this - * API after meta_wayland_init() has been called. */ +MetaWaylandCompositor * meta_wayland_compositor_new (void); + +void meta_wayland_compositor_setup (MetaWaylandCompositor *compositor); + META_EXPORT_TEST MetaWaylandCompositor *meta_wayland_compositor_get_default (void);