2021-03-03 05:31:24 -05:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2001 Havoc Pennington
|
|
|
|
* Copyright (C) 2006 Elijah Newren
|
|
|
|
* Copyright (C) 2021 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-main.h"
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
#include <gio/gio.h>
|
|
|
|
|
|
|
|
#if defined(HAVE_NATIVE_BACKEND) && defined(HAVE_WAYLAND)
|
|
|
|
#include <systemd/sd-login.h>
|
|
|
|
#endif /* HAVE_WAYLAND && HAVE_NATIVE_BACKEND */
|
|
|
|
|
|
|
|
#include "backends/meta-monitor-manager-private.h"
|
|
|
|
#include "backends/meta-virtual-monitor.h"
|
|
|
|
#include "backends/x11/cm/meta-backend-x11-cm.h"
|
|
|
|
#include "meta/meta-backend.h"
|
|
|
|
#include "wayland/meta-wayland.h"
|
|
|
|
#include "x11/session.h"
|
|
|
|
|
|
|
|
#ifdef HAVE_NATIVE_BACKEND
|
|
|
|
#include "backends/native/meta-backend-native.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
#include "backends/x11/nested/meta-backend-x11-nested.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
typedef struct _MetaContextMainOptions
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
char *display_name;
|
|
|
|
gboolean replace;
|
|
|
|
gboolean sync;
|
|
|
|
gboolean force;
|
|
|
|
} x11;
|
|
|
|
struct {
|
|
|
|
char *save_file;
|
|
|
|
char *client_id;
|
|
|
|
gboolean disable;
|
|
|
|
} sm;
|
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
gboolean wayland;
|
|
|
|
gboolean nested;
|
|
|
|
gboolean no_x11;
|
|
|
|
char *wayland_display;
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_NATIVE_BACKEND
|
|
|
|
gboolean display_server;
|
|
|
|
gboolean headless;
|
|
|
|
#endif
|
2021-09-02 12:41:16 -04:00
|
|
|
gboolean unsafe_mode;
|
2021-03-03 05:31:24 -05:00
|
|
|
#ifdef HAVE_NATIVE_BACKEND
|
|
|
|
GList *virtual_monitor_infos;
|
|
|
|
#endif
|
|
|
|
} MetaContextMainOptions;
|
|
|
|
|
|
|
|
struct _MetaContextMain
|
|
|
|
{
|
|
|
|
GObject parent;
|
|
|
|
|
|
|
|
MetaContextMainOptions options;
|
|
|
|
|
|
|
|
MetaCompositorType compositor_type;
|
|
|
|
|
|
|
|
GList *persistent_virtual_monitors;
|
|
|
|
};
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (MetaContextMain, meta_context_main, META_TYPE_CONTEXT)
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
check_configuration (MetaContextMain *context_main,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
if (context_main->options.x11.force && context_main->options.no_x11)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
|
|
|
|
"Can't run in X11 mode with no X11");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (context_main->options.x11.force && context_main->options.wayland)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
|
|
|
|
"Can't run in X11 mode with Wayland enabled");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (context_main->options.x11.force && context_main->options.nested)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
|
|
|
|
"Can't run in X11 mode nested");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
#endif /* HAVE_WAYLAND */
|
|
|
|
|
|
|
|
#ifdef HAVE_NATIVE_BACKEND
|
|
|
|
if (context_main->options.x11.force && context_main->options.display_server)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
|
|
|
|
"Can't run in X11 mode as a display server");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (context_main->options.x11.force && context_main->options.headless)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
|
|
|
|
"Can't run in X11 mode headlessly");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (context_main->options.display_server && context_main->options.headless)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
|
|
|
|
"Can't run in display server mode headlessly");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
#endif /* HAVE_NATIVE_BACKEND */
|
|
|
|
|
|
|
|
if (context_main->options.sm.save_file &&
|
|
|
|
context_main->options.sm.client_id)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
|
|
|
|
"Can't specify both SM save file and SM client id");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(HAVE_WAYLAND) && defined(HAVE_NATIVE_BACKEND)
|
|
|
|
static gboolean
|
|
|
|
session_type_is_supported (const char *session_type)
|
|
|
|
{
|
|
|
|
return (g_strcmp0 (session_type, "x11") == 0) ||
|
|
|
|
(g_strcmp0 (session_type, "wayland") == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
find_session_type (GError **error)
|
|
|
|
{
|
|
|
|
char **sessions = NULL;
|
|
|
|
char *session_id;
|
|
|
|
char *session_type;
|
|
|
|
const char *session_type_env;
|
|
|
|
gboolean is_tty = FALSE;
|
|
|
|
int ret, i;
|
|
|
|
|
|
|
|
ret = sd_pid_get_session (0, &session_id);
|
|
|
|
if (ret == 0 && session_id != NULL)
|
|
|
|
{
|
|
|
|
ret = sd_session_get_type (session_id, &session_type);
|
|
|
|
free (session_id);
|
|
|
|
|
|
|
|
if (ret == 0)
|
|
|
|
{
|
|
|
|
if (session_type_is_supported (session_type))
|
|
|
|
goto out;
|
|
|
|
else
|
|
|
|
is_tty = g_strcmp0 (session_type, "tty") == 0;
|
|
|
|
free (session_type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (sd_uid_get_sessions (getuid (), 1, &sessions) > 0)
|
|
|
|
{
|
|
|
|
for (i = 0; sessions[i] != NULL; i++)
|
|
|
|
{
|
|
|
|
ret = sd_session_get_type (sessions[i], &session_type);
|
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (session_type_is_supported (session_type))
|
|
|
|
{
|
|
|
|
g_strfreev (sessions);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
free (session_type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_strfreev (sessions);
|
|
|
|
|
|
|
|
session_type_env = g_getenv ("XDG_SESSION_TYPE");
|
|
|
|
if (session_type_is_supported (session_type_env))
|
|
|
|
{
|
|
|
|
/* The string should be freeable */
|
|
|
|
session_type = strdup (session_type_env);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Legacy support for starting through xinit */
|
|
|
|
if (is_tty && (g_getenv ("MUTTER_DISPLAY") || g_getenv ("DISPLAY")))
|
|
|
|
{
|
|
|
|
session_type = strdup ("x11");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
|
|
"Unsupported session type");
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
out:
|
|
|
|
return session_type;
|
|
|
|
}
|
|
|
|
#else /* defined(HAVE_WAYLAND) && defined(HAVE_NATIVE_BACKEND) */
|
|
|
|
static char *
|
|
|
|
find_session_type (GError **error)
|
|
|
|
{
|
|
|
|
return g_strdup ("x11");
|
|
|
|
}
|
|
|
|
#endif /* defined(HAVE_WAYLAND) && defined(HAVE_NATIVE_BACKEND) */
|
|
|
|
|
|
|
|
static MetaCompositorType
|
|
|
|
determine_compositor_type (MetaContextMain *context_main,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
g_autofree char *session_type = NULL;
|
|
|
|
|
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
if (context_main->options.wayland ||
|
|
|
|
#ifdef HAVE_NATIVE_BACKEND
|
|
|
|
context_main->options.display_server ||
|
|
|
|
context_main->options.headless ||
|
|
|
|
#endif /* HAVE_NATIVE_BACKEND */
|
|
|
|
context_main->options.nested)
|
|
|
|
return META_COMPOSITOR_TYPE_WAYLAND;
|
|
|
|
#endif /* HAVE_WAYLAND */
|
|
|
|
|
|
|
|
if (context_main->options.x11.force)
|
|
|
|
return META_COMPOSITOR_TYPE_X11;
|
|
|
|
|
|
|
|
session_type = find_session_type (error);
|
|
|
|
if (!session_type)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (strcmp (session_type, "x11") == 0)
|
|
|
|
return META_COMPOSITOR_TYPE_X11;
|
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
else if (strcmp (session_type, "wayland") == 0)
|
|
|
|
return META_COMPOSITOR_TYPE_WAYLAND;
|
|
|
|
#endif
|
|
|
|
else
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
meta_context_main_configure (MetaContext *context,
|
|
|
|
int *argc,
|
|
|
|
char ***argv,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
MetaContextMain *context_main = META_CONTEXT_MAIN (context);
|
|
|
|
MetaContextClass *context_class =
|
|
|
|
META_CONTEXT_CLASS (meta_context_main_parent_class);
|
|
|
|
|
|
|
|
if (!context_class->configure (context, argc, argv, error))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!check_configuration (context_main, error))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
context_main->compositor_type = determine_compositor_type (context_main,
|
|
|
|
error);
|
|
|
|
if (context_main->compositor_type == -1)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
if (context_main->options.wayland_display)
|
|
|
|
meta_wayland_override_display_name (context_main->options.wayland_display);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MetaCompositorType
|
|
|
|
meta_context_main_get_compositor_type (MetaContext *context)
|
|
|
|
{
|
|
|
|
MetaContextMain *context_main = META_CONTEXT_MAIN (context);
|
|
|
|
|
|
|
|
return context_main->compositor_type;
|
|
|
|
}
|
|
|
|
|
2021-04-16 14:34:29 -04:00
|
|
|
static MetaX11DisplayPolicy
|
|
|
|
meta_context_main_get_x11_display_policy (MetaContext *context)
|
|
|
|
{
|
|
|
|
MetaCompositorType compositor_type;
|
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
MetaContextMain *context_main = META_CONTEXT_MAIN (context);
|
|
|
|
char *unit;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
compositor_type = meta_context_get_compositor_type (context);
|
|
|
|
switch (compositor_type)
|
|
|
|
{
|
|
|
|
case META_COMPOSITOR_TYPE_X11:
|
|
|
|
return META_X11_DISPLAY_POLICY_MANDATORY;
|
|
|
|
case META_COMPOSITOR_TYPE_WAYLAND:
|
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
if (context_main->options.no_x11)
|
|
|
|
return META_X11_DISPLAY_POLICY_DISABLED;
|
|
|
|
else if (sd_pid_get_user_unit (0, &unit) < 0)
|
|
|
|
return META_X11_DISPLAY_POLICY_MANDATORY;
|
|
|
|
else
|
|
|
|
return META_X11_DISPLAY_POLICY_ON_DEMAND;
|
|
|
|
#else /* HAVE_WAYLAND */
|
|
|
|
g_assert_not_reached ();
|
|
|
|
#endif /* HAVE_WAYLAND */
|
|
|
|
}
|
|
|
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
|
2021-04-19 10:13:47 -04:00
|
|
|
static gboolean
|
|
|
|
meta_context_main_is_replacing (MetaContext *context)
|
|
|
|
{
|
|
|
|
MetaContextMain *context_main = META_CONTEXT_MAIN (context);
|
|
|
|
|
|
|
|
return context_main->options.x11.replace;
|
|
|
|
}
|
|
|
|
|
2021-03-03 05:31:24 -05:00
|
|
|
#ifdef HAVE_NATIVE_BACKEND
|
|
|
|
static gboolean
|
|
|
|
add_persistent_virtual_monitors (MetaContextMain *context_main,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
MetaBackend *backend = meta_get_backend ();
|
|
|
|
MetaMonitorManager *monitor_manager =
|
|
|
|
meta_backend_get_monitor_manager (backend);
|
|
|
|
GList *l;
|
|
|
|
|
|
|
|
for (l = context_main->options.virtual_monitor_infos; l; l = l->next)
|
|
|
|
{
|
|
|
|
MetaVirtualMonitorInfo *info = l->data;
|
|
|
|
MetaVirtualMonitor *virtual_monitor;
|
|
|
|
|
|
|
|
virtual_monitor =
|
|
|
|
meta_monitor_manager_create_virtual_monitor (monitor_manager,
|
|
|
|
info,
|
|
|
|
error);
|
|
|
|
if (!virtual_monitor)
|
|
|
|
{
|
|
|
|
g_prefix_error (error, "Failed to add virtual monitor: ");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
context_main->persistent_virtual_monitors =
|
|
|
|
g_list_append (context_main->persistent_virtual_monitors, virtual_monitor);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (context_main->options.virtual_monitor_infos)
|
|
|
|
{
|
|
|
|
g_list_free_full (context_main->options.virtual_monitor_infos,
|
|
|
|
(GDestroyNotify) meta_virtual_monitor_info_free);
|
|
|
|
context_main->options.virtual_monitor_infos = NULL;
|
|
|
|
|
|
|
|
meta_monitor_manager_reload (monitor_manager);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
meta_context_main_setup (MetaContext *context,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
MetaContextMain *context_main = META_CONTEXT_MAIN (context);
|
|
|
|
|
|
|
|
if (!META_CONTEXT_CLASS (meta_context_main_parent_class)->setup (context,
|
|
|
|
error))
|
|
|
|
return FALSE;
|
|
|
|
|
2021-09-02 12:41:16 -04:00
|
|
|
meta_context_set_unsafe_mode (context, context_main->options.unsafe_mode);
|
2021-03-03 05:31:24 -05:00
|
|
|
|
|
|
|
#ifdef HAVE_NATIVE_BACKEND
|
|
|
|
if (!add_persistent_virtual_monitors (context_main, error))
|
|
|
|
return FALSE;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MetaBackend *
|
|
|
|
create_x11_cm_backend (MetaContext *context,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
MetaContextMain *context_main = META_CONTEXT_MAIN (context);
|
|
|
|
|
|
|
|
#ifdef HAVE_NATIVE_BACKEND
|
|
|
|
if (context_main->options.virtual_monitor_infos)
|
|
|
|
g_warning ("Ignoring added virtual monitors in X11 session");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return g_initable_new (META_TYPE_BACKEND_X11_CM,
|
|
|
|
NULL, error,
|
2021-03-03 08:31:56 -05:00
|
|
|
"context", context,
|
2021-03-03 05:31:24 -05:00
|
|
|
"display-name", context_main->options.x11.display_name,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
static MetaBackend *
|
|
|
|
create_nested_backend (MetaContext *context,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
return g_initable_new (META_TYPE_BACKEND_X11_NESTED,
|
|
|
|
NULL, error,
|
2021-03-03 08:31:56 -05:00
|
|
|
"context", context,
|
2021-03-03 05:31:24 -05:00
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_NATIVE_BACKEND
|
|
|
|
static MetaBackend *
|
|
|
|
create_headless_backend (MetaContext *context,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
return g_initable_new (META_TYPE_BACKEND_NATIVE,
|
|
|
|
NULL, error,
|
2021-03-03 08:31:56 -05:00
|
|
|
"context", context,
|
2021-05-17 13:13:40 -04:00
|
|
|
"mode", META_BACKEND_NATIVE_MODE_HEADLESS,
|
2021-03-03 05:31:24 -05:00
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static MetaBackend *
|
|
|
|
create_native_backend (MetaContext *context,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
return g_initable_new (META_TYPE_BACKEND_NATIVE,
|
|
|
|
NULL, error,
|
2021-03-03 08:31:56 -05:00
|
|
|
"context", context,
|
2021-03-03 05:31:24 -05:00
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
#endif /* HAVE_NATIVE_BACKEND */
|
|
|
|
#endif /* HAVE_WAYLAND */
|
|
|
|
|
|
|
|
static MetaBackend *
|
|
|
|
meta_context_main_create_backend (MetaContext *context,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
MetaContextMain *context_main = META_CONTEXT_MAIN (context);
|
|
|
|
#endif
|
|
|
|
MetaCompositorType compositor_type;
|
|
|
|
|
|
|
|
compositor_type = meta_context_get_compositor_type (context);
|
|
|
|
switch (compositor_type)
|
|
|
|
{
|
2022-05-26 08:54:15 -04:00
|
|
|
#ifdef HAVE_X11
|
2021-03-03 05:31:24 -05:00
|
|
|
case META_COMPOSITOR_TYPE_X11:
|
|
|
|
return create_x11_cm_backend (context, error);
|
2022-05-26 08:54:15 -04:00
|
|
|
#endif
|
2021-03-03 05:31:24 -05:00
|
|
|
case META_COMPOSITOR_TYPE_WAYLAND:
|
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
if (context_main->options.nested)
|
|
|
|
return create_nested_backend (context, error);
|
|
|
|
#ifdef HAVE_NATIVE_BACKEND
|
|
|
|
else if (context_main->options.headless)
|
|
|
|
return create_headless_backend (context, error);
|
|
|
|
else
|
|
|
|
return create_native_backend (context, error);
|
|
|
|
#endif /* HAVE_NATIVE_BACKEND */
|
|
|
|
#else /* HAVE_WAYLAND */
|
|
|
|
g_assert_not_reached ();
|
|
|
|
#endif /* HAVE_WAYLAND */
|
|
|
|
}
|
|
|
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_context_main_notify_ready (MetaContext *context)
|
|
|
|
{
|
|
|
|
MetaContextMain *context_main = META_CONTEXT_MAIN (context);
|
|
|
|
|
|
|
|
if (!context_main->options.sm.disable)
|
|
|
|
{
|
2021-03-03 11:23:44 -05:00
|
|
|
meta_session_init (context,
|
|
|
|
context_main->options.sm.client_id,
|
2021-03-03 05:31:24 -05:00
|
|
|
context_main->options.sm.save_file);
|
|
|
|
}
|
|
|
|
g_clear_pointer (&context_main->options.sm.client_id, g_free);
|
|
|
|
g_clear_pointer (&context_main->options.sm.save_file, g_free);
|
|
|
|
}
|
|
|
|
|
2022-05-30 14:27:02 -04:00
|
|
|
#ifdef HAVE_X11
|
|
|
|
static gboolean
|
|
|
|
meta_context_main_is_x11_sync (MetaContext *context)
|
|
|
|
{
|
|
|
|
MetaContextMain *context_main = META_CONTEXT_MAIN (context);
|
|
|
|
|
|
|
|
return context_main->options.x11.sync || g_getenv ("MUTTER_SYNC");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-03-03 05:31:24 -05:00
|
|
|
#ifdef HAVE_NATIVE_BACKEND
|
|
|
|
static gboolean
|
|
|
|
add_virtual_monitor_cb (const char *option_name,
|
|
|
|
const char *value,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
MetaContextMain *context_main = user_data;
|
|
|
|
int width, height;
|
|
|
|
float refresh_rate = 60.0;
|
|
|
|
|
|
|
|
if (sscanf (value, "%dx%d@%f",
|
|
|
|
&width, &height, &refresh_rate) == 3 ||
|
|
|
|
sscanf (value, "%dx%d",
|
|
|
|
&width, &height) == 2)
|
|
|
|
{
|
|
|
|
g_autofree char *serial = NULL;
|
|
|
|
MetaVirtualMonitorInfo *virtual_monitor;
|
|
|
|
int n_existing_virtual_monitor_infos;
|
|
|
|
|
|
|
|
n_existing_virtual_monitor_infos =
|
|
|
|
g_list_length (context_main->options.virtual_monitor_infos);
|
|
|
|
serial = g_strdup_printf ("0x%.2x", n_existing_virtual_monitor_infos);
|
|
|
|
virtual_monitor = meta_virtual_monitor_info_new (width,
|
|
|
|
height,
|
|
|
|
refresh_rate,
|
|
|
|
"MetaVendor",
|
|
|
|
"MetaVirtualMonitor",
|
|
|
|
serial);
|
|
|
|
context_main->options.virtual_monitor_infos =
|
|
|
|
g_list_append (context_main->options.virtual_monitor_infos,
|
|
|
|
virtual_monitor);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
|
|
|
|
"Unrecognizable virtual monitor spec '%s'", value);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* HAVE_NATIVE_BACKEND */
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_context_main_add_option_entries (MetaContextMain *context_main)
|
|
|
|
{
|
|
|
|
MetaContext *context = META_CONTEXT (context_main);
|
|
|
|
GOptionEntry options[] = {
|
2022-05-26 08:54:15 -04:00
|
|
|
#ifdef HAVE_X11
|
2021-03-03 05:31:24 -05:00
|
|
|
{
|
|
|
|
"replace", 'r', 0, G_OPTION_ARG_NONE,
|
|
|
|
&context_main->options.x11.replace,
|
|
|
|
N_("Replace the running window manager"),
|
|
|
|
NULL
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"display", 'd', 0, G_OPTION_ARG_STRING,
|
|
|
|
&context_main->options.x11.display_name,
|
|
|
|
N_("X Display to use"),
|
|
|
|
"DISPLAY"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"sm-disable", 0, 0, G_OPTION_ARG_NONE,
|
|
|
|
&context_main->options.sm.disable,
|
|
|
|
N_("Disable connection to session manager"),
|
|
|
|
NULL
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"sm-client-id", 0, 0, G_OPTION_ARG_STRING,
|
|
|
|
&context_main->options.sm.client_id,
|
|
|
|
N_("Specify session management ID"),
|
|
|
|
"ID"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"sm-save-file", 0, 0, G_OPTION_ARG_FILENAME,
|
|
|
|
&context_main->options.sm.save_file,
|
|
|
|
N_("Initialize session from savefile"),
|
|
|
|
"FILE"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"sync", 0, 0, G_OPTION_ARG_NONE,
|
|
|
|
&context_main->options.x11.sync,
|
|
|
|
N_("Make X calls synchronous"),
|
|
|
|
NULL
|
|
|
|
},
|
2022-05-26 08:54:15 -04:00
|
|
|
#endif
|
2021-03-03 05:31:24 -05:00
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
{
|
|
|
|
"wayland", 0, 0, G_OPTION_ARG_NONE,
|
|
|
|
&context_main->options.wayland,
|
|
|
|
N_("Run as a wayland compositor"),
|
|
|
|
NULL
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"nested", 0, 0, G_OPTION_ARG_NONE,
|
|
|
|
&context_main->options.nested,
|
|
|
|
N_("Run as a nested compositor"),
|
|
|
|
NULL
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"no-x11", 0, 0, G_OPTION_ARG_NONE,
|
|
|
|
&context_main->options.no_x11,
|
|
|
|
N_("Run wayland compositor without starting Xwayland"),
|
|
|
|
NULL
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"wayland-display", 0, 0, G_OPTION_ARG_STRING,
|
|
|
|
&context_main->options.wayland_display,
|
|
|
|
N_("Specify Wayland display name to use"),
|
|
|
|
NULL
|
|
|
|
},
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_NATIVE_BACKEND
|
|
|
|
{
|
|
|
|
"display-server", 0, 0, G_OPTION_ARG_NONE,
|
|
|
|
&context_main->options.display_server,
|
|
|
|
N_("Run as a full display server, rather than nested")
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"headless", 0, 0, G_OPTION_ARG_NONE,
|
|
|
|
&context_main->options.headless,
|
|
|
|
N_("Run as a headless display server")
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"virtual-monitor", 0, 0, G_OPTION_ARG_CALLBACK,
|
|
|
|
add_virtual_monitor_cb,
|
|
|
|
N_("Add persistent virtual monitor (WxH or WxH@R)")
|
|
|
|
},
|
|
|
|
#endif
|
2021-09-02 12:41:16 -04:00
|
|
|
{
|
|
|
|
"unsafe-mode", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE,
|
|
|
|
&context_main->options.unsafe_mode,
|
|
|
|
"Run in unsafe mode"
|
|
|
|
},
|
2022-05-26 08:54:15 -04:00
|
|
|
#ifdef HAVE_X11
|
2021-03-03 05:31:24 -05:00
|
|
|
{
|
|
|
|
"x11", 0, 0, G_OPTION_ARG_NONE,
|
|
|
|
&context_main->options.x11.force,
|
|
|
|
N_("Run with X11 backend")
|
|
|
|
},
|
2022-05-26 08:54:15 -04:00
|
|
|
#endif
|
2021-03-03 05:31:24 -05:00
|
|
|
{ NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
meta_context_add_option_entries (context, options, GETTEXT_PACKAGE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* meta_create_context:
|
|
|
|
* @name: Human readable name of display server or window manager
|
|
|
|
*
|
|
|
|
* Create a context.
|
|
|
|
*
|
|
|
|
* Returns: (transfer full): A new context instance.
|
|
|
|
*/
|
|
|
|
MetaContext *
|
|
|
|
meta_create_context (const char *name)
|
|
|
|
{
|
|
|
|
return g_object_new (META_TYPE_CONTEXT_MAIN,
|
|
|
|
"name", name,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_context_main_finalize (GObject *object)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_NATIVE_BACKEND
|
|
|
|
MetaContextMain *context_main = META_CONTEXT_MAIN (object);
|
|
|
|
|
|
|
|
g_list_free_full (context_main->persistent_virtual_monitors, g_object_unref);
|
|
|
|
context_main->persistent_virtual_monitors = NULL;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (meta_context_main_parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_context_main_constructed (GObject *object)
|
|
|
|
{
|
|
|
|
MetaContextMain *context_main = META_CONTEXT_MAIN (object);
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (meta_context_main_parent_class)->constructed (object);
|
|
|
|
|
|
|
|
meta_context_main_add_option_entries (context_main);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_context_main_class_init (MetaContextMainClass *klass)
|
|
|
|
{
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
MetaContextClass *context_class = META_CONTEXT_CLASS (klass);
|
|
|
|
|
|
|
|
object_class->finalize = meta_context_main_finalize;
|
|
|
|
object_class->constructed = meta_context_main_constructed;
|
|
|
|
|
|
|
|
context_class->configure = meta_context_main_configure;
|
|
|
|
context_class->get_compositor_type = meta_context_main_get_compositor_type;
|
2021-04-16 14:34:29 -04:00
|
|
|
context_class->get_x11_display_policy =
|
|
|
|
meta_context_main_get_x11_display_policy;
|
2021-04-19 10:13:47 -04:00
|
|
|
context_class->is_replacing = meta_context_main_is_replacing;
|
2021-03-03 05:31:24 -05:00
|
|
|
context_class->setup = meta_context_main_setup;
|
|
|
|
context_class->create_backend = meta_context_main_create_backend;
|
|
|
|
context_class->notify_ready = meta_context_main_notify_ready;
|
2022-05-30 14:27:02 -04:00
|
|
|
#ifdef HAVE_X11
|
|
|
|
context_class->is_x11_sync = meta_context_main_is_x11_sync;
|
|
|
|
#endif
|
2021-03-03 05:31:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_context_main_init (MetaContextMain *context_main)
|
|
|
|
{
|
|
|
|
context_main->compositor_type = -1;
|
|
|
|
}
|