Allow mutter to be used as a library

Move all of the mutter code into a new libmutter-wm.so, split its
main() method into meta_get_option_context(), meta_init() and
meta_run(), add methods for using in-process plugins, and add
libmutter-wm.pc pointing to the new library.

The mutter binary is now just a tiny program that links against
libmutter-wm. The --version and --mutter-plugins options are handled
at the mutter level, not in libmutter-wm, and a few strange unused
command-line options (--no-force-fullscreen and --no-tab-popup) have
been removed.

https://bugzilla.gnome.org/show_bug.cgi?id=643959
This commit is contained in:
Dan Winship
2011-03-05 16:16:26 -05:00
parent 28752718c5
commit bb50f65532
16 changed files with 314 additions and 268 deletions

View File

@ -75,7 +75,6 @@
#ifdef HAVE_INTROSPECTION
#include <girepository.h>
#include "compositor/meta-plugin-manager.h"
#endif
/**
@ -112,23 +111,6 @@ log_handler (const gchar *log_domain,
meta_print_backtrace ();
}
/**
* Prints the version notice. This is shown when Mutter is called
* with the --version switch.
*/
static void
version (void)
{
const int latest_year = 2010;
g_print (_("mutter %s\n"
"Copyright (C) 2001-%d Havoc Pennington, Red Hat, Inc., and others\n"
"This is free software; see the source for copying conditions.\n"
"There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"),
VERSION, latest_year);
exit (0);
}
/**
* Prints a list of which configure script options were used to
* build this copy of Mutter. This is actually always called
@ -208,131 +190,72 @@ meta_print_self_identity (void)
/**
* The set of possible options that can be set on Mutter's
* command line. This type exists so that meta_parse_options() can
* write to an instance of it.
* command line.
*/
typedef struct
{
gchar *save_file;
gchar *display_name;
gchar *client_id;
gchar *mutter_plugins;
gboolean replace_wm;
gboolean disable_sm;
gboolean print_version;
gboolean sync;
gboolean composite;
gboolean no_composite;
gboolean no_force_fullscreen;
gboolean no_tab_popup;
gchar *introspect;
} MetaArguments;
static gchar *opt_save_file;
static gchar *opt_display_name;
static gchar *opt_client_id;
static gboolean opt_replace_wm;
static gboolean opt_disable_sm;
static gboolean opt_sync;
#define COMPOSITE_OPTS_FLAGS 0
static GOptionEntry meta_options[] = {
{
"sm-disable", 0, 0, G_OPTION_ARG_NONE,
&opt_disable_sm,
N_("Disable connection to session manager"),
NULL
},
{
"replace", 0, 0, G_OPTION_ARG_NONE,
&opt_replace_wm,
N_("Replace the running window manager"),
NULL
},
{
"sm-client-id", 0, 0, G_OPTION_ARG_STRING,
&opt_client_id,
N_("Specify session management ID"),
"ID"
},
{
"display", 'd', 0, G_OPTION_ARG_STRING,
&opt_display_name, N_("X Display to use"),
"DISPLAY"
},
{
"sm-save-file", 0, 0, G_OPTION_ARG_FILENAME,
&opt_save_file,
N_("Initialize session from savefile"),
"FILE"
},
{
"sync", 0, 0, G_OPTION_ARG_NONE,
&opt_sync,
N_("Make X calls synchronous"),
NULL
},
{NULL}
};
/**
* Parses argc and argv and returns the
* arguments that Mutter understands in meta_args.
* meta_get_option_context: (skip)
*
* The strange call signature has to be written like it is so
* that g_option_context_parse() gets a chance to modify argc and
* argv.
* Returns a #GOptionContext initialized with mutter-related options.
* Parse the command-line args with this before calling meta_init().
*
* \param argc Pointer to the number of arguments Mutter was given
* \param argv Pointer to the array of arguments Mutter was given
* \param meta_args The result of parsing the arguments.
**/
static GOptionContext *
meta_parse_options (int *argc, char ***argv,
MetaArguments *meta_args)
* Return value: the #GOptionContext
*/
GOptionContext *
meta_get_option_context (void)
{
MetaArguments my_args = {NULL, NULL, NULL, NULL,
FALSE, FALSE, FALSE, FALSE, FALSE};
GOptionEntry options[] = {
{
"sm-disable", 0, 0, G_OPTION_ARG_NONE,
&my_args.disable_sm,
N_("Disable connection to session manager"),
NULL
},
{
"replace", 0, 0, G_OPTION_ARG_NONE,
&my_args.replace_wm,
N_("Replace the running window manager with Mutter"),
NULL
},
{
"sm-client-id", 0, 0, G_OPTION_ARG_STRING,
&my_args.client_id,
N_("Specify session management ID"),
"ID"
},
{
"display", 'd', 0, G_OPTION_ARG_STRING,
&my_args.display_name, N_("X Display to use"),
"DISPLAY"
},
{
"sm-save-file", 0, 0, G_OPTION_ARG_FILENAME,
&my_args.save_file,
N_("Initialize session from savefile"),
"FILE"
},
{
"version", 0, 0, G_OPTION_ARG_NONE,
&my_args.print_version,
N_("Print version"),
NULL
},
{
"sync", 0, 0, G_OPTION_ARG_NONE,
&my_args.sync,
N_("Make X calls synchronous"),
NULL
},
{
"no-force-fullscreen", 0, COMPOSITE_OPTS_FLAGS, G_OPTION_ARG_NONE,
&my_args.no_force_fullscreen,
N_("Don't make fullscreen windows that are maximized and have no decorations"),
NULL
},
{
"mutter-plugins", 0, 0, G_OPTION_ARG_STRING,
&my_args.mutter_plugins,
N_("Comma-separated list of compositor plugins"),
"PLUGINS"
},
{
"no-tab-popup", 0, 0, G_OPTION_ARG_NONE,
&my_args.no_tab_popup,
N_("Whether window popup/frame should be shown when cycling windows."),
NULL
},
#ifdef HAVE_INTROSPECTION
{
"introspect-dump", 0, 0, G_OPTION_ARG_STRING,
&my_args.introspect,
N_("Internal argument for GObject introspection"), "INTROSPECT"
},
#endif
{NULL}
};
GOptionContext *ctx;
GError *error = NULL;
ctx = g_option_context_new (NULL);
g_option_context_add_main_entries (ctx, options, "mutter");
g_option_context_add_main_entries (ctx, meta_options, GETTEXT_PACKAGE);
g_option_context_add_group (ctx, clutter_get_option_group_without_init ());
g_option_context_add_group (ctx, cogl_get_option_group ());
if (!g_option_context_parse (ctx, argc, argv, &error))
{
g_print ("mutter: %s\n", error->message);
exit(1);
}
/* Return the parsed options through the meta_args param. */
*meta_args = my_args;
return ctx;
}
@ -381,12 +304,12 @@ static GSourceFuncs event_funcs = {
};
static void
meta_clutter_init (GOptionContext *ctx, int *argc, char ***argv)
meta_clutter_init (void)
{
clutter_x11_set_display (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
clutter_x11_disable_event_retrieval ();
if (CLUTTER_INIT_SUCCESS == clutter_init (argc, argv))
if (CLUTTER_INIT_SUCCESS == clutter_init (NULL, NULL))
{
GSource *source = g_source_new (&event_funcs, sizeof (GSource));
g_source_attach (source, NULL);
@ -452,34 +375,18 @@ on_sigterm (void)
}
/**
* This is where the story begins. It parses commandline options and
* environment variables, sets up the screen, hands control off to
* GTK, and cleans up afterwards.
* meta_init: (skip)
*
* \param argc Number of arguments (as usual)
* \param argv Array of arguments (as usual)
*
* \bug It's a bit long. It would be good to split it out into separate
* functions.
* Initialize mutter. Call this after meta_get_option_context() and
* meta_plugin_type_register(), and before meta_run().
*/
int
main (int argc, char **argv)
void
meta_init (void)
{
struct sigaction act;
sigset_t empty_mask;
MetaArguments meta_args;
const gchar *log_domains[] = {
NULL, G_LOG_DOMAIN, "Gtk", "Gdk", "GLib",
"Pango", "GLib-GObject", "GThread"
};
guint i;
GIOChannel *channel;
GOptionContext *ctx;
MetaPluginManager *mgr;
if (!g_thread_supported ())
g_thread_init (NULL);
if (setlocale (LC_ALL, "") == NULL)
meta_warning ("Locale not understood by C library, internationalization will not work\n");
@ -523,8 +430,6 @@ main (int argc, char **argv)
meta_warning ("Could not change to home directory %s.\n",
g_get_home_dir ());
g_type_init ();
meta_print_self_identity ();
bindtextdomain (GETTEXT_PACKAGE, MUTTER_LOCALEDIR);
@ -535,79 +440,51 @@ main (int argc, char **argv)
g_irepository_prepend_search_path (MUTTER_PKGLIBDIR);
#endif
/* Parse command line arguments.*/
ctx = meta_parse_options (&argc, &argv, &meta_args);
meta_set_syncing (opt_sync || (g_getenv ("MUTTER_SYNC") != NULL));
if (meta_args.print_version)
version ();
mgr = meta_plugin_manager_get_default ();
/* This must come before the introspect below, so we load all the plugins
* in order to get their get_type functions.
*/
if (meta_args.mutter_plugins)
{
char **plugins = g_strsplit (meta_args.mutter_plugins, ",", -1);
char **plugin;
for (plugin = plugins; *plugin; plugin++)
{
g_strstrip (*plugin);
meta_plugin_manager_load (mgr, *plugin);
}
g_strfreev (plugins);
}
#ifdef HAVE_INTROSPECTION
if (meta_args.introspect)
{
GError *error = NULL;
if (!g_irepository_dump (meta_args.introspect, &error))
{
g_printerr ("failed to dump: %s\n", error->message);
return 1;
}
return 0;
}
#endif
meta_set_syncing (meta_args.sync || (g_getenv ("MUTTER_SYNC") != NULL));
meta_select_display (meta_args.display_name);
meta_select_display (opt_display_name);
if (meta_args.replace_wm)
if (opt_replace_wm)
meta_set_replace_current_wm (TRUE);
if (meta_args.save_file && meta_args.client_id)
if (opt_save_file && opt_client_id)
meta_fatal ("Can't specify both SM save file and SM client id\n");
meta_main_loop = g_main_loop_new (NULL, FALSE);
meta_ui_init (&argc, &argv);
meta_ui_init ();
/*
* Clutter can only be initialized after the UI.
*/
meta_clutter_init (ctx, &argc, &argv);
meta_clutter_init ();
}
g_option_context_free (ctx);
/**
* meta_run: (skip)
*
* Runs mutter. Call this after completing your own initialization.
*
* Return value: mutter's exit status
*/
int
meta_run (void)
{
const gchar *log_domains[] = {
NULL, G_LOG_DOMAIN, "Gtk", "Gdk", "GLib",
"Pango", "GLib-GObject", "GThread"
};
guint i;
/* Load prefs */
meta_prefs_init ();
meta_prefs_add_listener (prefs_changed_callback, NULL);
#if 1
for (i=0; i<G_N_ELEMENTS(log_domains); i++)
g_log_set_handler (log_domains[i],
G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
log_handler, NULL);
#endif
if (g_getenv ("MUTTER_G_FATAL_WARNINGS") != NULL)
g_log_set_always_fatal (G_LOG_LEVEL_MASK);
@ -651,38 +528,30 @@ main (int argc, char **argv)
* or we might try to manage a window before we have the session
* info
*/
if (!meta_args.disable_sm)
if (!opt_disable_sm)
{
if (meta_args.client_id == NULL)
if (opt_client_id == NULL)
{
const gchar *desktop_autostart_id;
desktop_autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID");
if (desktop_autostart_id != NULL)
meta_args.client_id = g_strdup (desktop_autostart_id);
opt_client_id = g_strdup (desktop_autostart_id);
}
/* Unset DESKTOP_AUTOSTART_ID in order to avoid child processes to
* use the same client id. */
g_unsetenv ("DESKTOP_AUTOSTART_ID");
meta_session_init (meta_args.client_id, meta_args.save_file);
meta_session_init (opt_client_id, opt_save_file);
}
/* Free memory possibly allocated by the argument parsing which are
* no longer needed.
*/
g_free (meta_args.save_file);
g_free (meta_args.display_name);
g_free (meta_args.client_id);
if (meta_args.no_force_fullscreen)
meta_prefs_set_force_fullscreen (FALSE);
if (meta_args.no_tab_popup)
{
meta_prefs_override_no_tab_popup (TRUE);
}
g_free (opt_save_file);
g_free (opt_display_name);
g_free (opt_client_id);
if (!meta_display_open ())
meta_exit (META_EXIT_ERROR);

99
src/core/mutter.c Normal file
View File

@ -0,0 +1,99 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2011 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "config.h"
#include <stdlib.h>
#include "main.h"
#include "util.h"
#ifdef HAVE_INTROSPECTION
#include "compositor/meta-plugin-manager.h"
#endif
#include <glib.h>
static gboolean
print_version (const gchar *option_name,
const gchar *value,
gpointer data,
GError **error)
{
const int latest_year = 2011;
g_print (_("mutter %s\n"
"Copyright (C) 2001-%d Havoc Pennington, Red Hat, Inc., and others\n"
"This is free software; see the source for copying conditions.\n"
"There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"),
VERSION, latest_year);
exit (0);
}
static gchar *mutter_plugins;
GOptionEntry mutter_options[] = {
{
"version", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
print_version,
N_("Print version"),
NULL
},
{
"mutter-plugins", 0, 0, G_OPTION_ARG_STRING,
&mutter_plugins,
N_("Comma-separated list of compositor plugins"),
"PLUGINS"
},
{ NULL }
};
int
main (int argc, char **argv)
{
GOptionContext *ctx;
GError *error = NULL;
ctx = meta_get_option_context ();
g_option_context_add_main_entries (ctx, mutter_options, GETTEXT_PACKAGE);
if (!g_option_context_parse (ctx, &argc, &argv, &error))
{
g_printerr ("mutter: %s\n", error->message);
exit (1);
}
if (mutter_plugins)
{
MetaPluginManager *mgr;
char **plugins = g_strsplit (mutter_plugins, ",", -1);
char **plugin;
mgr = meta_plugin_manager_get_default ();
for (plugin = plugins; *plugin; plugin++)
{
g_strstrip (*plugin);
meta_plugin_manager_load (mgr, *plugin);
}
g_strfreev (plugins);
}
meta_init ();
return meta_run ();
}

View File

@ -3020,12 +3020,6 @@ meta_prefs_set_no_tab_popup (gboolean whether)
#endif
}
void
meta_prefs_override_no_tab_popup (gboolean whether)
{
no_tab_popup = whether;
}
#ifndef HAVE_GCONF
static void
init_button_layout(void)