[gnome-shell] Use libmutter-wm, and build a real gnome-shell binary



commit ae96b0c97142162690c9dba1d65c437f768cd46b
Author: Dan Winship <danw gnome org>
Date:   Fri Feb 25 11:20:27 2011 -0500

    Use libmutter-wm, and build a real gnome-shell binary
    
    Build gnome-shell as a binary linked against libmutter-wm, instead of
    a module to be loaded by libmutter-wm. Move the majority of
    initialization-type stuff from gnome_shell_plugin_start() into main().
    
    We still build libgnome-shell as a shared library, so that the linker
    doesn't discard all the methods that are never called from C.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=641724

 .gitignore                   |    2 +-
 configure.ac                 |   46 ++---
 src/Makefile.am              |   63 +++---
 src/gnome-shell-installed.in |   41 ----
 src/gnome-shell-jhbuild.in   |   29 ++--
 src/gnome-shell-plugin.c     |  420 +-------------------------------------
 src/main.c                   |  460 ++++++++++++++++++++++++++++++++++++++++++
 src/shell-a11y.c             |    3 -
 src/shell-global-private.h   |    4 +-
 src/shell-global.c           |   19 ++-
 tests/Makefile.am            |    2 +-
 tests/run-test.sh.in         |    2 +-
 12 files changed, 553 insertions(+), 538 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 907bffd..dba52f8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -44,7 +44,7 @@ src/calendar-server/org.gnome.Shell.CalendarServer.service
 src/gnome-shell
 src/gnome-shell-calendar-server
 src/gnome-shell-extension-tool
-src/gnome-shell-installed
+src/gnome-shell-real
 src/gnome-shell-jhbuild
 src/run-js-test
 src/test-recorder
diff --git a/configure.ac b/configure.ac
index 6031a53..f118495 100644
--- a/configure.ac
+++ b/configure.ac
@@ -74,20 +74,20 @@ TELEPATHY_GLIB_MIN_VERSION=0.13.12
 POLKIT_MIN_VERSION=0.100
 
 # Collect more than 20 libraries for a prize!
-PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION
-                                 gio-unix-2.0 dbus-glib-1 libxml-2.0
-                                 gtk+-3.0 >= $GTK_MIN_VERSION
-                                 mutter-plugins >= $MUTTER_MIN_VERSION
-                                 gjs-internals-1.0 >= $GJS_MIN_VERSION
-				 libgnome-menu $recorder_modules gconf-2.0
-                                 gdk-x11-3.0
-				 clutter-x11-1.0 >= $CLUTTER_MIN_VERSION
-				 clutter-glx-1.0 >= $CLUTTER_MIN_VERSION
-                                 libstartup-notification-1.0
-                                 gobject-introspection-1.0 >= $GOBJECT_INTROSPECTION_MIN_VERSION
-				 libcanberra
-                                 telepathy-glib >= $TELEPATHY_GLIB_MIN_VERSION
-                                 polkit-agent-1 >= $POLKIT_MIN_VERSION)
+PKG_CHECK_MODULES(GNOME_SHELL, gio-2.0 >= $GIO_MIN_VERSION
+                               gio-unix-2.0 dbus-glib-1 libxml-2.0
+                               gtk+-3.0 >= $GTK_MIN_VERSION
+                               libmutter-wm >= $MUTTER_MIN_VERSION
+                               gjs-internals-1.0 >= $GJS_MIN_VERSION
+			       libgnome-menu $recorder_modules gconf-2.0
+                               gdk-x11-3.0
+			       clutter-x11-1.0 >= $CLUTTER_MIN_VERSION
+			       clutter-glx-1.0 >= $CLUTTER_MIN_VERSION
+                               libstartup-notification-1.0
+                               gobject-introspection-1.0 >= $GOBJECT_INTROSPECTION_MIN_VERSION
+			       libcanberra
+                               telepathy-glib >= $TELEPATHY_GLIB_MIN_VERSION
+                               polkit-agent-1 >= $POLKIT_MIN_VERSION)
 
 GJS_VERSION=`$PKG_CONFIG --modversion gjs-internals-1.0`
 AC_DEFINE_UNQUOTED([GJS_VERSION], ["$GJS_VERSION"], [The version of GJS we're linking to])
@@ -97,8 +97,8 @@ GOBJECT_INTROSPECTION_CHECK([$GOBJECT_INTROSPECTION_MIN_VERSION])
 
 saved_CFLAGS=$CFLAGS
 saved_LIBS=$LIBS
-CFLAGS=$MUTTER_PLUGIN_CFLAGS
-LIBS=$MUTTER_PLUGIN_LIBS
+CFLAGS=$GNOME_SHELL_CFLAGS
+LIBS=$GNOME_SHELL_LIBS
 # sn_startup_sequence_get_application_id, we can replace with a version check later
 AC_CHECK_FUNCS(JS_NewGlobalObject sn_startup_sequence_get_application_id)
 CFLAGS=$saved_CFLAGS
@@ -134,13 +134,10 @@ PKG_CHECK_MODULES(CALENDAR_SERVER, libecal-1.2 >= $LIBECAL_MIN_VERSION libedatas
 AC_SUBST(CALENDAR_SERVER_CFLAGS)
 AC_SUBST(CALENDAR_SERVER_LIBS)
 
-MUTTER_BIN_DIR=`$PKG_CONFIG --variable=exec_prefix mutter-plugins`/bin
-# FIXME: metacity-plugins.pc should point directly to its .gir file
-MUTTER_LIB_DIR=`$PKG_CONFIG --variable=libdir mutter-plugins`
-MUTTER_PLUGIN_DIR=`$PKG_CONFIG --variable=plugindir mutter-plugins`
-AC_SUBST(MUTTER_BIN_DIR)
-AC_SUBST(MUTTER_LIB_DIR)
-AC_SUBST(MUTTER_PLUGIN_DIR)
+MUTTER_GIR_DIR=`$PKG_CONFIG --variable=girdir libmutter-wm`
+MUTTER_TYPELIB_DIR=`$PKG_CONFIG --variable=typelibdir libmutter-wm`
+AC_SUBST(MUTTER_GIR_DIR)
+AC_SUBST(MUTTER_TYPELIB_DIR)
 
 GJS_CONSOLE=`$PKG_CONFIG --variable=gjs_console gjs-1.0`
 AC_SUBST(GJS_CONSOLE)
@@ -207,9 +204,6 @@ AC_ARG_ENABLE(dynamic-mozjs-hack,
 ENABLE_DYNAMIC_MOZJS_HACK=$enable_dynamic_mozjs_hack
 AC_SUBST(ENABLE_DYNAMIC_MOZJS_HACK)
 
-AC_PATH_PROG(mutter, [mutter])
-AC_SUBST(mutter)
-
 AC_CONFIG_FILES([
   Makefile
   data/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index f15bf95..c72c54f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -10,17 +10,31 @@ noinst_PROGRAMS =
 -include $(INTROSPECTION_MAKEFILE)
 INTROSPECTION_GIRS =
 INTROSPECTION_SCANNER_ARGS = --warn-all --warn-error --add-include-path=$(srcdir)
-INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir) --includedir=$(MUTTER_LIB_DIR)/mutter/
+INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir) --includedir=$(MUTTER_TYPELIB_DIR)
 
 typelibdir = $(pkglibdir)
 typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
 
 CLEANFILES += $(gir_DATA) $(typelib_DATA)
 
-generated_bin_scripts = gnome-shell-installed gnome-shell-jhbuild gnome-shell-extension-tool
-bin_SCRIPTS += gnome-shell $(generated_bin_scripts)
+bin_SCRIPTS += gnome-shell-extension-tool
+bin_PROGRAMS = gnome-shell-real
 
-generated_script_substitutions = -e "s|@MUTTER_BIN_DIR[ ]|$(MUTTER_BIN_DIR)|" \
+if USE_JHBUILD_WRAPPER_SCRIPT
+gnome_shell = gnome-shell-jhbuild
+bin_SCRIPTS += gnome-shell-jhbuild
+else
+gnome_shell = gnome-shell-real
+endif
+
+noinst_DATA = gnome-shell
+gnome-shell: $(gnome_shell) Makefile
+	cp $< $  tmp && mv $  tmp $@
+install-exec-hook:
+	mv $(DESTDIR)$(bindir)/$(gnome_shell) $(DESTDIR)$(bindir)/gnome-shell
+
+generated_script_substitutions = \
+	    -e "s|@bindir[ ]|$(bindir)|" \
 	    -e "s|@datadir[ ]|$(datadir)|" \
 	    -e "s|@libexecdir[ ]|$(libexecdir)|" \
 	    -e "s|@libdir[ ]|$(libdir)|" \
@@ -33,22 +47,11 @@ generated_script_substitutions = -e "s|@MUTTER_BIN_DIR[ ]|$(MUTTER_BIN_DIR)|" \
 gnome-shell-jhbuild: gnome-shell-jhbuild.in Makefile
 	$(AM_V_GEN) sed $(generated_script_substitutions) $< > $  tmp && mv $  tmp $@ && chmod a+x $@
 
-gnome-shell-installed: gnome-shell-installed.in Makefile
-	$(AM_V_GEN) sed $(generated_script_substitutions) $< > $  tmp && mv $  tmp $@ && chmod a+x $@
-
 gnome-shell-extension-tool: gnome-shell-extension-tool.in Makefile
 	$(AM_V_GEN) sed $(generated_script_substitutions) $< > $  tmp && mv $  tmp $@ && chmod a+x $@
 
-if USE_JHBUILD_WRAPPER_SCRIPT
-gnome-shell: gnome-shell-jhbuild Makefile
-	cp $< $  tmp && mv $  tmp $@
-else
-gnome-shell: gnome-shell-installed Makefile
-	cp $< $  tmp && mv $  tmp $@
-endif
-
-CLEANFILES += gnome-shell $(generated_bin_scripts)
-EXTRA_DIST += $(generated_bin_scripts:=.in)
+CLEANFILES += gnome-shell $(bin_SCRIPTS)
+EXTRA_DIST += $(bin_SCRIPTS:=.in)
 
 include Makefile-gdmuser.am
 include Makefile-st.am
@@ -57,17 +60,17 @@ include Makefile-gvc.am
 include Makefile-calendar-server.am
 
 gnome_shell_cflags =				\
-	$(MUTTER_PLUGIN_CFLAGS)			\
-	$(LIBGNOMEUI_CFLAGS)                    \
+	$(GNOME_SHELL_CFLAGS)			\
 	-I$(srcdir)/tray			\
+	-DVERSION=\"$(VERSION)\"		\
 	-DLOCALEDIR=\"$(datadir)/locale\" \
 	-DGNOME_SHELL_LIBEXECDIR=\"$(libexecdir)\"	\
 	-DGNOME_SHELL_DATADIR=\"$(pkgdatadir)\"	\
 	-DGNOME_SHELL_PKGLIBDIR=\"$(pkglibdir)\" \
 	-DJSDIR=\"$(pkgdatadir)/js\"
 
-plugindir = $(MUTTER_PLUGIN_DIR)
-plugin_LTLIBRARIES = libgnome-shell.la
+privlibdir = $(pkglibdir)
+privlib_LTLIBRARIES = libgnome-shell.la
 
 shell_built_sources = \
 	shell-marshal.h \
@@ -134,6 +137,11 @@ libgnome_shell_la_SOURCES =		\
 libgnome_shell_la_gir_sources = \
 	$(filter-out %-private.h $(shell_recorder_non_gir_sources), $(shell_public_headers_h) $(libgnome_shell_la_SOURCES))
 
+gnome_shell_real_SOURCES =		\
+	main.c
+gnome_shell_real_CPPFLAGS = $(gnome_shell_cflags)
+gnome_shell_real_LDADD = -lgnome-shell
+
 ########################################
 
 shell_recorder_sources =        \
@@ -232,11 +240,10 @@ shell-enum-types.c: shell-enum-types.c.in stamp-shell-enum-types.h
 	rm -f $  tmp
 EXTRA_DIST += shell-enum-types.c.in
 
-libgnome_shell_la_LDFLAGS = -avoid-version -module
-libgnome_shell_la_LIBADD =	\
+libgnome_shell_la_LDFLAGS = -avoid-version
+libgnome_shell_la_LIBADD =		\
 	-lm			\
-	$(MUTTER_PLUGIN_LIBS)	\
-	$(LIBGNOMEUI_LIBS)      \
+	$(GNOME_SHELL_LIBS)	\
 	$(BLUETOOTH_LIBS)	\
 	libst-1.0.la       	\
 	libgdmuser-1.0.la	\
@@ -244,7 +251,7 @@ libgnome_shell_la_LIBADD =	\
 	libgvc.la		\
 	$(NULL)
 
-libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags) $(LIBECAL_CFLAGS)
+libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)
 
 Shell-0.1.gir: libgnome-shell.la St-1.0.gir
 Shell_0_1_gir_INCLUDES = Clutter-1.0 ClutterX11-1.0 Meta-2.91 TelepathyGLib-0.12
@@ -252,9 +259,7 @@ Shell_0_1_gir_CFLAGS = $(libgnome_shell_la_CPPFLAGS) -I $(srcdir)
 Shell_0_1_gir_LIBS = libgnome-shell.la
 Shell_0_1_gir_FILES = $(addprefix $(srcdir)/,$(libgnome_shell_la_gir_sources))
 Shell_0_1_gir_SCANNERFLAGS = --include-uninstalled=$(builddir)/St-1.0.gir \
-	--add-include-path=$(MUTTER_LIB_DIR)/mutter/ \
-	--program=mutter \
-	--program-arg=--mutter-plugins=`pwd`/libgnome-shell.la
+	--add-include-path=$(MUTTER_GIR_DIR)
 INTROSPECTION_GIRS += Shell-0.1.gir
 
 St-1.0.gir: libst-1.0.la
diff --git a/src/gnome-shell-jhbuild.in b/src/gnome-shell-jhbuild.in
index 220d53f..3774777 100755
--- a/src/gnome-shell-jhbuild.in
+++ b/src/gnome-shell-jhbuild.in
@@ -143,17 +143,15 @@ def start_dconf_await_service():
     loop.run()
 
 def start_shell(perf_output=None):
-    bin_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
-    if os.path.exists(os.path.join(bin_dir, 'gnome-shell-jhbuild.in')):
+    self_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
+    if os.path.exists(os.path.join(self_dir, 'gnome-shell-jhbuild.in')):
         running_from_source_tree = True
-        top_dir = os.path.dirname(bin_dir)
-        plugin = os.path.join(top_dir, 'src', 'libgnome-shell.la')
+        top_dir = os.path.dirname(self_dir)
         typelib_dir = os.path.join(top_dir, "src")
         js_dir = os.path.join(top_dir, "js")
         data_dir = os.path.join(top_dir, "data")
     else:
         running_from_source_tree = False
-        plugin = 'libgnome-shell'
         js_dir = os.path.join('@pkgdatadir@', 'js')
 
     # Set up environment
@@ -166,13 +164,13 @@ def start_shell(perf_output=None):
     # below. Otherwise it's just a bad reimplementation of "jhbuild
     # run".  See bug #642084
     env.update({'GNOME_SHELL_JS'      : js_dir,
-                'PATH'                : '@MUTTER_BIN_DIR@:' + os.environ.get('PATH', ''),
+                'PATH'                : '@bindir@:' + os.environ.get('PATH', ''),
                 'XDG_CONFIG_DIRS'     : '@sysconfdir@/xdg:' + (os.environ.get('XDG_CONFIG_DIRS') or '/etc/xdg'),
                 'XDG_DATA_DIRS'       : '@datadir@:' + (os.environ.get('XDG_DATA_DIRS') or '/usr/local/share:/usr/share')})
     if running_from_source_tree:
         if os.environ.has_key('GI_TYPELIB_PATH'):
             typelib_dir = typelib_dir + ":" + os.environ.get('GI_TYPELIB_PATH')
-        env.update({'GNOME_SHELL_BINDIR' : bin_dir,
+        env.update({'GNOME_SHELL_BINDIR'   : self_dir,
                     'GNOME_SHELL_DATADIR'  : data_dir,
                     'GI_TYPELIB_PATH'      : typelib_dir,
                     'GSETTINGS_SCHEMA_DIR' : data_dir })
@@ -191,15 +189,14 @@ def start_shell(perf_output=None):
     if perf_output is not None:
         env['SHELL_PERF_OUTPUT'] = perf_output
 
+    args = []
     if options.debug:
         debug_command = options.debug_command.split()
-        args = list(debug_command)
-    else:
-        args = []
+        if running_from_source_tree:
+            args += [os.path.join(top_dir, 'libtool'), '--mode=execute']
+        args += debug_command
 
-    if running_from_source_tree:
-        env['MUTTER_PLUGINS'] = plugin
-    args.append(os.path.join(bin_dir, 'gnome-shell-installed'))
+    args.append(os.path.join(self_dir, 'gnome-shell-real'))
     if options.replace:
         args.append('--replace')
     if options.sync:
@@ -427,9 +424,9 @@ def run_performance_test():
         }
 
         # Add the Git revision if available
-        bin_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
-        if os.path.exists(os.path.join(bin_dir, 'gnome-shell.in')):
-            top_dir = os.path.dirname(bin_dir)
+        self_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
+        if os.path.exists(os.path.join(self_dir, 'gnome-shell-jhbuild.in')):
+            top_dir = os.path.dirname(self_dir)
             git_dir = os.path.join(top_dir, '.git')
             if os.path.exists(git_dir):
                 env = dict(os.environ)
diff --git a/src/gnome-shell-plugin.c b/src/gnome-shell-plugin.c
index 8e1192f..d634391 100644
--- a/src/gnome-shell-plugin.c
+++ b/src/gnome-shell-plugin.c
@@ -27,19 +27,9 @@
 
 #include <meta-plugin.h>
 
-#include <glib/gi18n-lib.h>
-
 #include <clutter/clutter.h>
 #include <clutter/x11/clutter-x11.h>
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-#include <gdk/gdkx.h>
 #include <gjs/gjs.h>
-#include <girepository.h>
-#include <gmodule.h>
-#ifdef HAVE_MALLINFO
-#include <malloc.h>
-#endif
 #include <stdlib.h>
 #include <string.h>
 
@@ -51,16 +41,10 @@
 #include "shell-global-private.h"
 #include "shell-perf-log.h"
 #include "shell-wm-private.h"
-#include "st.h"
-#include "shell-a11y.h"
-
-#define SHELL_DBUS_SERVICE "org.gnome.Shell"
-#define MAGNIFIER_DBUS_SERVICE "org.gnome.Magnifier"
 
 static void gnome_shell_plugin_dispose     (GObject *object);
 static void gnome_shell_plugin_finalize    (GObject *object);
 
-static void gnome_shell_plugin_early_initialize (MetaPlugin          *plugin);
 static void gnome_shell_plugin_start            (MetaPlugin          *plugin);
 static void gnome_shell_plugin_minimize         (MetaPlugin          *plugin,
                                                  MetaWindowActor     *actor);
@@ -110,7 +94,6 @@ struct _GnomeShellPlugin
 {
   MetaPlugin parent;
 
-  GjsContext *gjs_context;
   Atom panel_action;
   Atom panel_action_run_dialog;
   Atom panel_action_main_menu;
@@ -127,11 +110,9 @@ struct _GnomeShellPluginClass
   MetaPluginClass parent_class;
 };
 
-/*
- * Create the plugin struct; function pointers initialized in
- * g_module_check_init().
- */
-META_PLUGIN_DECLARE(GnomeShellPlugin, gnome_shell_plugin);
+GType gnome_shell_plugin_get_type (void);
+
+G_DEFINE_TYPE (GnomeShellPlugin, gnome_shell_plugin, META_TYPE_PLUGIN)
 
 static void
 gnome_shell_plugin_class_init (GnomeShellPluginClass *klass)
@@ -142,7 +123,6 @@ gnome_shell_plugin_class_init (GnomeShellPluginClass *klass)
   gobject_class->dispose         = gnome_shell_plugin_dispose;
   gobject_class->finalize        = gnome_shell_plugin_finalize;
 
-  plugin_class->early_initialize = gnome_shell_plugin_early_initialize;
   plugin_class->start            = gnome_shell_plugin_start;
   plugin_class->map              = gnome_shell_plugin_map;
   plugin_class->minimize         = gnome_shell_plugin_minimize;
@@ -162,328 +142,6 @@ gnome_shell_plugin_class_init (GnomeShellPluginClass *klass)
 static void
 gnome_shell_plugin_init (GnomeShellPlugin *shell_plugin)
 {
-  meta_prefs_override_preference_location ("/apps/mutter/general/attach_modal_dialogs",
-                                           "/desktop/gnome/shell/windows/attach_modal_dialogs");
-  meta_prefs_override_preference_location ("/apps/metacity/general/button_layout",
-                                           "/desktop/gnome/shell/windows/button_layout");
-  meta_prefs_override_preference_location ("/apps/metacity/general/edge_tiling",
-                                           "/desktop/gnome/shell/windows/edge_tiling");
-  meta_prefs_override_preference_location ("/apps/metacity/general/theme",
-                                           "/desktop/gnome/shell/windows/theme");
-}
-
-static void
-update_font_options (GtkSettings *settings)
-{
-  StThemeContext *context;
-  ClutterStage *stage;
-  ClutterBackend *backend;
-  gint dpi;
-  gint hinting;
-  gchar *hint_style_str;
-  cairo_hint_style_t hint_style = CAIRO_HINT_STYLE_NONE;
-  gint antialias;
-  cairo_antialias_t antialias_mode = CAIRO_ANTIALIAS_NONE;
-  cairo_font_options_t *options;
-
-  /* Disable text mipmapping; it causes problems on pre-GEM Intel
-   * drivers and we should just be rendering text at the right
-   * size rather than scaling it. If we do effects where we dynamically
-   * zoom labels, then we might want to reconsider.
-   */
-  clutter_set_font_flags (clutter_get_font_flags () & ~CLUTTER_FONT_MIPMAPPING);
-
-  g_object_get (settings,
-                "gtk-xft-dpi", &dpi,
-                "gtk-xft-antialias", &antialias,
-                "gtk-xft-hinting", &hinting,
-                "gtk-xft-hintstyle", &hint_style_str,
-                NULL);
-
-  stage = CLUTTER_STAGE (clutter_stage_get_default ());
-  context = st_theme_context_get_for_stage (stage);
-
-  if (dpi != -1)
-    /* GTK stores resolution as 1024 * dots/inch */
-    st_theme_context_set_resolution (context, dpi / 1024);
-  else
-    st_theme_context_set_default_resolution (context);
-
-  /* Clutter (as of 0.9) passes comprehensively wrong font options
-   * override whatever set_font_flags() did above.
-   *
-   * http://bugzilla.openedhand.com/show_bug.cgi?id=1456
-   */
-  backend = clutter_get_default_backend ();
-  options = cairo_font_options_create ();
-
-  cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
-
-  if (hinting >= 0 && !hinting)
-    {
-      hint_style = CAIRO_HINT_STYLE_NONE;
-    }
-  else if (hint_style_str)
-    {
-      if (strcmp (hint_style_str, "hintnone") == 0)
-        hint_style = CAIRO_HINT_STYLE_NONE;
-      else if (strcmp (hint_style_str, "hintslight") == 0)
-        hint_style = CAIRO_HINT_STYLE_SLIGHT;
-      else if (strcmp (hint_style_str, "hintmedium") == 0)
-        hint_style = CAIRO_HINT_STYLE_MEDIUM;
-      else if (strcmp (hint_style_str, "hintfull") == 0)
-        hint_style = CAIRO_HINT_STYLE_FULL;
-    }
-
-  g_free (hint_style_str);
-
-  cairo_font_options_set_hint_style (options, hint_style);
-
-  /* We don't want to turn on subpixel anti-aliasing; since Clutter
-   * doesn't currently have the code to support ARGB masks,
-   * generating them then squashing them back to A8 is pointless.
-   */
-  antialias_mode = (antialias < 0 || antialias) ? CAIRO_ANTIALIAS_GRAY
-                                                : CAIRO_ANTIALIAS_NONE;
-
-  cairo_font_options_set_antialias (options, antialias_mode);
-
-  clutter_backend_set_font_options (backend, options);
-  cairo_font_options_destroy (options);
-}
-
-static void
-settings_notify_cb (GtkSettings *settings,
-                    GParamSpec  *pspec,
-                    gpointer     data)
-{
-  update_font_options (settings);
-}
-
-static void
-malloc_statistics_callback (ShellPerfLog *perf_log,
-                            gpointer      data)
-{
-#ifdef HAVE_MALLINFO
-  struct mallinfo info = mallinfo ();
-
-  shell_perf_log_update_statistic_i (perf_log,
-                                     "malloc.arenaSize",
-                                     info.arena);
-  shell_perf_log_update_statistic_i (perf_log,
-                                     "malloc.mmapSize",
-                                     info.hblkhd);
-  shell_perf_log_update_statistic_i (perf_log,
-                                     "malloc.usedSize",
-                                     info.uordblks);
-#endif
-}
-
-static void
-add_statistics (GnomeShellPlugin *shell_plugin)
-{
-  ShellPerfLog *perf_log = shell_perf_log_get_default ();
-
-  /* For probably historical reasons, mallinfo() defines the returned values,
-   * even those in bytes as int, not size_t. We're determined not to use
-   * more than 2G of malloc'ed memory, so are OK with that.
-   */
-  shell_perf_log_define_statistic (perf_log,
-                                   "malloc.arenaSize",
-                                   "Amount of memory allocated by malloc() with brk(), in bytes",
-                                   "i");
-  shell_perf_log_define_statistic (perf_log,
-                                   "malloc.mmapSize",
-                                   "Amount of memory allocated by malloc() with mmap(), in bytes",
-                                   "i");
-  shell_perf_log_define_statistic (perf_log,
-                                   "malloc.usedSize",
-                                   "Amount of malloc'ed memory currently in use",
-                                   "i");
-
-  shell_perf_log_add_statistics_callback (perf_log,
-                                          malloc_statistics_callback,
-                                          NULL, NULL);
-}
-
-/* This is an IBus workaround. The flow of events with IBus is that every time
- * it gets gets a key event, it:
- *
- *  Sends it to the daemon via D-Bus asynchronously
- *  When it gets an reply, synthesizes a new GdkEvent and puts it into the
- *   GDK event queue with gdk_event_put(), including
- *   IBUS_FORWARD_MASK = 1 << 25 in the state to prevent a loop.
- *
- * (Normally, IBus uses the GTK+ key snooper mechanism to get the key
- * events early, but since our key events aren't visible to GTK+ key snoopers,
- * IBus will instead get the events via the standard
- * GtkIMContext.filter_keypress() mechanism.)
- *
- * There are a number of potential problems here; probably the worst
- * problem is that IBus doesn't forward the timestamp with the event
- * so that every key event that gets delivered ends up with
- * GDK_CURRENT_TIME.  This creates some very subtle bugs; for example
- * if you have IBus running and a keystroke is used to trigger
- * launching an application, focus stealing prevention won't work
- * right. http://code.google.com/p/ibus/issues/detail?id=1184
- *
- * In any case, our normal flow of key events is:
- *
- *  GDK filter function => clutter_x11_handle_event => clutter actor
- *
- * So, if we see a key event that gets delivered via the GDK event handler
- * function - then we know it must be one of these synthesized events, and
- * we should push it back to clutter.
- *
- * To summarize, the full key event flow with IBus is:
- *
- *   GDK filter function
- *     => Mutter
- *     => gnome_shell_plugin_xevent_filter()
- *     => clutter_x11_handle_event()
- *     => clutter event delivery to actor
- *     => gtk_im_context_filter_event()
- *     => sent to IBus daemon
- *     => response received from IBus daemon
- *     => gdk_event_put()
- *     => GDK event handler
- *     => <this function>
- *     => clutter_event_put()
- *     => clutter event delivery to actor
- *
- * Anything else we see here we just pass on to the normal GDK event handler
- * gtk_main_do_event().
- */
-static void
-gnome_shell_gdk_event_handler (GdkEvent *event_gdk,
-                               gpointer  data)
-{
-  if (event_gdk->type == GDK_KEY_PRESS || event_gdk->type == GDK_KEY_RELEASE)
-    {
-      ClutterActor *stage;
-      Window stage_xwindow;
-
-      stage = clutter_stage_get_default ();
-      stage_xwindow = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
-
-      if (GDK_WINDOW_XID (event_gdk->key.window) == stage_xwindow)
-        {
-          ClutterDeviceManager *device_manager = clutter_device_manager_get_default ();
-          ClutterInputDevice *keyboard = clutter_device_manager_get_core_device (device_manager,
-                                                                                 CLUTTER_KEYBOARD_DEVICE);
-
-          ClutterEvent *event_clutter = clutter_event_new ((event_gdk->type == GDK_KEY_PRESS) ?
-                                                           CLUTTER_KEY_PRESS : CLUTTER_KEY_RELEASE);
-          event_clutter->key.time = event_gdk->key.time;
-          event_clutter->key.flags = CLUTTER_EVENT_NONE;
-          event_clutter->key.stage = CLUTTER_STAGE (stage);
-          event_clutter->key.source = NULL;
-
-          /* This depends on ClutterModifierType and GdkModifierType being
-           * identical, which they are currently. (They both match the X
-           * modifier state in the low 16-bits and have the same extensions.) */
-          event_clutter->key.modifier_state = event_gdk->key.state;
-
-          event_clutter->key.keyval = event_gdk->key.keyval;
-          event_clutter->key.hardware_keycode = event_gdk->key.hardware_keycode;
-          event_clutter->key.unicode_value = gdk_keyval_to_unicode (event_clutter->key.keyval);
-          event_clutter->key.device = keyboard;
-
-          clutter_event_put (event_clutter);
-          clutter_event_free (event_clutter);
-
-          return;
-        }
-    }
-
-  gtk_main_do_event (event_gdk);
-}
-
-static void
-muted_log_handler (const char     *log_domain,
-                   GLogLevelFlags  log_level,
-                   const char     *message,
-                   gpointer        data)
-{
-  /* Intentionally empty to discard message */
-}
-
-static void
-gnome_shell_plugin_early_initialize (MetaPlugin *plugin)
-{
-  GError *error = NULL;
-  DBusGConnection *session;
-  DBusGProxy *bus;
-  guint32 request_name_result;
-
-  /** TODO:
-   * In the future we should use GDBus for this.  However, in
-   * order to do that, we need to port all of the JavaScript
-   * code.  Otherwise, the name will be claimed on the wrong
-   * connection.
-   */
-  session = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
-
-  bus = dbus_g_proxy_new_for_name (session,
-                                   DBUS_SERVICE_DBUS,
-                                   DBUS_PATH_DBUS,
-                                   DBUS_INTERFACE_DBUS);
-
-  if (!dbus_g_proxy_call (bus, "RequestName", &error,
-                          G_TYPE_STRING, SHELL_DBUS_SERVICE,
-                          G_TYPE_UINT, 0,
-                          G_TYPE_INVALID,
-                          G_TYPE_UINT, &request_name_result,
-                          G_TYPE_INVALID))
-    {
-      g_print ("failed to acquire org.gnome.Shell: %s\n", error->message);
-      /* If we somehow got started again, it's not an error to be running
-       * already.  So just exit 0.
-       */
-      exit (0);
-    }
-
-  /* Also grab org.gnome.Panel to replace any existing panel process,
-   * unless a special environment variable is passed.  The environment
-   * variable is used by the gnome-shell (no --replace) launcher in
-   * Xephyr */
-  if (!dbus_g_proxy_call (bus, "RequestName", &error, G_TYPE_STRING,
-                          "org.gnome.Panel", G_TYPE_UINT,
-                          DBUS_NAME_FLAG_REPLACE_EXISTING | DBUS_NAME_FLAG_DO_NOT_QUEUE,
-                          G_TYPE_INVALID, G_TYPE_UINT,
-                          &request_name_result, G_TYPE_INVALID))
-    {
-      g_print ("failed to acquire org.gnome.Panel: %s\n", error->message);
-      exit (1);
-    }
-
-  /* ...and the org.gnome.Magnifier service.
-   */
-  if (!dbus_g_proxy_call (bus, "RequestName", &error,
-                          G_TYPE_STRING, MAGNIFIER_DBUS_SERVICE,
-                          G_TYPE_UINT, 0,
-                          G_TYPE_INVALID,
-                          G_TYPE_UINT, &request_name_result,
-                          G_TYPE_INVALID))
-    {
-      g_print ("failed to acquire %s: %s\n", MAGNIFIER_DBUS_SERVICE, error->message);
-      /* Failing to acquire the magnifer service is not fatal.  Log the error,
-       * but keep going. */
-    }
-
-  /* ...and the org.freedesktop.Notifications service.
-   */
-  if (!dbus_g_proxy_call (bus, "RequestName", &error,
-                          G_TYPE_STRING, "org.freedesktop.Notifications",
-                          G_TYPE_UINT, DBUS_NAME_FLAG_REPLACE_EXISTING | DBUS_NAME_FLAG_DO_NOT_QUEUE,
-                          G_TYPE_INVALID,
-                          G_TYPE_UINT, &request_name_result,
-                          G_TYPE_INVALID))
-    {
-      g_print ("failed to acquire org.freedesktop.Notifications: %s\n", error->message);
-    }
-
-  g_object_unref (bus);
 }
 
 static void
@@ -493,32 +151,10 @@ gnome_shell_plugin_start (MetaPlugin *plugin)
   MetaScreen *screen;
   MetaDisplay *display;
   Display *xdisplay;
-  GtkSettings *settings;
   GError *error = NULL;
   int status;
-  const char *shell_js;
-  char **search_path;
   const char *glx_extensions;
-
-  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
-  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
-
-  shell_a11y_init ();
-
-  settings = gtk_settings_get_default ();
-  g_object_connect (settings,
-                    "signal::notify::gtk-xft-dpi",
-                    G_CALLBACK (settings_notify_cb), NULL,
-                    "signal::notify::gtk-xft-antialias",
-                    G_CALLBACK (settings_notify_cb), NULL,
-                    "signal::notify::gtk-xft-hinting",
-                    G_CALLBACK (settings_notify_cb), NULL,
-                    "signal::notify::gtk-xft-hintstyle",
-                    G_CALLBACK (settings_notify_cb), NULL,
-                    NULL);
-  update_font_options (settings);
-
-  gdk_event_handler_set (gnome_shell_gdk_event_handler, plugin, NULL);
+  GjsContext *gjs_context;
 
   screen = meta_plugin_get_screen (plugin);
   display = meta_screen_get_display (screen);
@@ -538,40 +174,12 @@ gnome_shell_plugin_start (MetaPlugin *plugin)
                                "GL buffer swap complete event received (with timestamp of completion)",
                                "x");
 
-#if HAVE_BLUETOOTH
-  g_irepository_prepend_search_path (BLUETOOTH_DIR);
-#endif
-
-  g_irepository_prepend_search_path (GNOME_SHELL_PKGLIBDIR);
-
-  shell_js = g_getenv("GNOME_SHELL_JS");
-  if (!shell_js)
-    shell_js = JSDIR;
-
-  search_path = g_strsplit(shell_js, ":", -1);
-  shell_plugin->gjs_context = g_object_new (GJS_TYPE_CONTEXT,
-                                            "search-path", search_path,
-                                            "js-version", "1.8",
-                                            NULL);
-  g_strfreev(search_path);
-
-  /* Disable debug spew from various libraries */
-  g_log_set_handler ("Gvc", G_LOG_LEVEL_DEBUG,
-                     muted_log_handler, NULL);
-  g_log_set_handler ("GdmUser", G_LOG_LEVEL_DEBUG,
-                     muted_log_handler, NULL);
-  g_log_set_handler ("Bluetooth", G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_MESSAGE,
-                     muted_log_handler, NULL);
-
-  /* Initialize the global object here. */
   shell_plugin->global = shell_global_get ();
+  _shell_global_set_plugin (shell_plugin->global, META_PLUGIN (shell_plugin));
 
-  _shell_global_set_plugin (shell_plugin->global, META_PLUGIN(shell_plugin));
-  _shell_global_set_gjs_context (shell_plugin->global, shell_plugin->gjs_context);
-
-  add_statistics (shell_plugin);
+  gjs_context = _shell_global_get_gjs_context (shell_plugin->global);
 
-  if (!gjs_context_eval (shell_plugin->gjs_context,
+  if (!gjs_context_eval (gjs_context,
                          "const Main = imports.ui.main; Main.start();",
                          -1,
                          "<main>",
@@ -752,17 +360,3 @@ MetaPluginInfo *gnome_shell_plugin_plugin_info (MetaPlugin *plugin)
 
   return &info;
 }
-
-#if HAVE_BLUETOOTH
-/* HACK:
-   Add a non-static function that calls into libgnome-bluetooth-applet.so,
-   to avoid the linker being too smart and removing the dependency.
-   This function is never actually called.
-*/
-extern GType bluetooth_applet_get_type(void);
-void _shell_link_to_bluetooth(void);
-
-void _shell_link_to_bluetooth(void) {
-  bluetooth_applet_get_type();
-}
-#endif
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..91cd968
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,460 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+#include "config.h"
+
+#ifdef HAVE_MALLINFO
+#include <malloc.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include <clutter/clutter.h>
+#include <clutter/x11/clutter-x11.h>
+#include <dbus/dbus-glib.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n-lib.h>
+#include <girepository.h>
+#include <main.h>
+#include <meta-plugin.h>
+#include <prefs.h>
+
+#include "shell-a11y.h"
+#include "shell-global.h"
+#include "shell-perf-log.h"
+#include "st.h"
+
+extern GType gnome_shell_plugin_get_type (void);
+
+#define SHELL_DBUS_SERVICE "org.gnome.Shell"
+#define MAGNIFIER_DBUS_SERVICE "org.gnome.Magnifier"
+
+static void
+shell_dbus_init (void)
+{
+  GError *error = NULL;
+  DBusGConnection *session;
+  DBusGProxy *bus;
+  guint32 request_name_result;
+
+  /** TODO:
+   * In the future we should use GDBus for this.  However, in
+   * order to do that, we need to port all of the JavaScript
+   * code.  Otherwise, the name will be claimed on the wrong
+   * connection.
+   */
+  session = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
+
+  bus = dbus_g_proxy_new_for_name (session,
+                                   DBUS_SERVICE_DBUS,
+                                   DBUS_PATH_DBUS,
+                                   DBUS_INTERFACE_DBUS);
+
+  if (!dbus_g_proxy_call (bus, "RequestName", &error,
+                          G_TYPE_STRING, SHELL_DBUS_SERVICE,
+                          G_TYPE_UINT, 0,
+                          G_TYPE_INVALID,
+                          G_TYPE_UINT, &request_name_result,
+                          G_TYPE_INVALID))
+    {
+      g_print ("failed to acquire org.gnome.Shell: %s\n", error->message);
+      /* If we somehow got started again, it's not an error to be running
+       * already.  So just exit 0.
+       */
+      exit (0);
+    }
+
+  /* Also grab org.gnome.Panel to replace any existing panel process,
+   * unless a special environment variable is passed.  The environment
+   * variable is used by the gnome-shell (no --replace) launcher in
+   * Xephyr */
+  if (!dbus_g_proxy_call (bus, "RequestName", &error, G_TYPE_STRING,
+                          "org.gnome.Panel", G_TYPE_UINT,
+                          DBUS_NAME_FLAG_REPLACE_EXISTING | DBUS_NAME_FLAG_DO_NOT_QUEUE,
+                          G_TYPE_INVALID, G_TYPE_UINT,
+                          &request_name_result, G_TYPE_INVALID))
+    {
+      g_print ("failed to acquire org.gnome.Panel: %s\n", error->message);
+      exit (1);
+    }
+
+  /* ...and the org.gnome.Magnifier service.
+   */
+  if (!dbus_g_proxy_call (bus, "RequestName", &error,
+                          G_TYPE_STRING, MAGNIFIER_DBUS_SERVICE,
+                          G_TYPE_UINT, 0,
+                          G_TYPE_INVALID,
+                          G_TYPE_UINT, &request_name_result,
+                          G_TYPE_INVALID))
+    {
+      g_print ("failed to acquire %s: %s\n", MAGNIFIER_DBUS_SERVICE, error->message);
+      /* Failing to acquire the magnifer service is not fatal.  Log the error,
+       * but keep going. */
+    }
+
+  /* ...and the org.freedesktop.Notifications service.
+   */
+  if (!dbus_g_proxy_call (bus, "RequestName", &error,
+                          G_TYPE_STRING, "org.freedesktop.Notifications",
+                          G_TYPE_UINT, DBUS_NAME_FLAG_REPLACE_EXISTING | DBUS_NAME_FLAG_DO_NOT_QUEUE,
+                          G_TYPE_INVALID,
+                          G_TYPE_UINT, &request_name_result,
+                          G_TYPE_INVALID))
+    {
+      g_print ("failed to acquire org.freedesktop.Notifications: %s\n", error->message);
+    }
+
+  g_object_unref (bus);
+}
+
+
+static void
+update_font_options (GtkSettings *settings)
+{
+  StThemeContext *context;
+  ClutterStage *stage;
+  ClutterBackend *backend;
+  gint dpi;
+  gint hinting;
+  gchar *hint_style_str;
+  cairo_hint_style_t hint_style = CAIRO_HINT_STYLE_NONE;
+  gint antialias;
+  cairo_antialias_t antialias_mode = CAIRO_ANTIALIAS_NONE;
+  cairo_font_options_t *options;
+
+  g_object_get (settings,
+                "gtk-xft-dpi", &dpi,
+                "gtk-xft-antialias", &antialias,
+                "gtk-xft-hinting", &hinting,
+                "gtk-xft-hintstyle", &hint_style_str,
+                NULL);
+
+  stage = CLUTTER_STAGE (clutter_stage_get_default ());
+  context = st_theme_context_get_for_stage (stage);
+
+  if (dpi != -1)
+    /* GTK stores resolution as 1024 * dots/inch */
+    st_theme_context_set_resolution (context, dpi / 1024);
+  else
+    st_theme_context_set_default_resolution (context);
+
+  /* Clutter (as of 0.9) passes comprehensively wrong font options
+   * override whatever set_font_flags() did above.
+   *
+   * http://bugzilla.openedhand.com/show_bug.cgi?id=1456
+   */
+  backend = clutter_get_default_backend ();
+  options = cairo_font_options_create ();
+
+  cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
+
+  if (hinting >= 0 && !hinting)
+    {
+      hint_style = CAIRO_HINT_STYLE_NONE;
+    }
+  else if (hint_style_str)
+    {
+      if (strcmp (hint_style_str, "hintnone") == 0)
+        hint_style = CAIRO_HINT_STYLE_NONE;
+      else if (strcmp (hint_style_str, "hintslight") == 0)
+        hint_style = CAIRO_HINT_STYLE_SLIGHT;
+      else if (strcmp (hint_style_str, "hintmedium") == 0)
+        hint_style = CAIRO_HINT_STYLE_MEDIUM;
+      else if (strcmp (hint_style_str, "hintfull") == 0)
+        hint_style = CAIRO_HINT_STYLE_FULL;
+    }
+
+  g_free (hint_style_str);
+
+  cairo_font_options_set_hint_style (options, hint_style);
+
+  /* We don't want to turn on subpixel anti-aliasing; since Clutter
+   * doesn't currently have the code to support ARGB masks,
+   * generating them then squashing them back to A8 is pointless.
+   */
+  antialias_mode = (antialias < 0 || antialias) ? CAIRO_ANTIALIAS_GRAY
+                                                : CAIRO_ANTIALIAS_NONE;
+
+  cairo_font_options_set_antialias (options, antialias_mode);
+
+  clutter_backend_set_font_options (backend, options);
+  cairo_font_options_destroy (options);
+}
+
+static void
+settings_notify_cb (GtkSettings *settings,
+                    GParamSpec  *pspec,
+                    gpointer     data)
+{
+  update_font_options (settings);
+}
+
+static void
+shell_fonts_init (void)
+{
+  GtkSettings *settings;
+
+  /* Disable text mipmapping; it causes problems on pre-GEM Intel
+   * drivers and we should just be rendering text at the right
+   * size rather than scaling it. If we do effects where we dynamically
+   * zoom labels, then we might want to reconsider.
+   */
+  clutter_set_font_flags (clutter_get_font_flags () & ~CLUTTER_FONT_MIPMAPPING);
+
+  settings = gtk_settings_get_default ();
+  g_object_connect (settings,
+                    "signal::notify::gtk-xft-dpi",
+                    G_CALLBACK (settings_notify_cb), NULL,
+                    "signal::notify::gtk-xft-antialias",
+                    G_CALLBACK (settings_notify_cb), NULL,
+                    "signal::notify::gtk-xft-hinting",
+                    G_CALLBACK (settings_notify_cb), NULL,
+                    "signal::notify::gtk-xft-hintstyle",
+                    G_CALLBACK (settings_notify_cb), NULL,
+                    NULL);
+  update_font_options (settings);
+}
+
+static void
+shell_prefs_init (void)
+{
+  meta_prefs_override_preference_location ("/apps/mutter/general/attach_modal_dialogs",
+                                           "/desktop/gnome/shell/windows/attach_modal_dialogs");
+  meta_prefs_override_preference_location ("/apps/metacity/general/button_layout",
+                                           "/desktop/gnome/shell/windows/button_layout");
+  meta_prefs_override_preference_location ("/apps/metacity/general/edge_tiling",
+                                           "/desktop/gnome/shell/windows/edge_tiling");
+  meta_prefs_override_preference_location ("/apps/metacity/general/theme",
+                                           "/desktop/gnome/shell/windows/theme");
+}
+
+/* This is an IBus workaround. The flow of events with IBus is that every time
+ * it gets gets a key event, it:
+ *
+ *  Sends it to the daemon via D-Bus asynchronously
+ *  When it gets an reply, synthesizes a new GdkEvent and puts it into the
+ *   GDK event queue with gdk_event_put(), including
+ *   IBUS_FORWARD_MASK = 1 << 25 in the state to prevent a loop.
+ *
+ * (Normally, IBus uses the GTK+ key snooper mechanism to get the key
+ * events early, but since our key events aren't visible to GTK+ key snoopers,
+ * IBus will instead get the events via the standard
+ * GtkIMContext.filter_keypress() mechanism.)
+ *
+ * There are a number of potential problems here; probably the worst
+ * problem is that IBus doesn't forward the timestamp with the event
+ * so that every key event that gets delivered ends up with
+ * GDK_CURRENT_TIME.  This creates some very subtle bugs; for example
+ * if you have IBus running and a keystroke is used to trigger
+ * launching an application, focus stealing prevention won't work
+ * right. http://code.google.com/p/ibus/issues/detail?id=1184
+ *
+ * In any case, our normal flow of key events is:
+ *
+ *  GDK filter function => clutter_x11_handle_event => clutter actor
+ *
+ * So, if we see a key event that gets delivered via the GDK event handler
+ * function - then we know it must be one of these synthesized events, and
+ * we should push it back to clutter.
+ *
+ * To summarize, the full key event flow with IBus is:
+ *
+ *   GDK filter function
+ *     => Mutter
+ *     => gnome_shell_plugin_xevent_filter()
+ *     => clutter_x11_handle_event()
+ *     => clutter event delivery to actor
+ *     => gtk_im_context_filter_event()
+ *     => sent to IBus daemon
+ *     => response received from IBus daemon
+ *     => gdk_event_put()
+ *     => GDK event handler
+ *     => <this function>
+ *     => clutter_event_put()
+ *     => clutter event delivery to actor
+ *
+ * Anything else we see here we just pass on to the normal GDK event handler
+ * gtk_main_do_event().
+ */
+static void
+gnome_shell_gdk_event_handler (GdkEvent *event_gdk,
+                               gpointer  data)
+{
+  if (event_gdk->type == GDK_KEY_PRESS || event_gdk->type == GDK_KEY_RELEASE)
+    {
+      ClutterActor *stage;
+      Window stage_xwindow;
+
+      stage = clutter_stage_get_default ();
+      stage_xwindow = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
+
+      if (GDK_WINDOW_XID (event_gdk->key.window) == stage_xwindow)
+        {
+          ClutterDeviceManager *device_manager = clutter_device_manager_get_default ();
+          ClutterInputDevice *keyboard = clutter_device_manager_get_core_device (device_manager,
+                                                                                 CLUTTER_KEYBOARD_DEVICE);
+
+          ClutterEvent *event_clutter = clutter_event_new ((event_gdk->type == GDK_KEY_PRESS) ?
+                                                           CLUTTER_KEY_PRESS : CLUTTER_KEY_RELEASE);
+          event_clutter->key.time = event_gdk->key.time;
+          event_clutter->key.flags = CLUTTER_EVENT_NONE;
+          event_clutter->key.stage = CLUTTER_STAGE (stage);
+          event_clutter->key.source = NULL;
+
+          /* This depends on ClutterModifierType and GdkModifierType being
+           * identical, which they are currently. (They both match the X
+           * modifier state in the low 16-bits and have the same extensions.) */
+          event_clutter->key.modifier_state = event_gdk->key.state;
+
+          event_clutter->key.keyval = event_gdk->key.keyval;
+          event_clutter->key.hardware_keycode = event_gdk->key.hardware_keycode;
+          event_clutter->key.unicode_value = gdk_keyval_to_unicode (event_clutter->key.keyval);
+          event_clutter->key.device = keyboard;
+
+          clutter_event_put (event_clutter);
+          clutter_event_free (event_clutter);
+
+          return;
+        }
+    }
+
+  gtk_main_do_event (event_gdk);
+}
+
+
+static void
+malloc_statistics_callback (ShellPerfLog *perf_log,
+                            gpointer      data)
+{
+#ifdef HAVE_MALLINFO
+  struct mallinfo info = mallinfo ();
+
+  shell_perf_log_update_statistic_i (perf_log,
+                                     "malloc.arenaSize",
+                                     info.arena);
+  shell_perf_log_update_statistic_i (perf_log,
+                                     "malloc.mmapSize",
+                                     info.hblkhd);
+  shell_perf_log_update_statistic_i (perf_log,
+                                     "malloc.usedSize",
+                                     info.uordblks);
+#endif
+}
+
+static void
+shell_perf_log_init (void)
+{
+  ShellPerfLog *perf_log = shell_perf_log_get_default ();
+
+  /* For probably historical reasons, mallinfo() defines the returned values,
+   * even those in bytes as int, not size_t. We're determined not to use
+   * more than 2G of malloc'ed memory, so are OK with that.
+   */
+  shell_perf_log_define_statistic (perf_log,
+                                   "malloc.arenaSize",
+                                   "Amount of memory allocated by malloc() with brk(), in bytes",
+                                   "i");
+  shell_perf_log_define_statistic (perf_log,
+                                   "malloc.mmapSize",
+                                   "Amount of memory allocated by malloc() with mmap(), in bytes",
+                                   "i");
+  shell_perf_log_define_statistic (perf_log,
+                                   "malloc.usedSize",
+                                   "Amount of malloc'ed memory currently in use",
+                                   "i");
+
+  shell_perf_log_add_statistics_callback (perf_log,
+                                          malloc_statistics_callback,
+                                          NULL, NULL);
+}
+
+static void
+muted_log_handler (const char     *log_domain,
+                   GLogLevelFlags  log_level,
+                   const char     *message,
+                   gpointer        data)
+{
+  /* Intentionally empty to discard message */
+}
+
+static gboolean
+print_version (const gchar    *option_name,
+               const gchar    *value,
+               gpointer        data,
+               GError        **error)
+{
+  g_print ("GNOME Shell %s\n", VERSION);
+  exit (0);
+}
+
+GOptionEntry gnome_shell_options[] = {
+  {
+    "version", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
+    print_version,
+    N_("Print version"),
+    NULL
+  },
+  { NULL }
+};
+
+int
+main (int argc, char **argv)
+{
+  GOptionContext *ctx;
+  GError *error = NULL;
+
+  g_type_init ();
+
+  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+
+  ctx = meta_get_option_context ();
+  g_option_context_add_main_entries (ctx, gnome_shell_options, GETTEXT_PACKAGE);
+  if (!g_option_context_parse (ctx, &argc, &argv, &error))
+    {
+      g_printerr ("%s: %s\n", argv[0], error->message);
+      exit (1);
+    }
+
+  meta_plugin_type_register (gnome_shell_plugin_get_type ());
+
+  /* Prevent meta_init() from causing gtk to load gail and at-bridge */
+  g_setenv ("NO_GAIL", "1", TRUE);
+  g_setenv ("NO_AT_BRIDGE", "1", TRUE);
+  meta_init ();
+  g_unsetenv ("NO_GAIL");
+  g_unsetenv ("NO_AT_BRIDGE");
+
+  /* FIXME: Add gjs API to set this stuff and don't depend on the
+   * environment.  These propagate to child processes.
+   */
+  g_setenv ("GJS_DEBUG_OUTPUT", "stderr", TRUE);
+  g_setenv ("GJS_DEBUG_TOPICS", "JS ERROR;JS LOG", TRUE);
+
+  shell_dbus_init ();
+  shell_a11y_init ();
+  shell_fonts_init ();
+  shell_perf_log_init ();
+  shell_prefs_init ();
+
+  gdk_event_handler_set (gnome_shell_gdk_event_handler, NULL, NULL);
+
+  g_irepository_prepend_search_path (GNOME_SHELL_PKGLIBDIR);
+#if HAVE_BLUETOOTH
+  g_irepository_prepend_search_path (BLUETOOTH_DIR);
+#endif
+
+  /* Disable debug spew from various libraries */
+  g_log_set_handler ("Gvc", G_LOG_LEVEL_DEBUG,
+                     muted_log_handler, NULL);
+  g_log_set_handler ("GdmUser", G_LOG_LEVEL_DEBUG,
+                     muted_log_handler, NULL);
+  g_log_set_handler ("Bluetooth", G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_MESSAGE,
+                     muted_log_handler, NULL);
+
+  /* Initialize the global object */
+  shell_global_get ();
+
+  return meta_run ();
+}
diff --git a/src/shell-a11y.c b/src/shell-a11y.c
index 506df95..c9721ea 100644
--- a/src/shell-a11y.c
+++ b/src/shell-a11y.c
@@ -134,9 +134,6 @@ shell_a11y_init (void)
 {
   char *bridge_path = NULL;
 
-  g_unsetenv ("NO_AT_BRIDGE");
-  g_unsetenv ("NO_GAIL");
-
   if (!should_enable_a11y ())
     return;
 
diff --git a/src/shell-global-private.h b/src/shell-global-private.h
index e175145..5512645 100644
--- a/src/shell-global-private.h
+++ b/src/shell-global-private.h
@@ -8,8 +8,8 @@
 
 void _shell_global_set_plugin      (ShellGlobal  *global,
                                     MetaPlugin   *plugin);
-void _shell_global_set_gjs_context (ShellGlobal  *global,
-                                    GjsContext   *context);
+
+GjsContext *_shell_global_get_gjs_context (ShellGlobal  *global);
 
 gboolean _shell_global_check_xdnd_event (ShellGlobal  *global,
                                          XEvent       *xev);
diff --git a/src/shell-global.c b/src/shell-global.c
index 4f08bca..5a2f2e6 100644
--- a/src/shell-global.c
+++ b/src/shell-global.c
@@ -203,7 +203,8 @@ static void
 shell_global_init (ShellGlobal *global)
 {
   const char *datadir = g_getenv ("GNOME_SHELL_DATADIR");
-  char *imagedir;
+  const char *shell_js = g_getenv("GNOME_SHELL_JS");
+  char *imagedir, **search_path;
 
   if (!datadir)
     datadir = GNOME_SHELL_DATADIR;
@@ -242,6 +243,15 @@ shell_global_init (ShellGlobal *global)
   ca_context_create (&global->sound_context);
   ca_context_change_props (global->sound_context, CA_PROP_APPLICATION_NAME, PACKAGE_NAME, CA_PROP_APPLICATION_ID, "org.gnome.Shell", NULL);
   ca_context_open (global->sound_context);
+
+  if (!shell_js)
+    shell_js = JSDIR;
+  search_path = g_strsplit (shell_js, ":", -1);
+  global->js_context = g_object_new (GJS_TYPE_CONTEXT,
+                                     "search-path", search_path,
+                                     "js-version", "1.8",
+                                     NULL);
+  g_strfreev (search_path);
 }
 
 static void
@@ -791,11 +801,10 @@ _shell_global_set_plugin (ShellGlobal *global,
   global->focus_manager = st_focus_manager_get_for_stage (CLUTTER_STAGE (stage));
 }
 
-void
-_shell_global_set_gjs_context (ShellGlobal *global,
-                               GjsContext  *context)
+GjsContext *
+_shell_global_get_gjs_context (ShellGlobal *global)
 {
-  global->js_context = context;
+  return global->js_context;
 }
 
 /**
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 75a7a73..172dc99 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -27,7 +27,7 @@ EXTRA_DIST += $(TEST_MISC)
 
 run-test.sh: run-test.sh.in
 	$(AM_V_GEN) sed \
-	    -e "s|@MUTTER_LIB_DIR[ ]|$(MUTTER_LIB_DIR)|" \
+	    -e "s|@MUTTER_TYPELIB_DIR[ ]|$(MUTTER_TYPELIB_DIR)|" \
 	    -e "s|@srcdir[ ]|$(srcdir)|" \
 	    $< > $@ && chmod a+x $@
 
diff --git a/tests/run-test.sh.in b/tests/run-test.sh.in
old mode 100644
new mode 100755
index 300ca2b..ee1472f
--- a/tests/run-test.sh.in
+++ b/tests/run-test.sh.in
@@ -30,7 +30,7 @@ builddir=`cd $builddir && pwd`
 srcdir=$builddir/@srcdir@
 srcdir=`cd $srcdir && pwd`
 
-GI_TYPELIB_PATH="@MUTTER_LIB_DIR@/mutter:$builddir/../src"
+GI_TYPELIB_PATH="@MUTTER_TYPELIB_DIR@:$builddir/../src"
 GJS_PATH="$srcdir:$srcdir/../js"
 GJS_DEBUG_OUTPUT=stderr
 $verbose || GJS_DEBUG_TOPICS="JS ERROR;JS LOG"



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]