2021-03-02 03:31:19 -05:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2019 Red Hat Inc.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License as
|
|
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
|
|
* License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2023-08-07 05:50:23 -04:00
|
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
2021-03-02 03:31:19 -05:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include "core/meta-context-private.h"
|
|
|
|
|
2021-03-02 04:51:18 -05:00
|
|
|
#include <locale.h>
|
2022-01-14 05:33:22 -05:00
|
|
|
#include <sys/resource.h>
|
2021-03-02 04:51:18 -05:00
|
|
|
|
2021-03-02 05:41:34 -05:00
|
|
|
#include "backends/meta-backend-private.h"
|
2021-03-02 05:48:22 -05:00
|
|
|
#include "compositor/meta-plugin-manager.h"
|
2021-03-02 05:53:59 -05:00
|
|
|
#include "core/display-private.h"
|
2023-01-27 15:49:56 -05:00
|
|
|
#include "core/meta-service-channel.h"
|
2021-03-02 05:57:57 -05:00
|
|
|
#include "core/prefs-private.h"
|
2021-03-02 04:35:38 -05:00
|
|
|
#include "core/util-private.h"
|
|
|
|
|
2022-10-12 16:30:07 -04:00
|
|
|
#ifdef HAVE_PROFILER
|
|
|
|
#include "core/meta-profiler.h"
|
|
|
|
#endif
|
|
|
|
|
2021-03-02 05:53:59 -05:00
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
#include "wayland/meta-wayland.h"
|
|
|
|
#endif
|
|
|
|
|
2021-03-02 03:31:19 -05:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
PROP_0,
|
|
|
|
|
|
|
|
PROP_NAME,
|
2021-09-01 15:12:03 -04:00
|
|
|
PROP_UNSAFE_MODE,
|
2021-03-02 03:31:19 -05:00
|
|
|
|
|
|
|
N_PROPS
|
|
|
|
};
|
|
|
|
|
|
|
|
static GParamSpec *obj_props[N_PROPS];
|
|
|
|
|
2022-11-24 10:21:07 -05:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
STARTED,
|
|
|
|
PREPARE_SHUTDOWN,
|
|
|
|
|
|
|
|
N_SIGNALS
|
|
|
|
};
|
|
|
|
|
|
|
|
static guint signals[N_SIGNALS];
|
|
|
|
|
2021-03-03 17:02:50 -05:00
|
|
|
typedef enum _MetaContextState
|
|
|
|
{
|
|
|
|
META_CONTEXT_STATE_INIT,
|
|
|
|
META_CONTEXT_STATE_CONFIGURED,
|
|
|
|
META_CONTEXT_STATE_SETUP,
|
|
|
|
META_CONTEXT_STATE_STARTED,
|
|
|
|
META_CONTEXT_STATE_RUNNING,
|
|
|
|
META_CONTEXT_STATE_TERMINATED,
|
|
|
|
} MetaContextState;
|
|
|
|
|
2021-03-02 03:31:19 -05:00
|
|
|
typedef struct _MetaContextPrivate
|
|
|
|
{
|
|
|
|
char *name;
|
2021-03-02 05:48:22 -05:00
|
|
|
char *plugin_name;
|
2021-03-03 07:55:32 -05:00
|
|
|
GType plugin_gtype;
|
2021-03-03 17:02:02 -05:00
|
|
|
char *gnome_wm_keybindings;
|
2021-03-02 05:53:59 -05:00
|
|
|
|
2021-09-01 15:12:03 -04:00
|
|
|
gboolean unsafe_mode;
|
|
|
|
|
2021-03-03 17:02:50 -05:00
|
|
|
MetaContextState state;
|
|
|
|
|
2021-03-02 10:46:05 -05:00
|
|
|
GOptionContext *option_context;
|
|
|
|
|
2021-03-03 08:31:56 -05:00
|
|
|
MetaBackend *backend;
|
2021-03-03 09:12:19 -05:00
|
|
|
MetaDisplay *display;
|
2021-03-03 16:00:05 -05:00
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
MetaWaylandCompositor *wayland_compositor;
|
|
|
|
#endif
|
2021-03-03 08:31:56 -05:00
|
|
|
|
2021-03-02 05:53:59 -05:00
|
|
|
GMainLoop *main_loop;
|
|
|
|
GError *termination_error;
|
2022-01-14 05:33:22 -05:00
|
|
|
#ifdef RLIMIT_NOFILE
|
|
|
|
struct rlimit saved_rlimit_nofile;
|
|
|
|
#endif
|
2022-10-12 16:30:07 -04:00
|
|
|
|
|
|
|
#ifdef HAVE_PROFILER
|
2023-05-10 16:26:08 -04:00
|
|
|
char *trace_file;
|
2022-10-12 16:30:07 -04:00
|
|
|
MetaProfiler *profiler;
|
|
|
|
#endif
|
2023-01-27 15:49:56 -05:00
|
|
|
|
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
MetaServiceChannel *service_channel;
|
|
|
|
#endif
|
2023-10-31 10:30:17 -04:00
|
|
|
|
|
|
|
MetaDebugControl *debug_control;
|
2021-03-02 03:31:19 -05:00
|
|
|
} MetaContextPrivate;
|
|
|
|
|
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE (MetaContext, meta_context, G_TYPE_OBJECT)
|
|
|
|
|
2021-08-26 06:42:31 -04:00
|
|
|
/**
|
|
|
|
* meta_context_add_option_entries:
|
|
|
|
* @context: a #MetaContext
|
|
|
|
* @entries: (array zero-terminated=1): a %NULL-terminated array of #GOptionEntrys
|
|
|
|
* @translation_domain: (nullable): a translation domain to use, or %NULL
|
|
|
|
*
|
|
|
|
* See g_option_context_add_main_entries() for more details.
|
|
|
|
**/
|
2021-03-02 10:46:05 -05:00
|
|
|
void
|
|
|
|
meta_context_add_option_entries (MetaContext *context,
|
|
|
|
const GOptionEntry *entries,
|
|
|
|
const char *translation_domain)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
2021-03-03 17:02:50 -05:00
|
|
|
g_warn_if_fail (priv->state == META_CONTEXT_STATE_INIT);
|
|
|
|
|
2021-03-02 10:46:05 -05:00
|
|
|
g_option_context_add_main_entries (priv->option_context,
|
|
|
|
entries,
|
|
|
|
translation_domain);
|
|
|
|
}
|
|
|
|
|
2021-08-26 06:42:31 -04:00
|
|
|
/**
|
|
|
|
* meta_context_add_option_group:
|
|
|
|
* @context: a #MetaContext
|
|
|
|
* @group: (transfer full): the group to add
|
|
|
|
*
|
|
|
|
* See g_option_context_add_group() for more details.
|
|
|
|
**/
|
2021-03-03 07:56:32 -05:00
|
|
|
void
|
|
|
|
meta_context_add_option_group (MetaContext *context,
|
|
|
|
GOptionGroup *group)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
2021-03-03 17:02:50 -05:00
|
|
|
g_warn_if_fail (priv->state == META_CONTEXT_STATE_INIT);
|
2021-03-03 07:56:32 -05:00
|
|
|
g_return_if_fail (priv->option_context);
|
|
|
|
|
|
|
|
g_option_context_add_group (priv->option_context, group);
|
|
|
|
}
|
|
|
|
|
2021-03-03 07:55:32 -05:00
|
|
|
void
|
|
|
|
meta_context_set_plugin_gtype (MetaContext *context,
|
|
|
|
GType plugin_gtype)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
2021-03-03 17:02:50 -05:00
|
|
|
g_return_if_fail (priv->state <= META_CONTEXT_STATE_CONFIGURED);
|
2021-03-03 07:55:32 -05:00
|
|
|
g_return_if_fail (!priv->plugin_name);
|
|
|
|
|
|
|
|
priv->plugin_gtype = plugin_gtype;
|
|
|
|
}
|
|
|
|
|
2021-03-02 05:48:22 -05:00
|
|
|
void
|
|
|
|
meta_context_set_plugin_name (MetaContext *context,
|
|
|
|
const char *plugin_name)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
2021-03-03 17:02:50 -05:00
|
|
|
g_return_if_fail (priv->state <= META_CONTEXT_STATE_CONFIGURED);
|
2021-03-03 07:55:32 -05:00
|
|
|
g_return_if_fail (priv->plugin_gtype == G_TYPE_NONE);
|
|
|
|
|
2021-03-02 05:48:22 -05:00
|
|
|
priv->plugin_name = g_strdup (plugin_name);
|
|
|
|
}
|
|
|
|
|
2021-03-03 17:02:02 -05:00
|
|
|
void
|
|
|
|
meta_context_set_gnome_wm_keybindings (MetaContext *context,
|
|
|
|
const char *wm_keybindings)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
2021-03-03 17:02:50 -05:00
|
|
|
g_return_if_fail (priv->state <= META_CONTEXT_STATE_CONFIGURED);
|
|
|
|
|
2021-03-03 17:02:02 -05:00
|
|
|
g_clear_pointer (&priv->gnome_wm_keybindings, g_free);
|
|
|
|
priv->gnome_wm_keybindings = g_strdup (wm_keybindings);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
meta_context_get_gnome_wm_keybindings (MetaContext *context)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
|
|
|
return priv->gnome_wm_keybindings;
|
|
|
|
}
|
|
|
|
|
2021-03-02 06:07:10 -05:00
|
|
|
void
|
|
|
|
meta_context_notify_ready (MetaContext *context)
|
|
|
|
{
|
2021-03-03 17:02:50 -05:00
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
|
|
|
g_return_if_fail (priv->state == META_CONTEXT_STATE_STARTED ||
|
|
|
|
priv->state == META_CONTEXT_STATE_RUNNING);
|
|
|
|
|
2024-01-28 04:35:56 -05:00
|
|
|
if (META_CONTEXT_GET_CLASS (context)->notify_ready)
|
|
|
|
META_CONTEXT_GET_CLASS (context)->notify_ready (context);
|
2021-03-02 06:07:10 -05:00
|
|
|
}
|
|
|
|
|
2021-03-03 16:12:01 -05:00
|
|
|
const char *
|
|
|
|
meta_context_get_name (MetaContext *context)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
|
|
|
return priv->name;
|
|
|
|
}
|
|
|
|
|
2021-03-03 08:31:56 -05:00
|
|
|
/**
|
|
|
|
* meta_context_get_backend:
|
|
|
|
* @context: The #MetaContext
|
|
|
|
*
|
|
|
|
* Returns: (transfer none): the #MetaBackend
|
|
|
|
*/
|
|
|
|
MetaBackend *
|
|
|
|
meta_context_get_backend (MetaContext *context)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
|
|
|
return priv->backend;
|
|
|
|
}
|
|
|
|
|
2021-03-03 09:12:19 -05:00
|
|
|
/**
|
|
|
|
* meta_context_get_display:
|
|
|
|
* @context: The #MetaContext
|
|
|
|
*
|
|
|
|
* Returns: (transfer none): the #MetaDisplay
|
|
|
|
*/
|
|
|
|
MetaDisplay *
|
|
|
|
meta_context_get_display (MetaContext *context)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
|
|
|
return priv->display;
|
|
|
|
}
|
|
|
|
|
2021-03-03 16:00:05 -05:00
|
|
|
#ifdef HAVE_WAYLAND
|
2023-06-26 10:08:08 -04:00
|
|
|
/**
|
|
|
|
* meta_context_get_wayland_compositor:
|
|
|
|
* @context: The #MetaContext
|
|
|
|
*
|
|
|
|
* Get the #MetaWaylandCompositor associated with the MetaContext. The might be
|
|
|
|
* none currently associated if the context hasn't been started or if the
|
|
|
|
* requested compositor type is not %META_COMPOSITOR_TYPE_WAYLAND.
|
|
|
|
*
|
|
|
|
* Returns: (transfer none) (nullable): the #MetaWaylandCompositor
|
|
|
|
*/
|
2021-03-03 16:00:05 -05:00
|
|
|
MetaWaylandCompositor *
|
|
|
|
meta_context_get_wayland_compositor (MetaContext *context)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
|
|
|
return priv->wayland_compositor;
|
|
|
|
}
|
2023-01-27 15:49:56 -05:00
|
|
|
|
|
|
|
MetaServiceChannel *
|
|
|
|
meta_context_get_service_channel (MetaContext *context)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
|
|
|
return priv->service_channel;
|
|
|
|
}
|
2021-03-03 16:00:05 -05:00
|
|
|
#endif
|
|
|
|
|
2021-03-03 05:31:24 -05:00
|
|
|
MetaCompositorType
|
2021-03-02 04:35:38 -05:00
|
|
|
meta_context_get_compositor_type (MetaContext *context)
|
|
|
|
{
|
|
|
|
return META_CONTEXT_GET_CLASS (context)->get_compositor_type (context);
|
|
|
|
}
|
|
|
|
|
2021-04-19 10:13:47 -04:00
|
|
|
gboolean
|
|
|
|
meta_context_is_replacing (MetaContext *context)
|
|
|
|
{
|
|
|
|
return META_CONTEXT_GET_CLASS (context)->is_replacing (context);
|
|
|
|
}
|
|
|
|
|
2021-04-16 14:34:29 -04:00
|
|
|
MetaX11DisplayPolicy
|
|
|
|
meta_context_get_x11_display_policy (MetaContext *context)
|
|
|
|
{
|
|
|
|
return META_CONTEXT_GET_CLASS (context)->get_x11_display_policy (context);
|
|
|
|
}
|
|
|
|
|
2022-05-30 14:27:02 -04:00
|
|
|
#ifdef HAVE_X11
|
|
|
|
gboolean
|
|
|
|
meta_context_is_x11_sync (MetaContext *context)
|
|
|
|
{
|
|
|
|
return META_CONTEXT_GET_CLASS (context)->is_x11_sync (context);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-10-26 06:10:43 -04:00
|
|
|
#ifdef HAVE_PROFILER
|
|
|
|
MetaProfiler *
|
|
|
|
meta_context_get_profiler (MetaContext *context)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
|
|
|
return priv->profiler;
|
|
|
|
}
|
2023-05-10 16:26:08 -04:00
|
|
|
|
|
|
|
void
|
|
|
|
meta_context_set_trace_file (MetaContext *context,
|
|
|
|
const char *trace_file)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
|
|
|
priv->trace_file = g_strdup (trace_file);
|
|
|
|
}
|
2022-10-26 06:10:43 -04:00
|
|
|
#endif
|
|
|
|
|
2021-03-02 10:46:05 -05:00
|
|
|
static gboolean
|
|
|
|
meta_context_real_configure (MetaContext *context,
|
|
|
|
int *argc,
|
|
|
|
char ***argv,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
g_autoptr (GOptionContext) option_context = NULL;
|
|
|
|
|
|
|
|
if (!priv->option_context)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
|
|
"Tried to configure multiple times");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
option_context = g_steal_pointer (&priv->option_context);
|
2023-10-31 10:30:17 -04:00
|
|
|
if (!g_option_context_parse (option_context, argc, argv, error))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
priv->debug_control = g_object_new (META_TYPE_DEBUG_CONTROL,
|
|
|
|
"context", context,
|
|
|
|
NULL);
|
|
|
|
return TRUE;
|
2021-03-02 10:46:05 -05:00
|
|
|
}
|
|
|
|
|
2021-08-26 06:42:31 -04:00
|
|
|
/**
|
|
|
|
* meta_context_configure:
|
|
|
|
* @context: a #MetaContext
|
|
|
|
* @argc: (inout): Address of the `argc` parameter of your main() function (or 0
|
|
|
|
* if @argv is %NULL).
|
|
|
|
* @argv: (array length=argc) (inout) (nullable): Address of the`argv` parameter
|
|
|
|
* of main(), or %NULL.
|
|
|
|
* @error: a return location for errors
|
|
|
|
*
|
|
|
|
* Returns: %TRUE if the commandline arguments (if any) were valid and if the
|
2023-08-09 19:44:52 -04:00
|
|
|
* configuration has been successful, %FALSE otherwise
|
2021-08-26 06:42:31 -04:00
|
|
|
*/
|
2021-03-02 04:35:38 -05:00
|
|
|
gboolean
|
|
|
|
meta_context_configure (MetaContext *context,
|
|
|
|
int *argc,
|
|
|
|
char ***argv,
|
|
|
|
GError **error)
|
|
|
|
{
|
2021-03-03 17:02:50 -05:00
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
2021-03-02 04:35:38 -05:00
|
|
|
MetaCompositorType compositor_type;
|
|
|
|
|
2021-03-03 17:02:50 -05:00
|
|
|
g_warn_if_fail (priv->state == META_CONTEXT_STATE_INIT);
|
|
|
|
|
2021-03-02 04:35:38 -05:00
|
|
|
if (!META_CONTEXT_GET_CLASS (context)->configure (context, argc, argv, error))
|
2021-03-03 17:02:50 -05:00
|
|
|
{
|
|
|
|
priv->state = META_CONTEXT_STATE_TERMINATED;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2021-03-02 04:35:38 -05:00
|
|
|
|
2023-05-10 16:26:08 -04:00
|
|
|
#ifdef HAVE_PROFILER
|
|
|
|
priv->profiler = meta_profiler_new (priv->trace_file);
|
|
|
|
#endif
|
|
|
|
|
2021-03-02 04:35:38 -05:00
|
|
|
compositor_type = meta_context_get_compositor_type (context);
|
|
|
|
switch (compositor_type)
|
|
|
|
{
|
|
|
|
case META_COMPOSITOR_TYPE_WAYLAND:
|
|
|
|
meta_set_is_wayland_compositor (TRUE);
|
|
|
|
break;
|
|
|
|
case META_COMPOSITOR_TYPE_X11:
|
|
|
|
meta_set_is_wayland_compositor (FALSE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-03-03 17:02:50 -05:00
|
|
|
priv->state = META_CONTEXT_STATE_CONFIGURED;
|
|
|
|
|
2021-03-02 04:35:38 -05:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2021-03-02 05:41:34 -05:00
|
|
|
static const char *
|
|
|
|
compositor_type_to_description (MetaCompositorType compositor_type)
|
|
|
|
{
|
|
|
|
switch (compositor_type)
|
|
|
|
{
|
|
|
|
case META_COMPOSITOR_TYPE_WAYLAND:
|
|
|
|
return "Wayland display server";
|
|
|
|
case META_COMPOSITOR_TYPE_X11:
|
|
|
|
return "X11 window and compositing manager";
|
|
|
|
}
|
|
|
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
|
2021-03-02 06:00:13 -05:00
|
|
|
static void
|
|
|
|
init_introspection (MetaContext *context)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_INTROSPECTION
|
|
|
|
g_irepository_prepend_search_path (MUTTER_PKGLIBDIR);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-03-02 05:41:34 -05:00
|
|
|
static gboolean
|
|
|
|
meta_context_real_setup (MetaContext *context,
|
|
|
|
GError **error)
|
|
|
|
{
|
2021-03-03 08:31:56 -05:00
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
MetaBackend *backend;
|
|
|
|
|
|
|
|
backend = META_CONTEXT_GET_CLASS (context)->create_backend (context, error);
|
|
|
|
if (!backend)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
priv->backend = backend;
|
|
|
|
return TRUE;
|
2021-03-02 05:41:34 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
meta_context_setup (MetaContext *context,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
MetaCompositorType compositor_type;
|
|
|
|
|
2021-03-03 17:02:50 -05:00
|
|
|
g_warn_if_fail (priv->state == META_CONTEXT_STATE_CONFIGURED);
|
|
|
|
|
2021-03-03 07:55:32 -05:00
|
|
|
if (!priv->plugin_name && priv->plugin_gtype == G_TYPE_NONE)
|
2021-03-02 05:48:22 -05:00
|
|
|
{
|
2021-03-03 17:02:50 -05:00
|
|
|
priv->state = META_CONTEXT_STATE_TERMINATED;
|
2021-03-02 05:48:22 -05:00
|
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
|
|
"No compositor plugin set");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2021-03-02 06:01:46 -05:00
|
|
|
meta_init_debug_utils ();
|
2021-03-02 05:59:39 -05:00
|
|
|
|
2021-03-02 05:41:34 -05:00
|
|
|
compositor_type = meta_context_get_compositor_type (context);
|
|
|
|
g_message ("Running %s (using mutter %s) as a %s",
|
|
|
|
priv->name, VERSION,
|
|
|
|
compositor_type_to_description (compositor_type));
|
2021-03-02 05:48:22 -05:00
|
|
|
|
2021-03-03 07:55:32 -05:00
|
|
|
if (priv->plugin_name)
|
|
|
|
meta_plugin_manager_load (priv->plugin_name);
|
|
|
|
else
|
|
|
|
meta_plugin_manager_set_plugin_type (priv->plugin_gtype);
|
2021-03-02 05:48:22 -05:00
|
|
|
|
2021-03-02 06:00:13 -05:00
|
|
|
init_introspection (context);
|
|
|
|
|
2021-03-03 17:02:50 -05:00
|
|
|
if (!META_CONTEXT_GET_CLASS (context)->setup (context, error))
|
|
|
|
{
|
|
|
|
priv->state = META_CONTEXT_STATE_TERMINATED;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv->state = META_CONTEXT_STATE_SETUP;
|
|
|
|
return TRUE;
|
2021-03-02 05:41:34 -05:00
|
|
|
}
|
|
|
|
|
2021-03-02 05:53:59 -05:00
|
|
|
gboolean
|
|
|
|
meta_context_start (MetaContext *context,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
2021-03-03 17:02:50 -05:00
|
|
|
g_warn_if_fail (priv->state == META_CONTEXT_STATE_SETUP);
|
|
|
|
|
2021-03-02 05:57:57 -05:00
|
|
|
meta_prefs_init ();
|
|
|
|
|
2021-03-02 05:53:59 -05:00
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
if (meta_context_get_compositor_type (context) ==
|
|
|
|
META_COMPOSITOR_TYPE_WAYLAND)
|
2021-05-06 10:02:34 -04:00
|
|
|
priv->wayland_compositor = meta_wayland_compositor_new (context);
|
2021-03-02 05:53:59 -05:00
|
|
|
#endif
|
|
|
|
|
2021-03-03 10:05:09 -05:00
|
|
|
priv->display = meta_display_new (context, error);
|
2021-03-03 09:12:19 -05:00
|
|
|
if (!priv->display)
|
2021-03-03 17:02:50 -05:00
|
|
|
{
|
|
|
|
priv->state = META_CONTEXT_STATE_TERMINATED;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2021-03-02 05:53:59 -05:00
|
|
|
|
2023-01-27 15:49:56 -05:00
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
priv->service_channel = meta_service_channel_new (context);
|
|
|
|
#endif
|
|
|
|
|
2021-03-02 05:53:59 -05:00
|
|
|
priv->main_loop = g_main_loop_new (NULL, FALSE);
|
|
|
|
|
2021-03-03 17:02:50 -05:00
|
|
|
priv->state = META_CONTEXT_STATE_STARTED;
|
|
|
|
|
2022-11-24 10:21:07 -05:00
|
|
|
g_signal_emit (context, signals[STARTED], 0);
|
|
|
|
|
2021-03-02 05:53:59 -05:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
meta_context_run_main_loop (MetaContext *context,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
2021-03-03 17:02:50 -05:00
|
|
|
g_warn_if_fail (priv->state == META_CONTEXT_STATE_STARTED);
|
2021-03-02 05:53:59 -05:00
|
|
|
if (!priv->main_loop)
|
|
|
|
{
|
2021-03-03 17:02:50 -05:00
|
|
|
priv->state = META_CONTEXT_STATE_TERMINATED;
|
2021-03-02 05:53:59 -05:00
|
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
|
|
"Tried to run main loop without having started");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2021-03-03 17:02:50 -05:00
|
|
|
priv->state = META_CONTEXT_STATE_RUNNING;
|
2021-03-02 05:53:59 -05:00
|
|
|
g_main_loop_run (priv->main_loop);
|
2021-03-03 17:02:50 -05:00
|
|
|
priv->state = META_CONTEXT_STATE_TERMINATED;
|
2021-03-02 05:53:59 -05:00
|
|
|
g_clear_pointer (&priv->main_loop, g_main_loop_unref);
|
|
|
|
|
|
|
|
if (priv->termination_error)
|
|
|
|
{
|
|
|
|
g_propagate_error (error, g_steal_pointer (&priv->termination_error));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_context_terminate (MetaContext *context)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
2021-03-03 17:02:50 -05:00
|
|
|
g_warn_if_fail (priv->state == META_CONTEXT_STATE_RUNNING);
|
|
|
|
g_warn_if_fail (g_main_loop_is_running (priv->main_loop));
|
2021-03-02 05:53:59 -05:00
|
|
|
|
|
|
|
g_main_loop_quit (priv->main_loop);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_context_terminate_with_error (MetaContext *context,
|
|
|
|
GError *error)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
|
|
|
priv->termination_error = g_steal_pointer (&error);
|
|
|
|
meta_context_terminate (context);
|
|
|
|
}
|
|
|
|
|
2021-05-10 15:43:18 -04:00
|
|
|
void
|
|
|
|
meta_context_destroy (MetaContext *context)
|
|
|
|
{
|
|
|
|
g_object_run_dispose (G_OBJECT (context));
|
|
|
|
g_object_unref (context);
|
|
|
|
}
|
|
|
|
|
2021-09-01 15:12:03 -04:00
|
|
|
void
|
|
|
|
meta_context_set_unsafe_mode (MetaContext *context,
|
|
|
|
gboolean enable)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
|
|
|
if (priv->unsafe_mode == enable)
|
|
|
|
return;
|
|
|
|
|
|
|
|
priv->unsafe_mode = enable;
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (context), obj_props[PROP_UNSAFE_MODE]);
|
|
|
|
}
|
|
|
|
|
2022-01-14 05:33:22 -05:00
|
|
|
static gboolean
|
|
|
|
meta_context_save_rlimit_nofile (MetaContext *context,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
#ifdef RLIMIT_NOFILE
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
|
|
|
if (getrlimit (RLIMIT_NOFILE, &priv->saved_rlimit_nofile) != 0)
|
|
|
|
{
|
|
|
|
priv->saved_rlimit_nofile.rlim_cur = 0;
|
|
|
|
priv->saved_rlimit_nofile.rlim_max = 0;
|
|
|
|
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
|
|
|
|
"getrlimit failed: %s", g_strerror (errno));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
#else
|
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOSYS,
|
|
|
|
"Missing support for RLIMIT_NOFILE");
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* meta_context_raise_rlimit_nofile:
|
|
|
|
* @context: a #MetaContext
|
|
|
|
* @error: a return location for errors
|
|
|
|
*
|
|
|
|
* Raises the RLIMIT_NOFILE limit value to the hard limit.
|
|
|
|
*/
|
|
|
|
gboolean
|
|
|
|
meta_context_raise_rlimit_nofile (MetaContext *context,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
#ifdef RLIMIT_NOFILE
|
|
|
|
struct rlimit new_rlimit;
|
|
|
|
|
|
|
|
if (getrlimit (RLIMIT_NOFILE, &new_rlimit) != 0)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
|
|
|
|
"getrlimit failed: %s", g_strerror (errno));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Raise the rlimit_nofile value to the hard limit */
|
|
|
|
new_rlimit.rlim_cur = new_rlimit.rlim_max;
|
|
|
|
|
|
|
|
if (setrlimit (RLIMIT_NOFILE, &new_rlimit) != 0)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
|
|
|
|
"setrlimit failed: %s", g_strerror (errno));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
#else
|
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOSYS,
|
|
|
|
"Missing support for RLIMIT_NOFILE");
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* meta_context_restore_rlimit_nofile:
|
|
|
|
* @context: a #MetaContext
|
|
|
|
* @error: a return location for errors
|
|
|
|
*
|
|
|
|
* Restores the RLIMIT_NOFILE limits from when the #MetaContext was created.
|
|
|
|
*/
|
|
|
|
gboolean
|
|
|
|
meta_context_restore_rlimit_nofile (MetaContext *context,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
#ifdef RLIMIT_NOFILE
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
|
|
|
if (priv->saved_rlimit_nofile.rlim_cur == 0)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT,
|
|
|
|
"RLIMIT_NOFILE not saved");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (setrlimit (RLIMIT_NOFILE, &priv->saved_rlimit_nofile) != 0)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
|
|
|
|
"setrlimit failed: %s", g_strerror (errno));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
#else
|
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOSYS,
|
|
|
|
"Missing support for RLIMIT_NOFILE");
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-03-02 03:31:19 -05:00
|
|
|
static void
|
|
|
|
meta_context_get_property (GObject *object,
|
|
|
|
guint prop_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
MetaContext *context = META_CONTEXT (object);
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
{
|
|
|
|
case PROP_NAME:
|
|
|
|
g_value_set_string (value, priv->name);
|
|
|
|
break;
|
2021-09-01 15:12:03 -04:00
|
|
|
case PROP_UNSAFE_MODE:
|
|
|
|
g_value_set_boolean (value, priv->unsafe_mode);
|
|
|
|
break;
|
2021-03-02 03:31:19 -05:00
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_context_set_property (GObject *object,
|
|
|
|
guint prop_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
MetaContext *context = META_CONTEXT (object);
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
{
|
|
|
|
case PROP_NAME:
|
|
|
|
priv->name = g_value_dup_string (value);
|
|
|
|
break;
|
2021-09-01 15:12:03 -04:00
|
|
|
case PROP_UNSAFE_MODE:
|
|
|
|
meta_context_set_unsafe_mode (META_CONTEXT (object),
|
|
|
|
g_value_get_boolean (value));
|
|
|
|
break;
|
2021-03-02 03:31:19 -05:00
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-05-10 15:43:18 -04:00
|
|
|
meta_context_dispose (GObject *object)
|
2021-03-02 03:31:19 -05:00
|
|
|
{
|
|
|
|
MetaContext *context = META_CONTEXT (object);
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
2021-03-02 05:41:34 -05:00
|
|
|
|
2022-11-24 10:21:07 -05:00
|
|
|
g_signal_emit (context, signals[PREPARE_SHUTDOWN], 0);
|
2021-03-02 05:41:34 -05:00
|
|
|
|
2021-03-02 05:53:59 -05:00
|
|
|
#ifdef HAVE_WAYLAND
|
2023-01-27 15:49:56 -05:00
|
|
|
g_clear_object (&priv->service_channel);
|
|
|
|
|
2021-03-03 16:00:05 -05:00
|
|
|
if (priv->wayland_compositor)
|
|
|
|
meta_wayland_compositor_prepare_shutdown (priv->wayland_compositor);
|
2021-03-02 05:53:59 -05:00
|
|
|
#endif
|
|
|
|
|
2021-03-03 09:12:19 -05:00
|
|
|
if (priv->display)
|
|
|
|
meta_display_close (priv->display, META_CURRENT_TIME);
|
|
|
|
g_clear_object (&priv->display);
|
2021-03-02 05:53:59 -05:00
|
|
|
|
|
|
|
#ifdef HAVE_WAYLAND
|
2021-03-03 16:00:05 -05:00
|
|
|
g_clear_object (&priv->wayland_compositor);
|
2021-03-02 05:53:59 -05:00
|
|
|
#endif
|
|
|
|
|
2021-03-03 08:31:56 -05:00
|
|
|
g_clear_pointer (&priv->backend, meta_backend_destroy);
|
2021-03-02 03:31:19 -05:00
|
|
|
|
2023-10-31 10:30:17 -04:00
|
|
|
g_clear_object (&priv->debug_control);
|
|
|
|
|
2021-03-02 10:46:05 -05:00
|
|
|
g_clear_pointer (&priv->option_context, g_option_context_free);
|
2021-03-02 05:53:59 -05:00
|
|
|
g_clear_pointer (&priv->main_loop, g_main_loop_unref);
|
2021-05-10 15:43:18 -04:00
|
|
|
|
|
|
|
G_OBJECT_CLASS (meta_context_parent_class)->dispose (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_context_finalize (GObject *object)
|
|
|
|
{
|
|
|
|
MetaContext *context = META_CONTEXT (object);
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
2022-10-12 16:30:07 -04:00
|
|
|
#ifdef HAVE_PROFILER
|
|
|
|
g_clear_object (&priv->profiler);
|
2023-05-10 16:26:08 -04:00
|
|
|
g_clear_pointer (&priv->trace_file, g_free);
|
2022-10-12 16:30:07 -04:00
|
|
|
#endif
|
|
|
|
|
2021-03-03 17:02:02 -05:00
|
|
|
g_clear_pointer (&priv->gnome_wm_keybindings, g_free);
|
2021-03-02 05:48:22 -05:00
|
|
|
g_clear_pointer (&priv->plugin_name, g_free);
|
2021-03-02 03:31:19 -05:00
|
|
|
g_clear_pointer (&priv->name, g_free);
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (meta_context_parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_context_class_init (MetaContextClass *klass)
|
|
|
|
{
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
object_class->get_property = meta_context_get_property;
|
|
|
|
object_class->set_property = meta_context_set_property;
|
2021-05-10 15:43:18 -04:00
|
|
|
object_class->dispose = meta_context_dispose;
|
2021-03-02 03:31:19 -05:00
|
|
|
object_class->finalize = meta_context_finalize;
|
|
|
|
|
2021-03-02 10:46:05 -05:00
|
|
|
klass->configure = meta_context_real_configure;
|
2021-03-02 05:41:34 -05:00
|
|
|
klass->setup = meta_context_real_setup;
|
|
|
|
|
2021-03-02 03:31:19 -05:00
|
|
|
obj_props[PROP_NAME] =
|
2023-06-28 08:02:43 -04:00
|
|
|
g_param_spec_string ("name", NULL, NULL,
|
2021-03-02 03:31:19 -05:00
|
|
|
NULL,
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2021-09-01 15:12:03 -04:00
|
|
|
obj_props[PROP_UNSAFE_MODE] =
|
2023-06-28 08:02:43 -04:00
|
|
|
g_param_spec_boolean ("unsafe-mode", NULL, NULL,
|
2021-09-01 15:12:03 -04:00
|
|
|
FALSE,
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
G_PARAM_EXPLICIT_NOTIFY |
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2021-03-02 03:31:19 -05:00
|
|
|
g_object_class_install_properties (object_class, N_PROPS, obj_props);
|
2022-11-24 10:21:07 -05:00
|
|
|
|
|
|
|
signals[STARTED] =
|
|
|
|
g_signal_new ("started",
|
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
0,
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
G_TYPE_NONE, 0);
|
|
|
|
signals[PREPARE_SHUTDOWN] =
|
|
|
|
g_signal_new ("prepare-shutdown",
|
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
0,
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
G_TYPE_NONE, 0);
|
2021-03-02 03:31:19 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_context_init (MetaContext *context)
|
|
|
|
{
|
2021-03-02 10:46:05 -05:00
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
2022-01-14 05:33:22 -05:00
|
|
|
g_autoptr (GError) error = NULL;
|
2021-03-02 10:46:05 -05:00
|
|
|
|
2021-03-03 07:55:32 -05:00
|
|
|
priv->plugin_gtype = G_TYPE_NONE;
|
2021-03-03 17:02:02 -05:00
|
|
|
priv->gnome_wm_keybindings = g_strdup ("Mutter");
|
2021-03-03 07:55:32 -05:00
|
|
|
|
2021-03-02 04:51:18 -05:00
|
|
|
if (!setlocale (LC_ALL, ""))
|
|
|
|
g_warning ("Locale not understood by C library");
|
|
|
|
bindtextdomain (GETTEXT_PACKAGE, MUTTER_LOCALEDIR);
|
|
|
|
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
2021-03-02 10:46:05 -05:00
|
|
|
|
|
|
|
priv->option_context = g_option_context_new (NULL);
|
|
|
|
g_option_context_set_main_group (priv->option_context,
|
|
|
|
g_option_group_new (NULL, NULL, NULL,
|
|
|
|
context, NULL));
|
2022-01-14 05:33:22 -05:00
|
|
|
|
|
|
|
if (!meta_context_save_rlimit_nofile (context, &error))
|
|
|
|
{
|
|
|
|
if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOSYS))
|
|
|
|
g_warning ("Failed to save the nofile limit: %s", error->message);
|
|
|
|
}
|
2021-03-02 03:31:19 -05:00
|
|
|
}
|
2023-10-31 10:30:17 -04:00
|
|
|
|
|
|
|
MetaDebugControl *
|
|
|
|
meta_context_get_debug_control (MetaContext *context)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
|
|
|
return priv->debug_control;
|
|
|
|
}
|