2021-03-02 08:31:19 +00: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
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
* 02111-1307, USA.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include "core/meta-context-private.h"
|
|
|
|
|
2021-03-02 09:51:18 +00:00
|
|
|
#include <locale.h>
|
2022-01-14 10:33:22 +00:00
|
|
|
#include <sys/resource.h>
|
2021-03-02 09:51:18 +00:00
|
|
|
|
2021-03-02 10:41:34 +00:00
|
|
|
#include "backends/meta-backend-private.h"
|
2021-03-02 10:48:22 +00:00
|
|
|
#include "compositor/meta-plugin-manager.h"
|
2021-03-02 10:53:59 +00:00
|
|
|
#include "core/display-private.h"
|
2021-03-02 10:57:57 +00:00
|
|
|
#include "core/prefs-private.h"
|
2021-03-02 09:35:38 +00:00
|
|
|
#include "core/util-private.h"
|
|
|
|
|
2021-03-02 10:53:59 +00:00
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
#include "wayland/meta-wayland.h"
|
|
|
|
#endif
|
|
|
|
|
2021-03-02 08:31:19 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
PROP_0,
|
|
|
|
|
|
|
|
PROP_NAME,
|
2021-09-01 19:12:03 +00:00
|
|
|
PROP_UNSAFE_MODE,
|
2021-03-02 08:31:19 +00:00
|
|
|
|
|
|
|
N_PROPS
|
|
|
|
};
|
|
|
|
|
|
|
|
static GParamSpec *obj_props[N_PROPS];
|
|
|
|
|
2021-03-03 22:02:50 +00: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 08:31:19 +00:00
|
|
|
typedef struct _MetaContextPrivate
|
|
|
|
{
|
|
|
|
char *name;
|
2021-03-02 10:48:22 +00:00
|
|
|
char *plugin_name;
|
2021-03-03 12:55:32 +00:00
|
|
|
GType plugin_gtype;
|
2021-03-03 22:02:02 +00:00
|
|
|
char *gnome_wm_keybindings;
|
2021-03-02 10:53:59 +00:00
|
|
|
|
2021-09-01 19:12:03 +00:00
|
|
|
gboolean unsafe_mode;
|
|
|
|
|
2021-03-03 22:02:50 +00:00
|
|
|
MetaContextState state;
|
|
|
|
|
2021-03-02 15:46:05 +00:00
|
|
|
GOptionContext *option_context;
|
|
|
|
|
2021-03-03 13:31:56 +00:00
|
|
|
MetaBackend *backend;
|
2021-03-03 14:12:19 +00:00
|
|
|
MetaDisplay *display;
|
2021-03-03 21:00:05 +00:00
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
MetaWaylandCompositor *wayland_compositor;
|
|
|
|
#endif
|
2021-03-03 13:31:56 +00:00
|
|
|
|
2021-03-02 10:53:59 +00:00
|
|
|
GMainLoop *main_loop;
|
|
|
|
GError *termination_error;
|
2022-01-14 10:33:22 +00:00
|
|
|
#ifdef RLIMIT_NOFILE
|
|
|
|
struct rlimit saved_rlimit_nofile;
|
|
|
|
#endif
|
2021-03-02 08:31:19 +00:00
|
|
|
} MetaContextPrivate;
|
|
|
|
|
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE (MetaContext, meta_context, G_TYPE_OBJECT)
|
|
|
|
|
2021-08-26 10:42:31 +00: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 15:46:05 +00: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 22:02:50 +00:00
|
|
|
g_warn_if_fail (priv->state == META_CONTEXT_STATE_INIT);
|
|
|
|
|
2021-03-02 15:46:05 +00:00
|
|
|
g_option_context_add_main_entries (priv->option_context,
|
|
|
|
entries,
|
|
|
|
translation_domain);
|
|
|
|
}
|
|
|
|
|
2021-08-26 10:42:31 +00: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 12:56:32 +00:00
|
|
|
void
|
|
|
|
meta_context_add_option_group (MetaContext *context,
|
|
|
|
GOptionGroup *group)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
2021-03-03 22:02:50 +00:00
|
|
|
g_warn_if_fail (priv->state == META_CONTEXT_STATE_INIT);
|
2021-03-03 12:56:32 +00:00
|
|
|
g_return_if_fail (priv->option_context);
|
|
|
|
|
|
|
|
g_option_context_add_group (priv->option_context, group);
|
|
|
|
}
|
|
|
|
|
2021-03-03 12:55:32 +00:00
|
|
|
void
|
|
|
|
meta_context_set_plugin_gtype (MetaContext *context,
|
|
|
|
GType plugin_gtype)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
2021-03-03 22:02:50 +00:00
|
|
|
g_return_if_fail (priv->state <= META_CONTEXT_STATE_CONFIGURED);
|
2021-03-03 12:55:32 +00:00
|
|
|
g_return_if_fail (!priv->plugin_name);
|
|
|
|
|
|
|
|
priv->plugin_gtype = plugin_gtype;
|
|
|
|
}
|
|
|
|
|
2021-03-02 10:48:22 +00:00
|
|
|
void
|
|
|
|
meta_context_set_plugin_name (MetaContext *context,
|
|
|
|
const char *plugin_name)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
2021-03-03 22:02:50 +00:00
|
|
|
g_return_if_fail (priv->state <= META_CONTEXT_STATE_CONFIGURED);
|
2021-03-03 12:55:32 +00:00
|
|
|
g_return_if_fail (priv->plugin_gtype == G_TYPE_NONE);
|
|
|
|
|
2021-03-02 10:48:22 +00:00
|
|
|
priv->plugin_name = g_strdup (plugin_name);
|
|
|
|
}
|
|
|
|
|
2021-03-03 22:02:02 +00: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 22:02:50 +00:00
|
|
|
g_return_if_fail (priv->state <= META_CONTEXT_STATE_CONFIGURED);
|
|
|
|
|
2021-03-03 22:02:02 +00: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 11:07:10 +00:00
|
|
|
void
|
|
|
|
meta_context_notify_ready (MetaContext *context)
|
|
|
|
{
|
2021-03-03 22:02:50 +00: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);
|
|
|
|
|
2021-03-02 11:07:10 +00:00
|
|
|
META_CONTEXT_GET_CLASS (context)->notify_ready (context);
|
|
|
|
}
|
|
|
|
|
2021-03-03 21:12:01 +00:00
|
|
|
const char *
|
|
|
|
meta_context_get_name (MetaContext *context)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
|
|
|
return priv->name;
|
|
|
|
}
|
|
|
|
|
2021-03-03 13:31:56 +00: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 14:12:19 +00: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 21:00:05 +00:00
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
MetaWaylandCompositor *
|
|
|
|
meta_context_get_wayland_compositor (MetaContext *context)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
|
|
|
return priv->wayland_compositor;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-03-03 10:31:24 +00:00
|
|
|
MetaCompositorType
|
2021-03-02 09:35:38 +00:00
|
|
|
meta_context_get_compositor_type (MetaContext *context)
|
|
|
|
{
|
|
|
|
return META_CONTEXT_GET_CLASS (context)->get_compositor_type (context);
|
|
|
|
}
|
|
|
|
|
2021-04-19 14:13:47 +00:00
|
|
|
gboolean
|
|
|
|
meta_context_is_replacing (MetaContext *context)
|
|
|
|
{
|
|
|
|
return META_CONTEXT_GET_CLASS (context)->is_replacing (context);
|
|
|
|
}
|
|
|
|
|
2021-04-16 18:34:29 +00:00
|
|
|
MetaX11DisplayPolicy
|
|
|
|
meta_context_get_x11_display_policy (MetaContext *context)
|
|
|
|
{
|
|
|
|
return META_CONTEXT_GET_CLASS (context)->get_x11_display_policy (context);
|
|
|
|
}
|
|
|
|
|
2022-05-30 18:27:02 +00:00
|
|
|
#ifdef HAVE_X11
|
|
|
|
gboolean
|
|
|
|
meta_context_is_x11_sync (MetaContext *context)
|
|
|
|
{
|
|
|
|
return META_CONTEXT_GET_CLASS (context)->is_x11_sync (context);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-03-02 15:46:05 +00: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);
|
|
|
|
return g_option_context_parse (option_context, argc, argv, error);
|
|
|
|
}
|
|
|
|
|
2021-08-26 10:42:31 +00: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
|
|
|
|
* configuration has been successfull, %FALSE otherwise
|
|
|
|
*/
|
2021-03-02 09:35:38 +00:00
|
|
|
gboolean
|
|
|
|
meta_context_configure (MetaContext *context,
|
|
|
|
int *argc,
|
|
|
|
char ***argv,
|
|
|
|
GError **error)
|
|
|
|
{
|
2021-03-03 22:02:50 +00:00
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
2021-03-02 09:35:38 +00:00
|
|
|
MetaCompositorType compositor_type;
|
|
|
|
|
2021-03-03 22:02:50 +00:00
|
|
|
g_warn_if_fail (priv->state == META_CONTEXT_STATE_INIT);
|
|
|
|
|
2021-03-02 09:35:38 +00:00
|
|
|
if (!META_CONTEXT_GET_CLASS (context)->configure (context, argc, argv, error))
|
2021-03-03 22:02:50 +00:00
|
|
|
{
|
|
|
|
priv->state = META_CONTEXT_STATE_TERMINATED;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2021-03-02 09:35:38 +00: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 22:02:50 +00:00
|
|
|
priv->state = META_CONTEXT_STATE_CONFIGURED;
|
|
|
|
|
2021-03-02 09:35:38 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2021-03-02 10:41:34 +00: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 11:00:13 +00:00
|
|
|
static void
|
|
|
|
init_introspection (MetaContext *context)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_INTROSPECTION
|
|
|
|
g_irepository_prepend_search_path (MUTTER_PKGLIBDIR);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-03-02 10:41:34 +00:00
|
|
|
static gboolean
|
|
|
|
meta_context_real_setup (MetaContext *context,
|
|
|
|
GError **error)
|
|
|
|
{
|
2021-03-03 13:31:56 +00: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 10:41:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
meta_context_setup (MetaContext *context,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
MetaCompositorType compositor_type;
|
|
|
|
|
2021-03-03 22:02:50 +00:00
|
|
|
g_warn_if_fail (priv->state == META_CONTEXT_STATE_CONFIGURED);
|
|
|
|
|
2021-03-03 12:55:32 +00:00
|
|
|
if (!priv->plugin_name && priv->plugin_gtype == G_TYPE_NONE)
|
2021-03-02 10:48:22 +00:00
|
|
|
{
|
2021-03-03 22:02:50 +00:00
|
|
|
priv->state = META_CONTEXT_STATE_TERMINATED;
|
2021-03-02 10:48:22 +00:00
|
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
|
|
"No compositor plugin set");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2021-03-02 11:01:46 +00:00
|
|
|
meta_init_debug_utils ();
|
2021-03-02 10:59:39 +00:00
|
|
|
|
2021-03-02 10:41:34 +00: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 10:48:22 +00:00
|
|
|
|
2021-03-03 12:55:32 +00: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 10:48:22 +00:00
|
|
|
|
2021-03-02 11:00:13 +00:00
|
|
|
init_introspection (context);
|
|
|
|
|
2021-03-03 22:02:50 +00: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 10:41:34 +00:00
|
|
|
}
|
|
|
|
|
2021-03-02 10:53:59 +00:00
|
|
|
gboolean
|
|
|
|
meta_context_start (MetaContext *context,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
2021-03-03 22:02:50 +00:00
|
|
|
g_warn_if_fail (priv->state == META_CONTEXT_STATE_SETUP);
|
|
|
|
|
2021-03-02 10:57:57 +00:00
|
|
|
meta_prefs_init ();
|
|
|
|
|
2021-03-02 10:53:59 +00:00
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
if (meta_context_get_compositor_type (context) ==
|
|
|
|
META_COMPOSITOR_TYPE_WAYLAND)
|
2021-05-06 14:02:34 +00:00
|
|
|
priv->wayland_compositor = meta_wayland_compositor_new (context);
|
2021-03-02 10:53:59 +00:00
|
|
|
#endif
|
|
|
|
|
2021-03-03 15:05:09 +00:00
|
|
|
priv->display = meta_display_new (context, error);
|
2021-03-03 14:12:19 +00:00
|
|
|
if (!priv->display)
|
2021-03-03 22:02:50 +00:00
|
|
|
{
|
|
|
|
priv->state = META_CONTEXT_STATE_TERMINATED;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2021-03-02 10:53:59 +00:00
|
|
|
|
|
|
|
priv->main_loop = g_main_loop_new (NULL, FALSE);
|
|
|
|
|
2021-03-03 22:02:50 +00:00
|
|
|
priv->state = META_CONTEXT_STATE_STARTED;
|
|
|
|
|
2021-03-02 10:53:59 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
meta_context_run_main_loop (MetaContext *context,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
2021-03-03 22:02:50 +00:00
|
|
|
g_warn_if_fail (priv->state == META_CONTEXT_STATE_STARTED);
|
2021-03-02 10:53:59 +00:00
|
|
|
if (!priv->main_loop)
|
|
|
|
{
|
2021-03-03 22:02:50 +00:00
|
|
|
priv->state = META_CONTEXT_STATE_TERMINATED;
|
2021-03-02 10:53:59 +00: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 22:02:50 +00:00
|
|
|
priv->state = META_CONTEXT_STATE_RUNNING;
|
2021-03-02 10:53:59 +00:00
|
|
|
g_main_loop_run (priv->main_loop);
|
2021-03-03 22:02:50 +00:00
|
|
|
priv->state = META_CONTEXT_STATE_TERMINATED;
|
2021-03-02 10:53:59 +00: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 22:02:50 +00: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 10:53:59 +00: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 19:43:18 +00:00
|
|
|
void
|
|
|
|
meta_context_destroy (MetaContext *context)
|
|
|
|
{
|
|
|
|
g_object_run_dispose (G_OBJECT (context));
|
|
|
|
g_object_unref (context);
|
|
|
|
}
|
|
|
|
|
2021-09-01 19:12:03 +00:00
|
|
|
gboolean
|
|
|
|
meta_context_get_unsafe_mode (MetaContext *context)
|
|
|
|
{
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
|
|
|
|
|
|
|
return priv->unsafe_mode;
|
|
|
|
}
|
|
|
|
|
|
|
|
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 10:33:22 +00: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 08:31:19 +00: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 19:12:03 +00:00
|
|
|
case PROP_UNSAFE_MODE:
|
|
|
|
g_value_set_boolean (value, priv->unsafe_mode);
|
|
|
|
break;
|
2021-03-02 08:31:19 +00: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 19:12:03 +00:00
|
|
|
case PROP_UNSAFE_MODE:
|
|
|
|
meta_context_set_unsafe_mode (META_CONTEXT (object),
|
|
|
|
g_value_get_boolean (value));
|
|
|
|
break;
|
2021-03-02 08:31:19 +00:00
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-05-10 19:43:18 +00:00
|
|
|
meta_context_dispose (GObject *object)
|
2021-03-02 08:31:19 +00:00
|
|
|
{
|
|
|
|
MetaContext *context = META_CONTEXT (object);
|
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
2021-03-02 10:41:34 +00:00
|
|
|
|
2021-03-03 13:31:56 +00:00
|
|
|
if (priv->backend)
|
|
|
|
meta_backend_prepare_shutdown (priv->backend);
|
2021-03-02 10:41:34 +00:00
|
|
|
|
2021-03-02 10:53:59 +00:00
|
|
|
#ifdef HAVE_WAYLAND
|
2021-03-03 21:00:05 +00:00
|
|
|
if (priv->wayland_compositor)
|
|
|
|
meta_wayland_compositor_prepare_shutdown (priv->wayland_compositor);
|
2021-03-02 10:53:59 +00:00
|
|
|
#endif
|
|
|
|
|
2021-03-03 14:12:19 +00:00
|
|
|
if (priv->display)
|
|
|
|
meta_display_close (priv->display, META_CURRENT_TIME);
|
|
|
|
g_clear_object (&priv->display);
|
2021-03-02 10:53:59 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_WAYLAND
|
2021-03-03 21:00:05 +00:00
|
|
|
g_clear_object (&priv->wayland_compositor);
|
2021-03-02 10:53:59 +00:00
|
|
|
#endif
|
|
|
|
|
2021-03-03 13:31:56 +00:00
|
|
|
g_clear_pointer (&priv->backend, meta_backend_destroy);
|
2021-03-02 08:31:19 +00:00
|
|
|
|
2021-03-02 15:46:05 +00:00
|
|
|
g_clear_pointer (&priv->option_context, g_option_context_free);
|
2021-03-02 10:53:59 +00:00
|
|
|
g_clear_pointer (&priv->main_loop, g_main_loop_unref);
|
2021-05-10 19:43:18 +00: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);
|
|
|
|
|
2021-03-03 22:02:02 +00:00
|
|
|
g_clear_pointer (&priv->gnome_wm_keybindings, g_free);
|
2021-03-02 10:48:22 +00:00
|
|
|
g_clear_pointer (&priv->plugin_name, g_free);
|
2021-03-02 08:31:19 +00: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 19:43:18 +00:00
|
|
|
object_class->dispose = meta_context_dispose;
|
2021-03-02 08:31:19 +00:00
|
|
|
object_class->finalize = meta_context_finalize;
|
|
|
|
|
2021-03-02 15:46:05 +00:00
|
|
|
klass->configure = meta_context_real_configure;
|
2021-03-02 10:41:34 +00:00
|
|
|
klass->setup = meta_context_real_setup;
|
|
|
|
|
2021-03-02 08:31:19 +00:00
|
|
|
obj_props[PROP_NAME] =
|
|
|
|
g_param_spec_string ("name",
|
|
|
|
"name",
|
|
|
|
"Human readable name",
|
|
|
|
NULL,
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2021-09-01 19:12:03 +00:00
|
|
|
obj_props[PROP_UNSAFE_MODE] =
|
|
|
|
g_param_spec_boolean ("unsafe-mode",
|
|
|
|
"unsafe mode",
|
|
|
|
"Unsafe mode",
|
|
|
|
FALSE,
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
G_PARAM_EXPLICIT_NOTIFY |
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2021-03-02 08:31:19 +00:00
|
|
|
g_object_class_install_properties (object_class, N_PROPS, obj_props);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_context_init (MetaContext *context)
|
|
|
|
{
|
2021-03-02 15:46:05 +00:00
|
|
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
2022-01-14 10:33:22 +00:00
|
|
|
g_autoptr (GError) error = NULL;
|
2021-03-02 15:46:05 +00:00
|
|
|
|
2021-03-03 12:55:32 +00:00
|
|
|
priv->plugin_gtype = G_TYPE_NONE;
|
2021-03-03 22:02:02 +00:00
|
|
|
priv->gnome_wm_keybindings = g_strdup ("Mutter");
|
2021-03-03 12:55:32 +00:00
|
|
|
|
2021-03-02 09:51:18 +00: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 15:46:05 +00: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 10:33:22 +00: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 08:31:19 +00:00
|
|
|
}
|