add the initial framework of a window management interface. #561724

svn path=/trunk/; revision=70
This commit is contained in:
Dan Winship 2008-11-21 14:02:09 +00:00
parent 06bde9cc98
commit 7dba934b96
9 changed files with 335 additions and 6 deletions

View File

@ -6,6 +6,7 @@ const Clutter = imports.gi.Clutter;
const Panel = imports.ui.panel; const Panel = imports.ui.panel;
const Overlay = imports.ui.overlay; const Overlay = imports.ui.overlay;
const RunDialog = imports.ui.run_dialog; const RunDialog = imports.ui.run_dialog;
const WindowManager = imports.ui.windowmanager;
const DEFAULT_BACKGROUND_COLOR = new Clutter.Color(); const DEFAULT_BACKGROUND_COLOR = new Clutter.Color();
DEFAULT_BACKGROUND_COLOR.from_pixel(0x2266bbff); DEFAULT_BACKGROUND_COLOR.from_pixel(0x2266bbff);
@ -13,6 +14,7 @@ DEFAULT_BACKGROUND_COLOR.from_pixel(0x2266bbff);
let panel = null; let panel = null;
let overlay = null; let overlay = null;
let run_dialog = null; let run_dialog = null;
let wm = null;
function start() { function start() {
let global = Shell.global_get(); let global = Shell.global_get();
@ -43,8 +45,10 @@ function start() {
}); });
panel = new Panel.Panel(); panel = new Panel.Panel();
overlay = new Overlay.Overlay();
global.set_stage_input_area(0, 0, global.screen_width, Panel.PANEL_HEIGHT); global.set_stage_input_area(0, 0, global.screen_width, Panel.PANEL_HEIGHT);
overlay = new Overlay.Overlay();
wm = new WindowManager.WindowManager();
} }
function show_overlay() { function show_overlay() {

29
js/ui/windowmanager.js Normal file
View File

@ -0,0 +1,29 @@
/* -*- mode: js2; js2-basic-offset: 4; -*- */
const Clutter = imports.gi.Clutter;
const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell;
const Main = imports.ui.main;
function WindowManager(shellwm) {
this._init(shellwm);
}
WindowManager.prototype = {
_init : function(shellwm) {
let global = Shell.global_get();
let shellwm = global.window_manager;
shellwm.connect('switch-workspace',
function(o, from, to, direction) {
let actors = shellwm.get_switch_workspace_actors();
for (let i = 0; i < actors.length; i++) {
if (actors[i].get_workspace() == from)
actors[i].hide();
else if (actors[i].get_workspace() == to)
actors[i].show();
}
});
}
};

View File

@ -13,7 +13,17 @@ gnome_shell_cflags = \
plugindir = $(libdir)/metacity/plugins/clutter plugindir = $(libdir)/metacity/plugins/clutter
plugin_LTLIBRARIES = libgnome-shell.la plugin_LTLIBRARIES = libgnome-shell.la
shell_built_sources = \
shell-marshal.h \
shell-marshal.c
BUILT_SOURCES += $(shell_built_sources)
SHELL_STAMP_FILES = stamp-shell-marshal.h
CLEANFILES += $(SHELL_STAMP_FILES)
libgnome_shell_la_SOURCES = \ libgnome_shell_la_SOURCES = \
$(shell_built_sources) \
gnome-shell-plugin.c \ gnome-shell-plugin.c \
shell-app-monitor.c \ shell-app-monitor.c \
shell-app-monitor.h \ shell-app-monitor.h \
@ -22,7 +32,29 @@ libgnome_shell_la_SOURCES = \
shell-global.c \ shell-global.c \
shell-global.h \ shell-global.h \
shell-tray-manager.c \ shell-tray-manager.c \
shell-tray-manager.h shell-tray-manager.h \
shell-wm.c \
shell-wm.h
shell-marshal.h: stamp-shell-marshal.h
@true
stamp-shell-marshal.h: Makefile shell-marshal.list
$(GLIB_GENMARSHAL) \
--prefix=_shell_marshal \
--header \
$(srcdir)/shell-marshal.list > xgen-tmh && \
(cmp -s xgen-tmh shell-marshal.h || cp -f xgen-tmh shell-marshal.h) && \
rm -f xgen-tmh && \
echo timestamp > $(@F)
shell-marshal.c: Makefile shell-marshal.list
(echo "#include \"shell-marshal.h\"" ; \
$(GLIB_GENMARSHAL) \
--prefix=_shell_marshal \
--body \
$(srcdir)/shell-marshal.list ) > xgen-tmc && \
cp -f xgen-tmc shell-marshal.c && \
rm -f xgen-tmc
libgnome_shell_la_LDFLAGS = -avoid-version -module libgnome_shell_la_LDFLAGS = -avoid-version -module
libgnome_shell_la_LIBADD = \ libgnome_shell_la_LIBADD = \

View File

@ -84,6 +84,11 @@ g_module_check_init (GModule *module)
/* Event handling */ /* Event handling */
plugin->xevent_filter = xevent_filter; plugin->xevent_filter = xevent_filter;
/* This will also create the ShellWM, which will set the appropriate
* window management callbacks in plugin.
*/
_shell_global_set_plugin (shell_global_get(), plugin);
return NULL; return NULL;
} }
@ -125,8 +130,6 @@ do_init (const char *params)
plugin_state->gjs_context = gjs_context_new_with_search_path(search_path); plugin_state->gjs_context = gjs_context_new_with_search_path(search_path);
g_strfreev(search_path); g_strfreev(search_path);
_shell_global_set_plugin (shell_global_get(), plugin);
plugin_state->panel_action = XInternAtom (meta_display_get_xdisplay (display), plugin_state->panel_action = XInternAtom (meta_display_get_xdisplay (display),
"_GNOME_PANEL_ACTION", FALSE); "_GNOME_PANEL_ACTION", FALSE);
plugin_state->panel_action_run_dialog = XInternAtom (meta_display_get_xdisplay (display), plugin_state->panel_action_run_dialog = XInternAtom (meta_display_get_xdisplay (display),

View File

@ -1,6 +1,7 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#include "shell-global.h" #include "shell-global.h"
#include "shell-wm.h"
#include "display.h" #include "display.h"
#include <clutter/x11/clutter-x11.h> #include <clutter/x11/clutter-x11.h>
@ -9,6 +10,7 @@ struct _ShellGlobal {
GObject parent; GObject parent;
MutterPlugin *plugin; MutterPlugin *plugin;
ShellWM *wm;
}; };
enum { enum {
@ -19,7 +21,8 @@ enum {
PROP_SCREEN_WIDTH, PROP_SCREEN_WIDTH,
PROP_SCREEN_HEIGHT, PROP_SCREEN_HEIGHT,
PROP_STAGE, PROP_STAGE,
PROP_WINDOW_GROUP PROP_WINDOW_GROUP,
PROP_WINDOW_MANAGER
}; };
/* Signals */ /* Signals */
@ -86,6 +89,9 @@ shell_global_get_property(GObject *object,
case PROP_WINDOW_GROUP: case PROP_WINDOW_GROUP:
g_value_set_object (value, mutter_plugin_get_window_group (global->plugin)); g_value_set_object (value, mutter_plugin_get_window_group (global->plugin));
break; break;
case PROP_WINDOW_MANAGER:
g_value_set_object (value, global->wm);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -166,6 +172,13 @@ shell_global_class_init (ShellGlobalClass *klass)
"Actor holding window actors", "Actor holding window actors",
CLUTTER_TYPE_ACTOR, CLUTTER_TYPE_ACTOR,
G_PARAM_READABLE)); G_PARAM_READABLE));
g_object_class_install_property (gobject_class,
PROP_WINDOW_MANAGER,
g_param_spec_object ("window-manager",
"Window Manager",
"Window management interface",
SHELL_TYPE_WM,
G_PARAM_READABLE));
} }
/** /**
@ -253,8 +266,10 @@ _shell_global_set_plugin (ShellGlobal *global,
MutterPlugin *plugin) MutterPlugin *plugin)
{ {
g_return_if_fail (SHELL_IS_GLOBAL (global)); g_return_if_fail (SHELL_IS_GLOBAL (global));
g_return_if_fail (global->plugin == NULL);
global->plugin = plugin; global->plugin = plugin;
global->wm = shell_wm_new (plugin);
} }
/** /**
@ -274,3 +289,19 @@ shell_global_focus_stage (ShellGlobal *global)
Window stagewin = clutter_x11_get_stage_window (stage); Window stagewin = clutter_x11_get_stage_window (stage);
XSetInputFocus (xdisplay, stagewin, RevertToParent, CurrentTime); XSetInputFocus (xdisplay, stagewin, RevertToParent, CurrentTime);
} }
ClutterActor *
shell_global_get_overlay_group (ShellGlobal *global)
{
g_return_val_if_fail (SHELL_IS_GLOBAL (global), NULL);
return mutter_plugin_get_overlay_group (global->plugin);
}
ClutterActor *
shell_global_get_window_group (ShellGlobal *global)
{
g_return_val_if_fail (SHELL_IS_GLOBAL (global), NULL);
return mutter_plugin_get_window_group (global->plugin);
}

View File

@ -43,6 +43,8 @@ void shell_global_set_stage_input_area (ShellGlobal *global,
int height); int height);
GList *shell_global_get_windows (ShellGlobal *global); GList *shell_global_get_windows (ShellGlobal *global);
ClutterActor *shell_global_get_window_group (ShellGlobal *global);
ClutterActor *shell_global_get_overlay_group (ShellGlobal *global);
void _shell_global_set_plugin (ShellGlobal *global, void _shell_global_set_plugin (ShellGlobal *global,
MutterPlugin *plugin); MutterPlugin *plugin);

1
src/shell-marshal.list Normal file
View File

@ -0,0 +1 @@
VOID:INT,INT,INT

194
src/shell-wm.c Normal file
View File

@ -0,0 +1,194 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#include "shell-wm.h"
#include "shell-global.h"
#include "shell-marshal.h"
struct _ShellWM {
GObject parent;
GList *switch_workspace_actors;
};
/* Signals */
enum
{
#ifdef NOT_YET
MINIMIZE,
KILL_MINIMIZE,
MAXIMIZE,
KILL_MAXIMIZE,
UNMAXIMIZE,
KILL_UNMAXIMIZE,
MAP,
KILL_MAP,
DESTROY,
KILL_DESTROY,
#endif
SWITCH_WORKSPACE,
KILL_SWITCH_WORKSPACE,
LAST_SIGNAL
};
G_DEFINE_TYPE(ShellWM, shell_wm, G_TYPE_OBJECT);
static void shell_wm_set_switch_workspace_actors (ShellWM *wm,
GList *actors);
static guint shell_wm_signals [LAST_SIGNAL] = { 0 };
static void
shell_wm_init (ShellWM *wm)
{
}
static void
shell_wm_finalize (GObject *object)
{
ShellWM *wm = SHELL_WM (object);
shell_wm_set_switch_workspace_actors (wm, NULL);
G_OBJECT_CLASS (shell_wm_parent_class)->finalize (object);
}
static void
shell_wm_class_init (ShellWMClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = shell_wm_finalize;
shell_wm_signals[SWITCH_WORKSPACE] =
g_signal_new ("switch-workspace",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
_shell_marshal_VOID__INT_INT_INT,
G_TYPE_NONE, 3,
G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
shell_wm_signals[KILL_SWITCH_WORKSPACE] =
g_signal_new ("kill-switch-workspace",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static ShellWM *
shell_wm_get (void)
{
ShellWM *wm;
g_object_get (shell_global_get (),
"window-manager", &wm,
NULL);
/* drop extra ref added by g_object_get */
g_object_unref (wm);
return wm;
}
static void
shell_wm_switch_workspace (const GList **actors,
gint from,
gint to,
MetaMotionDirection direction)
{
ShellWM *wm = shell_wm_get ();
shell_wm_set_switch_workspace_actors (wm, (GList *)*actors);
g_signal_emit (wm, shell_wm_signals[SWITCH_WORKSPACE], 0,
from, to, direction);
shell_wm_set_switch_workspace_actors (wm, NULL);
}
static void
shell_wm_kill_effect (MutterWindow *actor,
gulong events)
{
ShellWM *wm = shell_wm_get ();
#ifdef NOT_YET
if (events & MUTTER_PLUGIN_MINIMIZE)
g_signal_emit (wm, shell_wm_signals[KILL_MINIMIZE], 0);
if (events & MUTTER_PLUGIN_MAXIMIZE)
g_signal_emit (wm, shell_wm_signals[KILL_MAXIMIZE], 0);
if (events & MUTTER_PLUGIN_UNMAXIMIZE)
g_signal_emit (wm, shell_wm_signals[KILL_UNMAXIMIZE], 0);
if (events & MUTTER_PLUGIN_MAP)
g_signal_emit (wm, shell_wm_signals[KILL_MAP], 0);
if (events & MUTTER_PLUGIN_DESTROY)
g_signal_emit (wm, shell_wm_signals[KILL_DESTROY], 0);
#endif
if (events & MUTTER_PLUGIN_SWITCH_WORKSPACE)
g_signal_emit (wm, shell_wm_signals[KILL_SWITCH_WORKSPACE], 0);
}
/**
* shell_wm_new:
* @plugin: the #MutterPlugin
*
* Creates a new window management interface by hooking into @plugin.
*
* Return value: the new window-management interface
**/
ShellWM *
shell_wm_new (MutterPlugin *plugin)
{
#ifdef NOT_YET
plugin->minimize = shell_wm_minimize;
plugin->maximize = shell_wm_maximize;
plugin->unmaximize = shell_wm_unmaximize;
plugin->map = shell_wm_map;
plugin->destroy = shell_wm_destroy;
#endif
plugin->switch_workspace = shell_wm_switch_workspace;
plugin->kill_effect = shell_wm_kill_effect;
return g_object_new (SHELL_TYPE_WM, NULL);
}
/**
* shell_wm_get_switch_workspace_actors:
* @wm: the #ShellWM
*
* A workaround for a missing feature in gobject-introspection. Returns
* the list of windows involved in a switch-workspace operation (which
* cannot be passed directly to the signal handler because there's no
* way to annotate the element-type of a signal parameter.)
*
* You must call this from the #ShellWM::switch-workspace signal
* handler itself; if you need the value again later, you must save a
* copy yourself.
*
* Return value: (element-type MutterWindow) (transfer full): the list
* of windows
**/
GList *
shell_wm_get_switch_workspace_actors (ShellWM *wm)
{
GList *l;
for (l = wm->switch_workspace_actors; l; l = l->next)
g_object_ref (l->data);
return g_list_copy (wm->switch_workspace_actors);
}
static void
shell_wm_set_switch_workspace_actors (ShellWM *wm, GList *actors)
{
const GList *l;
for (l = wm->switch_workspace_actors; l; l = l->next)
g_object_unref (l->data);
g_list_free (wm->switch_workspace_actors);
wm->switch_workspace_actors = g_list_copy (actors);
for (l = wm->switch_workspace_actors; l; l = l->next)
g_object_ref (l->data);
}

33
src/shell-wm.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef __SHELL_WM_H__
#define __SHELL_WM_H__
#include <glib-object.h>
#include <mutter-plugin.h>
G_BEGIN_DECLS
typedef struct _ShellWM ShellWM;
typedef struct _ShellWMClass ShellWMClass;
#define SHELL_TYPE_WM (shell_wm_get_type ())
#define SHELL_WM(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SHELL_TYPE_WM, ShellWM))
#define SHELL_WM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_WM, ShellWMClass))
#define SHELL_IS_WM(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SHELL_TYPE_WM))
#define SHELL_IS_WM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_WM))
#define SHELL_WM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_WM, ShellWMClass))
struct _ShellWMClass
{
GObjectClass parent_class;
};
GType shell_wm_get_type (void) G_GNUC_CONST;
ShellWM *shell_wm_new (MutterPlugin *plugin);
GList *shell_wm_get_switch_workspace_actors (ShellWM *wm);
G_END_DECLS
#endif /* __SHELL_WM_H__ */