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
|
2023-08-07 05:50:23 -04:00
|
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
2021-03-03 05:31:24 -05:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include "core/meta-context-main.h"
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
#include <gio/gio.h>
|
|
|
|
|
2024-01-03 04:52:08 -05:00
|
|
|
#ifdef HAVE_WAYLAND
|
2021-03-03 05:31:24 -05:00
|
|
|
#include <systemd/sd-login.h>
|
2024-01-03 04:52:08 -05:00
|
|
|
#endif
|
2021-03-03 05:31:24 -05:00
|
|
|
|
|
|
|
#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 "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"
|
2023-12-25 07:51:46 -05:00
|
|
|
#include "wayland/meta-wayland.h"
|
2021-03-03 05:31:24 -05:00
|
|
|
#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
|
2023-05-10 16:26:08 -04:00
|
|
|
char *trace_file;
|
2023-10-31 10:30:17 -04:00
|
|
|
gboolean debug_control;
|
2021-03-03 05:31:24 -05:00
|
|
|
} 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
|
|
|
|
|
core: Retrieve DESKTOP_AUTOSTART_ID early on startup
With the move away from GTK3, and the indirect dependency on GTK4
grown in the GNOME Shell side, we've indirectly gotten a small sneaky
behavioral change: The GTK4 library will, right on dlopen, get
DESKTOP_AUTOSTART_ID for itself and delete it from the environment.
This happens before our own X11 session management code is
initialized, which confuses the hell out of it, into thinking
initialization is actually shutdown, gnome-session does not follow
along with this request, which leaves GNOME Shell into a confused
startup state where it never calls SmcSaveYourselfDone() and grinds
startup to a halt until gnome-session decides to move things forward.
In order to fix this, get the DESKTOP_AUTOSTART_ID before we lend
control to GNOME Shell bits and GTK4 is possibly initialized, and
feed it directly to our X11 session manager bits.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2906>
2023-03-09 11:34:22 -05:00
|
|
|
if (!context_main->options.sm.client_id)
|
|
|
|
{
|
|
|
|
const char *desktop_autostart_id;
|
|
|
|
|
|
|
|
desktop_autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID");
|
|
|
|
if (desktop_autostart_id)
|
|
|
|
context_main->options.sm.client_id = g_strdup (desktop_autostart_id);
|
|
|
|
}
|
|
|
|
|
2023-05-10 16:26:08 -04:00
|
|
|
#ifdef HAVE_PROFILER
|
|
|
|
meta_context_set_trace_file (context, context_main->options.trace_file);
|
|
|
|
#endif
|
|
|
|
|
2023-10-31 10:30:17 -04:00
|
|
|
if (context_main->options.debug_control)
|
|
|
|
{
|
|
|
|
MetaDebugControl *debug_control = meta_context_get_debug_control (context);
|
|
|
|
|
|
|
|
meta_debug_control_export (debug_control);
|
|
|
|
}
|
|
|
|
|
core: Retrieve DESKTOP_AUTOSTART_ID early on startup
With the move away from GTK3, and the indirect dependency on GTK4
grown in the GNOME Shell side, we've indirectly gotten a small sneaky
behavioral change: The GTK4 library will, right on dlopen, get
DESKTOP_AUTOSTART_ID for itself and delete it from the environment.
This happens before our own X11 session management code is
initialized, which confuses the hell out of it, into thinking
initialization is actually shutdown, gnome-session does not follow
along with this request, which leaves GNOME Shell into a confused
startup state where it never calls SmcSaveYourselfDone() and grinds
startup to a halt until gnome-session decides to move things forward.
In order to fix this, get the DESKTOP_AUTOSTART_ID before we lend
control to GNOME Shell bits and GTK4 is possibly initialized, and
feed it directly to our X11 session manager bits.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2906>
2023-03-09 11:34:22 -05:00
|
|
|
g_unsetenv ("DESKTOP_AUTOSTART_ID");
|
|
|
|
|
2021-03-03 05:31:24 -05:00
|
|
|
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);
|
2023-08-12 09:32:18 -04:00
|
|
|
g_autofree char *unit = NULL;
|
2021-04-16 14:34:29 -04:00
|
|
|
#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)
|
|
|
|
{
|
2022-05-27 16:27:07 -04:00
|
|
|
MetaContext *context = META_CONTEXT (context_main);
|
|
|
|
MetaBackend *backend = meta_context_get_backend (context);
|
2021-03-03 05:31:24 -05:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-01-22 10:56:45 -05:00
|
|
|
#ifdef HAVE_X11
|
2021-03-03 05:31:24 -05:00
|
|
|
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);
|
|
|
|
}
|
2024-01-22 10:56:45 -05:00
|
|
|
#endif
|
2021-03-03 05:31:24 -05:00
|
|
|
|
2024-01-22 10:56:45 -05:00
|
|
|
#if defined (HAVE_X11) && defined (HAVE_WAYLAND)
|
2021-03-03 05:31:24 -05:00
|
|
|
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);
|
|
|
|
}
|
2024-01-22 10:56:45 -05:00
|
|
|
#endif
|
2021-03-03 05:31:24 -05:00
|
|
|
|
2024-01-22 10:56:45 -05:00
|
|
|
#ifdef HAVE_WAYLAND
|
2021-03-03 05:31:24 -05:00
|
|
|
#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)
|
|
|
|
{
|
|
|
|
case META_COMPOSITOR_TYPE_X11:
|
2024-01-22 10:56:45 -05:00
|
|
|
#ifdef HAVE_X11
|
2021-03-03 05:31:24 -05:00
|
|
|
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
|
2024-01-22 10:56:45 -05:00
|
|
|
#ifdef HAVE_X11
|
2021-03-03 05:31:24 -05:00
|
|
|
if (context_main->options.nested)
|
|
|
|
return create_nested_backend (context, error);
|
2024-01-22 10:56:45 -05:00
|
|
|
else
|
|
|
|
#endif
|
2021-03-03 05:31:24 -05:00
|
|
|
#ifdef HAVE_NATIVE_BACKEND
|
2024-01-22 10:56:45 -05:00
|
|
|
if (context_main->options.headless)
|
2021-03-03 05:31:24 -05:00
|
|
|
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 ();
|
|
|
|
}
|
|
|
|
|
2024-01-22 10:56:45 -05:00
|
|
|
#ifdef HAVE_X11
|
2021-03-03 05:31:24 -05:00
|
|
|
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
|
|
|
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;
|
2023-03-07 16:39:57 -05:00
|
|
|
float refresh_rate;
|
2021-03-03 05:31:24 -05:00
|
|
|
|
2023-03-07 16:39:57 -05:00
|
|
|
if (meta_parse_monitor_mode (value, &width, &height, &refresh_rate, 60.0))
|
2021-03-03 05:31:24 -05:00
|
|
|
{
|
|
|
|
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
|
2023-05-10 16:26:08 -04:00
|
|
|
{
|
|
|
|
"profile", 0, 0, G_OPTION_ARG_FILENAME,
|
|
|
|
&context_main->options.trace_file,
|
|
|
|
N_("Profile performance using trace instrumentation"),
|
|
|
|
"FILE"
|
|
|
|
},
|
2023-10-31 10:30:17 -04:00
|
|
|
{
|
|
|
|
"debug-control", 0, 0, G_OPTION_ARG_NONE,
|
|
|
|
&context_main->options.debug_control,
|
|
|
|
N_("Enable debug control D-Bus interface")
|
|
|
|
},
|
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;
|
2022-05-30 14:27:02 -04:00
|
|
|
#ifdef HAVE_X11
|
2024-01-22 10:56:45 -05:00
|
|
|
context_class->notify_ready = meta_context_main_notify_ready;
|
2022-05-30 14:27:02 -04:00
|
|
|
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;
|
|
|
|
}
|