diff --git a/configure.ac b/configure.ac index e898cab68..31c20e8cd 100644 --- a/configure.ac +++ b/configure.ac @@ -16,7 +16,7 @@ AC_SUBST(GETTEXT_PACKAGE) AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [The prefix for our gettext translation domains.]) -PKG_CHECK_MODULES(MUTTER_PLUGIN, metacity-plugins gjs-gi-1.0) +PKG_CHECK_MODULES(MUTTER_PLUGIN, gtk+-2.0 metacity-plugins gjs-gi-1.0) changequote(,)dnl if test "x$GCC" = "xyes"; then diff --git a/js/ui/main.js b/js/ui/main.js index 56da058f2..c19d4a00e 100644 --- a/js/ui/main.js +++ b/js/ui/main.js @@ -26,6 +26,12 @@ function start() { for (let i = 0; i < children.length; i++) children[i].destroy(); + global.connect('panel-run-dialog', function (panel) { + log("showing main menu!"); + var p = new Shell.Process({'args' : ['gnome-terminal', 'gnome-terminal']}) + p.run() + }); + panel = new Panel.Panel(); overlay = new Overlay.Overlay(); global.set_stage_input_area(0, 0, global.screen_width, Panel.PANEL_HEIGHT); diff --git a/src/Makefile.am b/src/Makefile.am index 9aca09cc8..dc7fdc915 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,6 +8,8 @@ plugin_LTLIBRARIES = libgnome-shell.la libgnome_shell_la_SOURCES = \ gnome-shell-plugin.c \ + shell-process.c \ + shell-process.h \ shell-global.c \ shell-global.h diff --git a/src/gnome-shell-plugin.c b/src/gnome-shell-plugin.c index 25cd91c45..861776ba6 100644 --- a/src/gnome-shell-plugin.c +++ b/src/gnome-shell-plugin.c @@ -30,10 +30,14 @@ #include #include +#include +#include #include #include #include +#include "display.h" + #include "shell-global.h" static gboolean do_init (const char *params); @@ -54,6 +58,9 @@ typedef struct _PluginState { gboolean debug_mode : 1; GjsContext *gjs_context; + Atom panel_action; + Atom panel_action_run_dialog; + Atom panel_action_main_menu; } PluginState; @@ -88,11 +95,16 @@ static gboolean do_init (const char *params) { MutterPlugin *plugin = mutter_get_plugin(); + MetaScreen *screen; + MetaDisplay *display; GError *error = NULL; int status; const char *shell_js; char **search_path; + screen = mutter_plugin_get_screen (plugin); + display = meta_screen_get_display (screen); + plugin_state = g_new0 (PluginState, 1); if (params) @@ -115,6 +127,13 @@ do_init (const char *params) _shell_global_set_plugin (shell_global_get(), plugin); + plugin_state->panel_action = XInternAtom (meta_display_get_xdisplay (display), + "_GNOME_PANEL_ACTION", FALSE); + plugin_state->panel_action_run_dialog = XInternAtom (meta_display_get_xdisplay (display), + "_GNOME_PANEL_ACTION_RUN_DIALOG", FALSE); + plugin_state->panel_action_main_menu = XInternAtom (meta_display_get_xdisplay (display), + "_GNOME_PANEL_ACTION_MAIN_MENU", FALSE); + if (!gjs_context_eval (plugin_state->gjs_context, "const Main = imports.ui.main; Main.start();", -1, @@ -164,9 +183,43 @@ reload (const char *params) return FALSE; } +static gboolean +handle_panel_event (XEvent *xev) +{ + MetaScreen *screen; + MetaDisplay *display; + XClientMessageEvent *xev_client; + Window root; + + screen = mutter_plugin_get_screen (mutter_get_plugin ()); + display = meta_screen_get_display (screen); + + if (xev->type != ClientMessage) + return FALSE; + + root = meta_screen_get_xroot (screen); + + xev_client = (XClientMessageEvent*) xev; + if (!(xev_client->window == root && + xev_client->message_type == plugin_state->panel_action && + xev_client->format == 32)) + return FALSE; + + if (xev_client->data.l[0] == plugin_state->panel_action_run_dialog) + g_signal_emit_by_name (shell_global_get (), "panel-run-dialog", + (guint32) xev_client->data.l[1]); + else if (xev_client->data.l[0] == plugin_state->panel_action_main_menu) + g_signal_emit_by_name (shell_global_get (), "panel-main-menu", + (guint32) xev_client->data.l[1]); + + return TRUE; +} + static gboolean xevent_filter (XEvent *xev) { + if (handle_panel_event (xev)) + return TRUE; return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE; } diff --git a/src/metacity-symbols.c b/src/metacity-symbols.c index 29e559c30..16d99d643 100644 --- a/src/metacity-symbols.c +++ b/src/metacity-symbols.c @@ -31,3 +31,23 @@ mutter_plugin_set_stage_input_area (MutterPlugin *plugin, gint x, gint y, gint width, gint height) { } + +MetaScreen * +mutter_plugin_get_screen (MutterPlugin *plugin) +{ +} + +Display * +meta_display_get_xdisplay (MetaDisplay *display) +{ +} + +MetaDisplay * +meta_screen_get_display (MetaScreen *display) +{ +} + +Window +meta_screen_get_xroot (MetaScreen *display) +{ +} diff --git a/src/shell-global.c b/src/shell-global.c index 4db582460..6a95b34b2 100644 --- a/src/shell-global.c +++ b/src/shell-global.c @@ -8,10 +8,6 @@ struct _ShellGlobal { MutterPlugin *plugin; }; -struct _ShellGlobalClass { - GObjectClass parent_class; -}; - enum { PROP_0, @@ -21,8 +17,18 @@ enum { PROP_STAGE }; +/* Signals */ +enum +{ + PANEL_RUN_DIALOG, + PANEL_MAIN_MENU, + LAST_SIGNAL +}; + G_DEFINE_TYPE(ShellGlobal, shell_global, G_TYPE_OBJECT); +static guint shell_global_signals [LAST_SIGNAL] = { 0 }; + static void shell_global_set_property(GObject *object, guint prop_id, @@ -88,6 +94,24 @@ shell_global_class_init (ShellGlobalClass *klass) gobject_class->get_property = shell_global_get_property; gobject_class->set_property = shell_global_set_property; + shell_global_signals[PANEL_RUN_DIALOG] = + g_signal_new ("panel-run-dialog", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ShellGlobalClass, panel_run_dialog), + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + + shell_global_signals[PANEL_MAIN_MENU] = + g_signal_new ("panel-main-menu", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ShellGlobalClass, panel_main_menu), + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + g_object_class_install_property (gobject_class, PROP_OVERLAY_GROUP, g_param_spec_object ("overlay-group", @@ -169,7 +193,7 @@ shell_global_set_stage_input_area (ShellGlobal *global, GList * shell_global_get_windows (ShellGlobal *global) { - g_return_if_fail (SHELL_IS_GLOBAL (global)); + g_return_val_if_fail (SHELL_IS_GLOBAL (global), NULL); return mutter_plugin_get_windows (global->plugin); } diff --git a/src/shell-global.h b/src/shell-global.h index b33d49909..f128a2a1e 100644 --- a/src/shell-global.h +++ b/src/shell-global.h @@ -17,6 +17,16 @@ typedef struct _ShellGlobalClass ShellGlobalClass; #define SHELL_IS_GLOBAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_GLOBAL)) #define SHELL_GLOBAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_GLOBAL, ShellGlobalClass)) +struct _ShellGlobalClass +{ + GObjectClass parent_class; + + void (*panel_run_dialog) (ShellGlobal *global, + int timestamp); + void (*panel_main_menu) (ShellGlobal *global, + int timestamp); +}; + GType shell_global_get_type (void) G_GNUC_CONST; ShellGlobal *shell_global_get (void); diff --git a/src/shell-process.c b/src/shell-process.c new file mode 100644 index 000000000..76d745af4 --- /dev/null +++ b/src/shell-process.c @@ -0,0 +1,127 @@ +#include "shell-process.h" + +#include +#include + +struct _ShellProcessPrivate { + char **args; + GPid pid; +}; + +enum { + PROP_0, + PROP_ARGS, +}; + +static void shell_process_dispose (GObject *object); +static void shell_process_finalize (GObject *object); +static void shell_process_set_property ( GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec ); +static void shell_process_get_property( GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec ); + +G_DEFINE_TYPE( ShellProcess, shell_process, G_TYPE_OBJECT); + +static void shell_process_class_init( ShellProcessClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *)klass; + + gobject_class->dispose = shell_process_dispose; + gobject_class->finalize = shell_process_finalize; + gobject_class->set_property = shell_process_set_property; + gobject_class->get_property = shell_process_get_property; + + g_object_class_install_property (gobject_class, + PROP_ARGS, + g_param_spec_boxed ("args", + "Arguments", + "", + G_TYPE_STRV, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + +} + +static void shell_process_init (ShellProcess *self) +{ + self->priv = g_new0 (ShellProcessPrivate, 1); +} + +static void shell_process_dispose (GObject *object) +{ + ShellProcess *self = (ShellProcess*)object; + + G_OBJECT_CLASS (shell_process_parent_class)->dispose(object); +} + +static void shell_process_finalize (GObject *object) +{ + ShellProcess *self = (ShellProcess*)object; + + g_free (self->priv); + g_signal_handlers_destroy(object); + G_OBJECT_CLASS (shell_process_parent_class)->finalize(object); +} +static void shell_process_set_property ( GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec ) +{ + ShellProcess* self = SHELL_PROCESS(object); + switch (property_id) { + case PROP_ARGS: + self->priv->args = (char**) g_value_dup_boxed (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + + +static void shell_process_get_property ( GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec ) +{ + ShellProcess* self = SHELL_PROCESS(object); + switch (property_id) { + case PROP_ARGS: + g_value_set_boxed (value, self->priv->args); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +ShellProcess* shell_process_new(char **args) +{ + return (ShellProcess*) g_object_new(SHELL_TYPE_PROCESS, + "args", args, + NULL); +} + +gboolean +shell_process_run (ShellProcess *self, + GError **error) +{ + return g_spawn_async (NULL, self->priv->args, NULL, + G_SPAWN_SEARCH_PATH, NULL, NULL, + &self->priv->pid, + error); +} +/* +int +shell_process_wait (ShellProcess *self) +{ + int status; + + waitpid ((pid_t) self->priv->pid, &status, 0); + + return status; +} +*/ diff --git a/src/shell-process.h b/src/shell-process.h new file mode 100644 index 000000000..c3c1991b8 --- /dev/null +++ b/src/shell-process.h @@ -0,0 +1,36 @@ +#ifndef __SHELL_PROCESS_H__ +#define __SHELL_PROCESS_H__ + +#include + +#define SHELL_TYPE_PROCESS (shell_process_get_type ()) +#define SHELL_PROCESS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHELL_TYPE_PROCESS, ShellProcess)) +#define SHELL_PROCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_PROCESS, ShellProcessClass)) +#define SHELL_IS_PROCESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SHELL_TYPE_PROCESS)) +#define SHELL_IS_PROCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_PROCESS)) +#define SHELL_PROCESS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_PROCESS, ShellProcessClass)) + +typedef struct _ShellProcess ShellProcess; +typedef struct _ShellProcessClass ShellProcessClass; + +typedef struct _ShellProcessPrivate ShellProcessPrivate; + +struct _ShellProcess +{ + GObject parent; + + ShellProcessPrivate *priv; +}; + +struct _ShellProcessClass +{ + GObjectClass parent_class; + +}; + +GType shell_process_get_type (void) G_GNUC_CONST; +ShellProcess* shell_process_new(char **args); + +gboolean shell_process_run (ShellProcess *process, GError **error); + +#endif /* __SHELL_PROCESS_H__ */