diff --git a/js/perf/headlessStart.js b/js/perf/headlessStart.js index ace645355..0f18447e3 100644 --- a/js/perf/headlessStart.js +++ b/js/perf/headlessStart.js @@ -23,15 +23,12 @@ function init() { global.connect('shutdown', () => { _testMonitor?.destroy(); }); - global.context.connect('started', + GLib.timeout_add_seconds( + GLib.PRIORITY_LOW, 2, () => { - GLib.timeout_add_seconds( - GLib.PRIORITY_LOW, 2, - () => { - log('Connecting 1280x720 test monitor'); - _testMonitor = MetaTest.TestMonitor.new( - global.context, 1280, 720, 60.0); - }); + log('Connecting 1280x720 test monitor'); + _testMonitor = MetaTest.TestMonitor.new( + global.context, 1280, 720, 60.0); }); Scripting.defineScriptEvent('monitorsChanged', 'Monitors changed'); diff --git a/js/ui/init.js b/js/ui/init.js index a0fe63343..32d3c68ba 100644 --- a/js/ui/init.js +++ b/js/ui/init.js @@ -1,6 +1,25 @@ -import { setConsoleLogDomain } from 'console'; +import {setConsoleLogDomain} from 'console'; +import GLib from 'gi://GLib'; +import {exit} from 'system'; setConsoleLogDomain('GNOME Shell'); imports.ui.environment.init(); -imports.ui.main.start(); + +// Run the Mutter main loop after +// GJS finishes resolving this module. +imports._promiseNative.setMainLoopHook(() => { + // Queue starting the shell + GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { + try { + imports.ui.main.start(); + } catch (e) { + logError(e); + exit(1); + } + return GLib.SOURCE_REMOVE; + }); + + // Run the meta context's main loop + global.context.run_main_loop(); +}); diff --git a/src/gnome-shell-plugin.c b/src/gnome-shell-plugin.c index 5364f043a..39db3aefd 100644 --- a/src/gnome-shell-plugin.c +++ b/src/gnome-shell-plugin.c @@ -105,9 +105,6 @@ static void gnome_shell_plugin_start (MetaPlugin *plugin) { GnomeShellPlugin *shell_plugin = GNOME_SHELL_PLUGIN (plugin); - GError *error = NULL; - uint8_t status; - GjsContext *gjs_context; ClutterBackend *backend; backend = clutter_get_default_backend (); @@ -123,30 +120,6 @@ gnome_shell_plugin_start (MetaPlugin *plugin) shell_plugin->global = shell_global_get (); _shell_global_set_plugin (shell_plugin->global, META_PLUGIN (shell_plugin)); - - gjs_context = _shell_global_get_gjs_context (shell_plugin->global); - - if (!gjs_context_eval_module_file (gjs_context, - "resource:///org/gnome/shell/ui/init.js", - &status, - &error)) - { - g_message ("Execution of main.js threw exception: %s", error->message); - g_error_free (error); - /* We just exit() here, since in a development environment you'll get the - * error in your shell output, and it's way better than a busted WM, - * which typically manifests as a white screen. - * - * In production, we shouldn't crash =) But if we do, we should get - * restarted by the session infrastructure, which is likely going - * to be better than some undefined state. - * - * If there was a generic "hook into bug-buddy for non-C crashes" - * infrastructure, here would be the place to put it. - */ - g_object_unref (gjs_context); - exit (1); - } } static ShellWM * diff --git a/src/main.c b/src/main.c index e81f92c44..1bfa05e4b 100644 --- a/src/main.c +++ b/src/main.c @@ -608,11 +608,8 @@ main (int argc, char **argv) init_signal_handlers (context); change_to_home_directory (); - if (!meta_context_setup (context, &error)) - { - g_printerr ("Failed to setup: %s\n", error->message); - return EXIT_FAILURE; - } + if (session_mode == NULL) + session_mode = is_gdm_mode ? (char *)"gdm" : (char *)"user"; /* FIXME: Add gjs API to set this stuff and don't depend on the * environment. These propagate to child processes. @@ -620,24 +617,6 @@ main (int argc, char **argv) g_setenv ("GJS_DEBUG_OUTPUT", "stderr", TRUE); g_setenv ("GJS_DEBUG_TOPICS", "JS ERROR;JS LOG", TRUE); - shell_init_debug (g_getenv ("SHELL_DEBUG")); - - shell_dbus_init (meta_context_is_replacing (context)); - shell_a11y_init (); - shell_perf_log_init (); - shell_introspection_init (); - shell_fonts_init (); - - g_log_set_writer_func (default_log_writer, NULL, NULL); - - /* Initialize the global object */ - if (session_mode == NULL) - session_mode = is_gdm_mode ? (char *)"gdm" : (char *)"user"; - - _shell_global_init ("session-mode", session_mode, - "force-animations", force_animations, - NULL); - dump_gjs_stack_on_signal (SIGABRT); dump_gjs_stack_on_signal (SIGFPE); dump_gjs_stack_on_signal (SIGIOT); @@ -649,6 +628,33 @@ main (int argc, char **argv) dump_gjs_stack_on_signal (SIGSEGV); } + /* Initialize the Shell global, including GjsContext + * GjsContext will iterate the default main loop to + * resolve internal modules. + */ + _shell_global_init ("session-mode", session_mode, + "force-animations", force_animations, + NULL); + + /* Setup Meta _after_ the Shell global to avoid GjsContext + * iterating on the main loop once Meta starts adding events + */ + if (!meta_context_setup (context, &error)) + { + g_printerr ("Failed to setup: %s\n", error->message); + return EXIT_FAILURE; + } + + shell_init_debug (g_getenv ("SHELL_DEBUG")); + + shell_dbus_init (meta_context_is_replacing (context)); + shell_a11y_init (); + shell_perf_log_init (); + shell_introspection_init (); + shell_fonts_init (); + + g_log_set_writer_func (default_log_writer, NULL, NULL); + shell_profiler_init (); if (meta_context_get_compositor_type (context) == META_COMPOSITOR_TYPE_WAYLAND) @@ -660,10 +666,31 @@ main (int argc, char **argv) return EXIT_FAILURE; } - if (!meta_context_run_main_loop (context, &error)) + /* init.js calls meta_context_start_main_loop(), gjs_context_eval_module_file() + * will not return until Mutter is exited. + */ + GjsContext *gjs_context = _shell_global_get_gjs_context (shell_global_get()); + uint8_t status; + if (!gjs_context_eval_module_file (gjs_context, + "resource:///org/gnome/shell/ui/init.js", + &status, + &error)) { - g_printerr ("GNOME Shell terminated with an error: %s\n", error->message); - ecode = EXIT_FAILURE; + g_message ("Execution of main.js threw exception: %s", error->message); + g_error_free (error); + /* We just exit() here, since in a development environment you'll get the + * error in your shell output, and it's way better than a busted WM, + * which typically manifests as a white screen. + * + * In production, we shouldn't crash =) But if we do, we should get + * restarted by the session infrastructure, which is likely going + * to be better than some undefined state. + * + * If there was a generic "hook into bug-buddy for non-C crashes" + * infrastructure, here would be the place to put it. + */ + g_object_unref (gjs_context); + exit (1); } g_message ("Shutting down GNOME Shell");