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
This commit is contained in:
Dan Winship 2011-02-25 11:20:27 -05:00
parent c4dad3d2c1
commit ae96b0c971
12 changed files with 553 additions and 538 deletions

2
.gitignore vendored
View File

@ -44,7 +44,7 @@ src/calendar-server/org.gnome.Shell.CalendarServer.service
src/gnome-shell src/gnome-shell
src/gnome-shell-calendar-server src/gnome-shell-calendar-server
src/gnome-shell-extension-tool src/gnome-shell-extension-tool
src/gnome-shell-installed src/gnome-shell-real
src/gnome-shell-jhbuild src/gnome-shell-jhbuild
src/run-js-test src/run-js-test
src/test-recorder src/test-recorder

View File

@ -74,10 +74,10 @@ TELEPATHY_GLIB_MIN_VERSION=0.13.12
POLKIT_MIN_VERSION=0.100 POLKIT_MIN_VERSION=0.100
# Collect more than 20 libraries for a prize! # Collect more than 20 libraries for a prize!
PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION PKG_CHECK_MODULES(GNOME_SHELL, gio-2.0 >= $GIO_MIN_VERSION
gio-unix-2.0 dbus-glib-1 libxml-2.0 gio-unix-2.0 dbus-glib-1 libxml-2.0
gtk+-3.0 >= $GTK_MIN_VERSION gtk+-3.0 >= $GTK_MIN_VERSION
mutter-plugins >= $MUTTER_MIN_VERSION libmutter-wm >= $MUTTER_MIN_VERSION
gjs-internals-1.0 >= $GJS_MIN_VERSION gjs-internals-1.0 >= $GJS_MIN_VERSION
libgnome-menu $recorder_modules gconf-2.0 libgnome-menu $recorder_modules gconf-2.0
gdk-x11-3.0 gdk-x11-3.0
@ -97,8 +97,8 @@ GOBJECT_INTROSPECTION_CHECK([$GOBJECT_INTROSPECTION_MIN_VERSION])
saved_CFLAGS=$CFLAGS saved_CFLAGS=$CFLAGS
saved_LIBS=$LIBS saved_LIBS=$LIBS
CFLAGS=$MUTTER_PLUGIN_CFLAGS CFLAGS=$GNOME_SHELL_CFLAGS
LIBS=$MUTTER_PLUGIN_LIBS LIBS=$GNOME_SHELL_LIBS
# sn_startup_sequence_get_application_id, we can replace with a version check later # 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) AC_CHECK_FUNCS(JS_NewGlobalObject sn_startup_sequence_get_application_id)
CFLAGS=$saved_CFLAGS 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_CFLAGS)
AC_SUBST(CALENDAR_SERVER_LIBS) AC_SUBST(CALENDAR_SERVER_LIBS)
MUTTER_BIN_DIR=`$PKG_CONFIG --variable=exec_prefix mutter-plugins`/bin MUTTER_GIR_DIR=`$PKG_CONFIG --variable=girdir libmutter-wm`
# FIXME: metacity-plugins.pc should point directly to its .gir file MUTTER_TYPELIB_DIR=`$PKG_CONFIG --variable=typelibdir libmutter-wm`
MUTTER_LIB_DIR=`$PKG_CONFIG --variable=libdir mutter-plugins` AC_SUBST(MUTTER_GIR_DIR)
MUTTER_PLUGIN_DIR=`$PKG_CONFIG --variable=plugindir mutter-plugins` AC_SUBST(MUTTER_TYPELIB_DIR)
AC_SUBST(MUTTER_BIN_DIR)
AC_SUBST(MUTTER_LIB_DIR)
AC_SUBST(MUTTER_PLUGIN_DIR)
GJS_CONSOLE=`$PKG_CONFIG --variable=gjs_console gjs-1.0` GJS_CONSOLE=`$PKG_CONFIG --variable=gjs_console gjs-1.0`
AC_SUBST(GJS_CONSOLE) AC_SUBST(GJS_CONSOLE)
@ -207,9 +204,6 @@ AC_ARG_ENABLE(dynamic-mozjs-hack,
ENABLE_DYNAMIC_MOZJS_HACK=$enable_dynamic_mozjs_hack ENABLE_DYNAMIC_MOZJS_HACK=$enable_dynamic_mozjs_hack
AC_SUBST(ENABLE_DYNAMIC_MOZJS_HACK) AC_SUBST(ENABLE_DYNAMIC_MOZJS_HACK)
AC_PATH_PROG(mutter, [mutter])
AC_SUBST(mutter)
AC_CONFIG_FILES([ AC_CONFIG_FILES([
Makefile Makefile
data/Makefile data/Makefile

View File

@ -10,17 +10,31 @@ noinst_PROGRAMS =
-include $(INTROSPECTION_MAKEFILE) -include $(INTROSPECTION_MAKEFILE)
INTROSPECTION_GIRS = INTROSPECTION_GIRS =
INTROSPECTION_SCANNER_ARGS = --warn-all --warn-error --add-include-path=$(srcdir) 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) typelibdir = $(pkglibdir)
typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
CLEANFILES += $(gir_DATA) $(typelib_DATA) CLEANFILES += $(gir_DATA) $(typelib_DATA)
generated_bin_scripts = gnome-shell-installed gnome-shell-jhbuild gnome-shell-extension-tool bin_SCRIPTS += gnome-shell-extension-tool
bin_SCRIPTS += gnome-shell $(generated_bin_scripts) 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|@datadir[@]|$(datadir)|" \
-e "s|@libexecdir[@]|$(libexecdir)|" \ -e "s|@libexecdir[@]|$(libexecdir)|" \
-e "s|@libdir[@]|$(libdir)|" \ -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 gnome-shell-jhbuild: gnome-shell-jhbuild.in Makefile
$(AM_V_GEN) sed $(generated_script_substitutions) $< > $@.tmp && mv $@.tmp $@ && chmod a+x $@ $(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 gnome-shell-extension-tool: gnome-shell-extension-tool.in Makefile
$(AM_V_GEN) sed $(generated_script_substitutions) $< > $@.tmp && mv $@.tmp $@ && chmod a+x $@ $(AM_V_GEN) sed $(generated_script_substitutions) $< > $@.tmp && mv $@.tmp $@ && chmod a+x $@
if USE_JHBUILD_WRAPPER_SCRIPT CLEANFILES += gnome-shell $(bin_SCRIPTS)
gnome-shell: gnome-shell-jhbuild Makefile EXTRA_DIST += $(bin_SCRIPTS:=.in)
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)
include Makefile-gdmuser.am include Makefile-gdmuser.am
include Makefile-st.am include Makefile-st.am
@ -57,17 +60,17 @@ include Makefile-gvc.am
include Makefile-calendar-server.am include Makefile-calendar-server.am
gnome_shell_cflags = \ gnome_shell_cflags = \
$(MUTTER_PLUGIN_CFLAGS) \ $(GNOME_SHELL_CFLAGS) \
$(LIBGNOMEUI_CFLAGS) \
-I$(srcdir)/tray \ -I$(srcdir)/tray \
-DVERSION=\"$(VERSION)\" \
-DLOCALEDIR=\"$(datadir)/locale\" \ -DLOCALEDIR=\"$(datadir)/locale\" \
-DGNOME_SHELL_LIBEXECDIR=\"$(libexecdir)\" \ -DGNOME_SHELL_LIBEXECDIR=\"$(libexecdir)\" \
-DGNOME_SHELL_DATADIR=\"$(pkgdatadir)\" \ -DGNOME_SHELL_DATADIR=\"$(pkgdatadir)\" \
-DGNOME_SHELL_PKGLIBDIR=\"$(pkglibdir)\" \ -DGNOME_SHELL_PKGLIBDIR=\"$(pkglibdir)\" \
-DJSDIR=\"$(pkgdatadir)/js\" -DJSDIR=\"$(pkgdatadir)/js\"
plugindir = $(MUTTER_PLUGIN_DIR) privlibdir = $(pkglibdir)
plugin_LTLIBRARIES = libgnome-shell.la privlib_LTLIBRARIES = libgnome-shell.la
shell_built_sources = \ shell_built_sources = \
shell-marshal.h \ shell-marshal.h \
@ -134,6 +137,11 @@ libgnome_shell_la_SOURCES = \
libgnome_shell_la_gir_sources = \ libgnome_shell_la_gir_sources = \
$(filter-out %-private.h $(shell_recorder_non_gir_sources), $(shell_public_headers_h) $(libgnome_shell_la_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 = \ shell_recorder_sources = \
@ -232,11 +240,10 @@ shell-enum-types.c: shell-enum-types.c.in stamp-shell-enum-types.h
rm -f $@.tmp rm -f $@.tmp
EXTRA_DIST += shell-enum-types.c.in EXTRA_DIST += shell-enum-types.c.in
libgnome_shell_la_LDFLAGS = -avoid-version -module libgnome_shell_la_LDFLAGS = -avoid-version
libgnome_shell_la_LIBADD = \ libgnome_shell_la_LIBADD = \
-lm \ -lm \
$(MUTTER_PLUGIN_LIBS) \ $(GNOME_SHELL_LIBS) \
$(LIBGNOMEUI_LIBS) \
$(BLUETOOTH_LIBS) \ $(BLUETOOTH_LIBS) \
libst-1.0.la \ libst-1.0.la \
libgdmuser-1.0.la \ libgdmuser-1.0.la \
@ -244,7 +251,7 @@ libgnome_shell_la_LIBADD = \
libgvc.la \ libgvc.la \
$(NULL) $(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: libgnome-shell.la St-1.0.gir
Shell_0_1_gir_INCLUDES = Clutter-1.0 ClutterX11-1.0 Meta-2.91 TelepathyGLib-0.12 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_LIBS = libgnome-shell.la
Shell_0_1_gir_FILES = $(addprefix $(srcdir)/,$(libgnome_shell_la_gir_sources)) Shell_0_1_gir_FILES = $(addprefix $(srcdir)/,$(libgnome_shell_la_gir_sources))
Shell_0_1_gir_SCANNERFLAGS = --include-uninstalled=$(builddir)/St-1.0.gir \ Shell_0_1_gir_SCANNERFLAGS = --include-uninstalled=$(builddir)/St-1.0.gir \
--add-include-path=$(MUTTER_LIB_DIR)/mutter/ \ --add-include-path=$(MUTTER_GIR_DIR)
--program=mutter \
--program-arg=--mutter-plugins=`pwd`/libgnome-shell.la
INTROSPECTION_GIRS += Shell-0.1.gir INTROSPECTION_GIRS += Shell-0.1.gir
St-1.0.gir: libst-1.0.la St-1.0.gir: libst-1.0.la

View File

@ -1,41 +0,0 @@
#!/bin/bash
# gnome-shell is a plugin for mutter; start mutter with the right
# options.
# About the value of NO_GAIL and NO_AT_BRIDGE: If a11y is enabled,
# gtk_init() will normally load gail and at-bridge. But we don't
# want at-bridge to be loaded until after clutter is initialized
# (which mutter does after initializing gtk) and we don't want
# gail to be loaded at all. So set these flags. shell_a11y_init()
# will clear them so they don't get passed to gnome-shell's
# children.
export NO_GAIL=1
export NO_AT_BRIDGE=1
# FIXME - Add gjs API to set this stuff and don't depend on the
# environment. These propagate to child processes.
export GJS_DEBUG_OUTPUT='stderr'
# By default only let gjs show errors and things that are explicitly
# logged via log() from javascript
export GJS_DEBUG_TOPICS='JS ERROR;JS LOG'
if test -z "$MUTTER_PLUGINS"; then
MUTTER_PLUGINS=libgnome-shell
fi
# Work around Ubuntu xulrunner bug,
# http://bugzilla.gnome.org/show_bug.cgi?id=573413
if test x@ENABLE_DYNAMIC_MOZJS_HACK@ = xyes; then
sdkdir=$(pkg-config --variable=sdkdir mozilla-js)
if test -n "${sdkdir}"; then
mozjs_libdir=$(echo "$sdkdir" | sed -e s,'-\(sdk\|devel\)',,)
if test -n "$LD_LIBRARY_PATH"; then
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$mozjs_libdir
else
LD_LIBRARY_PATH=$mozjs_libdir
fi
export LD_LIBRARY_PATH
fi
fi
exec mutter --mutter-plugins=$MUTTER_PLUGINS "$@"

View File

@ -143,17 +143,15 @@ def start_dconf_await_service():
loop.run() loop.run()
def start_shell(perf_output=None): def start_shell(perf_output=None):
bin_dir = os.path.dirname(os.path.abspath(sys.argv[0])) self_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
if os.path.exists(os.path.join(bin_dir, 'gnome-shell-jhbuild.in')): if os.path.exists(os.path.join(self_dir, 'gnome-shell-jhbuild.in')):
running_from_source_tree = True running_from_source_tree = True
top_dir = os.path.dirname(bin_dir) top_dir = os.path.dirname(self_dir)
plugin = os.path.join(top_dir, 'src', 'libgnome-shell.la')
typelib_dir = os.path.join(top_dir, "src") typelib_dir = os.path.join(top_dir, "src")
js_dir = os.path.join(top_dir, "js") js_dir = os.path.join(top_dir, "js")
data_dir = os.path.join(top_dir, "data") data_dir = os.path.join(top_dir, "data")
else: else:
running_from_source_tree = False running_from_source_tree = False
plugin = 'libgnome-shell'
js_dir = os.path.join('@pkgdatadir@', 'js') js_dir = os.path.join('@pkgdatadir@', 'js')
# Set up environment # Set up environment
@ -166,13 +164,13 @@ def start_shell(perf_output=None):
# below. Otherwise it's just a bad reimplementation of "jhbuild # below. Otherwise it's just a bad reimplementation of "jhbuild
# run". See bug #642084 # run". See bug #642084
env.update({'GNOME_SHELL_JS' : js_dir, 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_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')}) 'XDG_DATA_DIRS' : '@datadir@:' + (os.environ.get('XDG_DATA_DIRS') or '/usr/local/share:/usr/share')})
if running_from_source_tree: if running_from_source_tree:
if os.environ.has_key('GI_TYPELIB_PATH'): if os.environ.has_key('GI_TYPELIB_PATH'):
typelib_dir = typelib_dir + ":" + os.environ.get('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, 'GNOME_SHELL_DATADIR' : data_dir,
'GI_TYPELIB_PATH' : typelib_dir, 'GI_TYPELIB_PATH' : typelib_dir,
'GSETTINGS_SCHEMA_DIR' : data_dir }) 'GSETTINGS_SCHEMA_DIR' : data_dir })
@ -191,15 +189,14 @@ def start_shell(perf_output=None):
if perf_output is not None: if perf_output is not None:
env['SHELL_PERF_OUTPUT'] = perf_output env['SHELL_PERF_OUTPUT'] = perf_output
args = []
if options.debug: if options.debug:
debug_command = options.debug_command.split() debug_command = options.debug_command.split()
args = list(debug_command)
else:
args = []
if running_from_source_tree: if running_from_source_tree:
env['MUTTER_PLUGINS'] = plugin args += [os.path.join(top_dir, 'libtool'), '--mode=execute']
args.append(os.path.join(bin_dir, 'gnome-shell-installed')) args += debug_command
args.append(os.path.join(self_dir, 'gnome-shell-real'))
if options.replace: if options.replace:
args.append('--replace') args.append('--replace')
if options.sync: if options.sync:
@ -427,9 +424,9 @@ def run_performance_test():
} }
# Add the Git revision if available # Add the Git revision if available
bin_dir = os.path.dirname(os.path.abspath(sys.argv[0])) self_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
if os.path.exists(os.path.join(bin_dir, 'gnome-shell.in')): if os.path.exists(os.path.join(self_dir, 'gnome-shell-jhbuild.in')):
top_dir = os.path.dirname(bin_dir) top_dir = os.path.dirname(self_dir)
git_dir = os.path.join(top_dir, '.git') git_dir = os.path.join(top_dir, '.git')
if os.path.exists(git_dir): if os.path.exists(git_dir):
env = dict(os.environ) env = dict(os.environ)

View File

@ -27,19 +27,9 @@
#include <meta-plugin.h> #include <meta-plugin.h>
#include <glib/gi18n-lib.h>
#include <clutter/clutter.h> #include <clutter/clutter.h>
#include <clutter/x11/clutter-x11.h> #include <clutter/x11/clutter-x11.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <gjs/gjs.h> #include <gjs/gjs.h>
#include <girepository.h>
#include <gmodule.h>
#ifdef HAVE_MALLINFO
#include <malloc.h>
#endif
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -51,16 +41,10 @@
#include "shell-global-private.h" #include "shell-global-private.h"
#include "shell-perf-log.h" #include "shell-perf-log.h"
#include "shell-wm-private.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_dispose (GObject *object);
static void gnome_shell_plugin_finalize (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_start (MetaPlugin *plugin);
static void gnome_shell_plugin_minimize (MetaPlugin *plugin, static void gnome_shell_plugin_minimize (MetaPlugin *plugin,
MetaWindowActor *actor); MetaWindowActor *actor);
@ -110,7 +94,6 @@ struct _GnomeShellPlugin
{ {
MetaPlugin parent; MetaPlugin parent;
GjsContext *gjs_context;
Atom panel_action; Atom panel_action;
Atom panel_action_run_dialog; Atom panel_action_run_dialog;
Atom panel_action_main_menu; Atom panel_action_main_menu;
@ -127,11 +110,9 @@ struct _GnomeShellPluginClass
MetaPluginClass parent_class; MetaPluginClass parent_class;
}; };
/* GType gnome_shell_plugin_get_type (void);
* Create the plugin struct; function pointers initialized in
* g_module_check_init(). G_DEFINE_TYPE (GnomeShellPlugin, gnome_shell_plugin, META_TYPE_PLUGIN)
*/
META_PLUGIN_DECLARE(GnomeShellPlugin, gnome_shell_plugin);
static void static void
gnome_shell_plugin_class_init (GnomeShellPluginClass *klass) 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->dispose = gnome_shell_plugin_dispose;
gobject_class->finalize = gnome_shell_plugin_finalize; 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->start = gnome_shell_plugin_start;
plugin_class->map = gnome_shell_plugin_map; plugin_class->map = gnome_shell_plugin_map;
plugin_class->minimize = gnome_shell_plugin_minimize; plugin_class->minimize = gnome_shell_plugin_minimize;
@ -162,328 +142,6 @@ gnome_shell_plugin_class_init (GnomeShellPluginClass *klass)
static void static void
gnome_shell_plugin_init (GnomeShellPlugin *shell_plugin) 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 static void
@ -493,32 +151,10 @@ gnome_shell_plugin_start (MetaPlugin *plugin)
MetaScreen *screen; MetaScreen *screen;
MetaDisplay *display; MetaDisplay *display;
Display *xdisplay; Display *xdisplay;
GtkSettings *settings;
GError *error = NULL; GError *error = NULL;
int status; int status;
const char *shell_js;
char **search_path;
const char *glx_extensions; const char *glx_extensions;
GjsContext *gjs_context;
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);
screen = meta_plugin_get_screen (plugin); screen = meta_plugin_get_screen (plugin);
display = meta_screen_get_display (screen); 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)", "GL buffer swap complete event received (with timestamp of completion)",
"x"); "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_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();", "const Main = imports.ui.main; Main.start();",
-1, -1,
"<main>", "<main>",
@ -752,17 +360,3 @@ MetaPluginInfo *gnome_shell_plugin_plugin_info (MetaPlugin *plugin)
return &info; 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

460
src/main.c Normal file
View File

@ -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 ();
}

View File

@ -134,9 +134,6 @@ shell_a11y_init (void)
{ {
char *bridge_path = NULL; char *bridge_path = NULL;
g_unsetenv ("NO_AT_BRIDGE");
g_unsetenv ("NO_GAIL");
if (!should_enable_a11y ()) if (!should_enable_a11y ())
return; return;

View File

@ -8,8 +8,8 @@
void _shell_global_set_plugin (ShellGlobal *global, void _shell_global_set_plugin (ShellGlobal *global,
MetaPlugin *plugin); 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, gboolean _shell_global_check_xdnd_event (ShellGlobal *global,
XEvent *xev); XEvent *xev);

View File

@ -203,7 +203,8 @@ static void
shell_global_init (ShellGlobal *global) shell_global_init (ShellGlobal *global)
{ {
const char *datadir = g_getenv ("GNOME_SHELL_DATADIR"); 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) if (!datadir)
datadir = GNOME_SHELL_DATADIR; datadir = GNOME_SHELL_DATADIR;
@ -242,6 +243,15 @@ shell_global_init (ShellGlobal *global)
ca_context_create (&global->sound_context); 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_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); 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 static void
@ -791,11 +801,10 @@ _shell_global_set_plugin (ShellGlobal *global,
global->focus_manager = st_focus_manager_get_for_stage (CLUTTER_STAGE (stage)); global->focus_manager = st_focus_manager_get_for_stage (CLUTTER_STAGE (stage));
} }
void GjsContext *
_shell_global_set_gjs_context (ShellGlobal *global, _shell_global_get_gjs_context (ShellGlobal *global)
GjsContext *context)
{ {
global->js_context = context; return global->js_context;
} }
/** /**

View File

@ -27,7 +27,7 @@ EXTRA_DIST += $(TEST_MISC)
run-test.sh: run-test.sh.in run-test.sh: run-test.sh.in
$(AM_V_GEN) sed \ $(AM_V_GEN) sed \
-e "s|@MUTTER_LIB_DIR[@]|$(MUTTER_LIB_DIR)|" \ -e "s|@MUTTER_TYPELIB_DIR[@]|$(MUTTER_TYPELIB_DIR)|" \
-e "s|@srcdir[@]|$(srcdir)|" \ -e "s|@srcdir[@]|$(srcdir)|" \
$< > $@ && chmod a+x $@ $< > $@ && chmod a+x $@

2
tests/run-test.sh.in Normal file → Executable file
View File

@ -30,7 +30,7 @@ builddir=`cd $builddir && pwd`
srcdir=$builddir/@srcdir@ srcdir=$builddir/@srcdir@
srcdir=`cd $srcdir && pwd` 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_PATH="$srcdir:$srcdir/../js"
GJS_DEBUG_OUTPUT=stderr GJS_DEBUG_OUTPUT=stderr
$verbose || GJS_DEBUG_TOPICS="JS ERROR;JS LOG" $verbose || GJS_DEBUG_TOPICS="JS ERROR;JS LOG"