changeset 14900:065e7ac30338

[gaim-migrate @ 17672] Rearranging a bunch of stuff. Users shouldn't notice any change, apart from the added ability to bind keys for the window-manager. I will update the manual in a while. I need to know how to revert a commit in case things go terribly wrong. ... I am going to remind everyone that Dido is AWESOME! committer: Tailor Script <tailor@pidgin.im>
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Sun, 05 Nov 2006 17:28:33 +0000
parents a8f92a837590
children d9d28bd79715
files console/libgnt/Makefile.am console/libgnt/gntbindable.c console/libgnt/gntbindable.h console/libgnt/gntcombobox.c console/libgnt/gntentry.c console/libgnt/gntmain.c console/libgnt/gntmarshal.c console/libgnt/gntmarshal.h console/libgnt/gntmenu.c console/libgnt/gntmenuitem.c console/libgnt/gntstyle.c console/libgnt/gntstyle.h console/libgnt/gnttree.c console/libgnt/gntwidget.c console/libgnt/gntwidget.h console/libgnt/gntwm.c console/libgnt/gntwm.h console/libgnt/test/multiwin.c console/libgnt/test/tv.c console/libgnt/wms/s.c
diffstat 20 files changed, 2376 insertions(+), 1756 deletions(-) [+]
line wrap: on
line diff
--- a/console/libgnt/Makefile.am	Sun Nov 05 14:57:05 2006 +0000
+++ b/console/libgnt/Makefile.am	Sun Nov 05 17:28:33 2006 +0000
@@ -6,6 +6,7 @@
 
 libgnt_la_SOURCES = \
 	gntwidget.c \
+	gntbindable.c \
 	gntbox.c \
 	gntbutton.c \
 	gntcheckbox.c \
@@ -24,10 +25,12 @@
 	gnttree.c \
 	gntutils.c \
 	gntwindow.c \
+	gntwm.c \
 	gntmain.c
 
 libgnt_la_headers = \
 	gntwidget.h \
+	gntbindable.h \
 	gntbox.h \
 	gntbutton.h \
 	gntcheckbox.h \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gntbindable.c	Sun Nov 05 17:28:33 2006 +0000
@@ -0,0 +1,212 @@
+#include "gntbindable.h"
+#include "gntstyle.h"
+#include "gnt.h"
+#include "gntutils.h"
+
+static GObjectClass *parent_class = NULL;
+
+static void
+gnt_bindable_class_init(GntBindableClass *klass)
+{
+	parent_class = g_type_class_peek_parent(klass);
+
+	klass->actions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+				(GDestroyNotify)gnt_bindable_action_free);
+	klass->bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+				(GDestroyNotify)gnt_bindable_action_param_free);
+
+	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
+	GNTDEBUG;
+}
+
+static void
+duplicate_hashes(GntBindableClass *klass)
+{
+	/* Duplicate the bindings from parent class */
+	if (klass->actions) {
+		klass->actions = g_hash_table_duplicate(klass->actions, g_str_hash,
+					g_str_equal, g_free, (GDestroyNotify)gnt_bindable_action_free);
+		klass->bindings = g_hash_table_duplicate(klass->bindings, g_str_hash,
+					g_str_equal, g_free, (GDestroyNotify)gnt_bindable_action_param_free);
+	} else {
+		klass->actions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+					(GDestroyNotify)gnt_bindable_action_free);
+		klass->bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+					(GDestroyNotify)gnt_bindable_action_param_free);
+	}
+
+	GNTDEBUG;
+}
+
+/******************************************************************************
+ * GntBindable API
+ *****************************************************************************/
+GType
+gnt_bindable_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0) {
+		static const GTypeInfo info = {
+			sizeof(GntBindableClass),
+			(GBaseInitFunc)duplicate_hashes,	/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_bindable_class_init,
+			NULL,
+			NULL,					/* class_data		*/
+			sizeof(GntBindable),
+			0,						/* n_preallocs		*/
+			NULL,					/* instance_init	*/
+		};
+
+		type = g_type_register_static(G_TYPE_OBJECT,
+									  "GntBindable",
+									  &info, G_TYPE_FLAG_ABSTRACT);
+	}
+
+	return type;
+}
+
+/**
+ * Key Remaps
+ */
+const char *
+gnt_bindable_remap_keys(GntBindable *bindable, const char *text)
+{
+	const char *remap = NULL;
+	GType type = G_OBJECT_TYPE(bindable);
+	GntBindableClass *klass = GNT_BINDABLE_CLASS(GNT_BINDABLE_GET_CLASS(bindable));
+
+	if (klass->remaps == NULL)
+	{
+		klass->remaps = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+		gnt_styles_get_keyremaps(type, klass->remaps);
+	}
+
+	remap = g_hash_table_lookup(klass->remaps, text);
+
+	return (remap ? remap : text);
+}
+
+/**
+ * Actions and Bindings
+ */
+gboolean
+gnt_bindable_perform_action_named(GntBindable *bindable, const char *name, ...)
+{
+	GntBindableClass *klass = GNT_BINDABLE_CLASS(GNT_BINDABLE_GET_CLASS(bindable));
+	GList *list = NULL;
+	va_list args;
+	GntBindableAction *action;
+	void *p;
+
+	va_start(args, name);
+	while ((p = va_arg(args, void *)) != NULL)
+		list = g_list_append(list, p);
+	va_end(args);
+	
+	action = g_hash_table_lookup(klass->actions, name);
+	if (action && action->u.action) {
+		if (list)
+			return action->u.action(bindable, list);
+		else
+			return action->u.action_noparam(bindable);
+	}
+	return FALSE;
+}
+
+gboolean
+gnt_bindable_perform_action_key(GntBindable *bindable, const char *keys)
+{
+	GntBindableClass *klass = GNT_BINDABLE_CLASS(GNT_BINDABLE_GET_CLASS(bindable));
+	GntBindableActionParam *param = g_hash_table_lookup(klass->bindings, keys);
+
+	if (param && param->action) {
+		if (param->list)
+			return param->action->u.action(bindable, param->list);
+		else
+			return param->action->u.action_noparam(bindable);
+	}
+	return FALSE;
+}
+
+static void
+register_binding(GntBindableClass *klass, const char *name, const char *trigger, GList *list)
+{
+	GntBindableActionParam *param;
+	GntBindableAction *action;
+
+	if (name == NULL || *name == '\0') {
+		g_hash_table_remove(klass->bindings, (char*)trigger);
+		return;
+	}
+
+	action = g_hash_table_lookup(klass->actions, name);
+	if (!action) {
+		g_printerr("GntWidget: Invalid action name %s for %s\n",
+				name, g_type_name(G_OBJECT_CLASS_TYPE(klass)));
+		if (list)
+			g_list_free(list);
+		return;
+	}
+
+	param = g_new0(GntBindableActionParam, 1);
+	param->action = action;
+	param->list = list;
+	g_hash_table_replace(klass->bindings, g_strdup(trigger), param);
+}
+
+void gnt_bindable_register_binding(GntBindableClass *klass, const char *name,
+			const char *trigger, ...)
+{
+	GList *list = NULL;
+	va_list args;
+	void *data;
+
+	va_start(args, trigger);
+	while ((data = va_arg(args, void *))) {
+		list = g_list_append(list, data);
+	}
+	va_end(args);
+
+	register_binding(klass, name, trigger, list);
+}
+
+void gnt_bindable_class_register_action(GntBindableClass *klass, const char *name,
+			GntBindableActionCallback callback, const char *trigger, ...)
+{
+	void *data;
+	va_list args;
+	GntBindableAction *action = g_new0(GntBindableAction, 1);
+	GList *list;
+
+	action->name = g_strdup(name);
+	action->u.action = callback;
+
+	g_hash_table_replace(klass->actions, g_strdup(name), action);
+
+	if (trigger) {
+		list = NULL;
+		va_start(args, trigger);
+		while ((data = va_arg(args, void *))) {
+			list = g_list_append(list, data);
+		}
+		va_end(args);
+
+		register_binding(klass, name, trigger, list);
+	}
+}
+
+void gnt_bindable_action_free(GntBindableAction *action)
+{
+	g_free(action->name);
+	g_free(action);
+}
+
+void gnt_bindable_action_param_free(GntBindableActionParam *param)
+{
+	g_list_free(param->list);   /* XXX: There may be a leak here for string parameters */
+	g_free(param);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gntbindable.h	Sun Nov 05 17:28:33 2006 +0000
@@ -0,0 +1,90 @@
+#ifndef GNT_BINDABLE_H
+#define GNT_BINDABLE_H
+
+#include <stdio.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <ncurses.h>
+
+#define GNT_TYPE_BINDABLE				(gnt_bindable_get_gtype())
+#define GNT_BINDABLE(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_BINDABLE, GntBindable))
+#define GNT_BINDABLE_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_BINDABLE, GntBindableClass))
+#define GNT_IS_BINDABLE(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_BINDABLE))
+#define GNT_IS_BINDABLE_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_BINDABLE))
+#define GNT_BINDABLE_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_BINDABLE, GntBindableClass))
+
+#define	GNTDEBUG	fprintf(stderr, "%s\n", __FUNCTION__)
+
+typedef struct _GnBindable			GntBindable;
+typedef struct _GnBindableClass		GntBindableClass;
+
+struct _GnBindable
+{
+	GObject inherit;
+};
+
+struct _GnBindableClass
+{
+	GObjectClass parent;
+
+	GHashTable *remaps;   /* Key remaps */
+	GHashTable *actions;  /* name -> Action */
+	GHashTable *bindings; /* key -> ActionParam */
+
+	void (*gnt_reserved1)(void);
+	void (*gnt_reserved2)(void);
+	void (*gnt_reserved3)(void);
+	void (*gnt_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType gnt_bindable_get_gtype(void);
+
+/******************/
+/*   Key Remaps   */
+/******************/
+const char * gnt_bindable_remap_keys(GntBindable *bindable, const char *text);
+
+/******************/
+/* Bindable Actions */
+/******************/
+typedef gboolean (*GntBindableActionCallback) (GntBindable *bindable, GList *params);
+typedef gboolean (*GntBindableActionCallbackNoParam)(GntBindable *bindable);
+
+typedef struct _GnBindableAction GntBindableAction;
+typedef struct _GnBindableActionParam GntBindableActionParam;
+
+struct _GnBindableAction
+{
+	char *name;        /* The name of the action */
+	union {
+		gboolean (*action)(GntBindable *bindable, GList *params);
+		gboolean (*action_noparam)(GntBindable *bindable);
+	} u;
+};
+
+struct _GnBindableActionParam
+{
+	GntBindableAction *action;
+	GList *list;
+};
+
+
+/*GntBindableAction *gnt_bindable_action_parse(const char *name);*/
+
+void gnt_bindable_action_free(GntBindableAction *action);
+void gnt_bindable_action_param_free(GntBindableActionParam *param);
+
+void gnt_bindable_class_register_action(GntBindableClass *klass, const char *name,
+			GntBindableActionCallback callback, const char *trigger, ...);
+void gnt_bindable_register_binding(GntBindableClass *klass, const char *name,
+			const char *trigger, ...);
+
+gboolean gnt_bindable_perform_action_key(GntBindable *bindable, const char *keys);
+gboolean gnt_bindable_perform_action_named(GntBindable *bindable, const char *name, ...);
+
+G_END_DECLS
+
+#endif /* GNT_BINDABLE_H */
+
--- a/console/libgnt/gntcombobox.c	Sun Nov 05 14:57:05 2006 +0000
+++ b/console/libgnt/gntcombobox.c	Sun Nov 05 17:28:33 2006 +0000
@@ -105,6 +105,7 @@
 	parent->priv.width = widget->priv.width;
 	parent->priv.height = height + 2;
 
+	GNT_WIDGET_UNSET_FLAGS(parent, GNT_WIDGET_INVISIBLE);
 	gnt_widget_draw(parent);
 }
 
--- a/console/libgnt/gntentry.c	Sun Nov 05 14:57:05 2006 +0000
+++ b/console/libgnt/gntentry.c	Sun Nov 05 17:28:33 2006 +0000
@@ -74,8 +74,6 @@
 		if (y + 10 >= getmaxy(stdscr))
 			y -= 11;
 		gnt_widget_set_position(box, x, y);
-		
-		gnt_widget_draw(box);
 	}
 	else
 		gnt_tree_remove_all(GNT_TREE(entry->ddown));
@@ -99,6 +97,7 @@
 		return FALSE;
 	}
 
+	gnt_widget_draw(entry->ddown->parent);
 	return TRUE;
 }
 
@@ -159,9 +158,9 @@
 }
 
 static gboolean
-move_back(GntWidget *widget, GList *null)
+move_back(GntBindable *bind, GList *null)
 {
-	GntEntry *entry = GNT_ENTRY(widget);
+	GntEntry *entry = GNT_ENTRY(bind);
 	if (entry->cursor <= entry->start)
 		return FALSE;
 	entry->cursor = g_utf8_find_prev_char(entry->start, entry->cursor);
@@ -172,9 +171,9 @@
 }
 
 static gboolean
-move_forward(GntWidget *widget, GList *list)
+move_forward(GntBindable *bind, GList *list)
 {
-	GntEntry *entry = GNT_ENTRY(widget);
+	GntEntry *entry = GNT_ENTRY(bind);
 	if (entry->cursor >= entry->end)
 		return FALSE;
 	entry->cursor = g_utf8_find_next_char(entry->cursor, NULL);
@@ -185,10 +184,10 @@
 }
 
 static gboolean
-backspace(GntWidget *widget, GList *null)
+backspace(GntBindable *bind, GList *null)
 {
 	int len;
-	GntEntry *entry = GNT_ENTRY(widget);
+	GntEntry *entry = GNT_ENTRY(bind);
 
 	if (entry->cursor <= entry->start)
 		return TRUE;
@@ -208,10 +207,10 @@
 }
 
 static gboolean
-delkey(GntWidget *widget, GList *null)
+delkey(GntBindable *bind, GList *null)
 {
 	int len;
-	GntEntry *entry = GNT_ENTRY(widget);
+	GntEntry *entry = GNT_ENTRY(bind);
 
 	if (entry->cursor >= entry->end)
 		return FALSE;
@@ -227,18 +226,18 @@
 }
 
 static gboolean
-move_start(GntWidget *widget, GList *null)
+move_start(GntBindable *bind, GList *null)
 {
-	GntEntry *entry = GNT_ENTRY(widget);
+	GntEntry *entry = GNT_ENTRY(bind);
 	entry->scroll = entry->cursor = entry->start;
 	entry_redraw(GNT_WIDGET(entry));
 	return TRUE;
 }
 
 static gboolean
-move_end(GntWidget *widget, GList *null)
+move_end(GntBindable *bind, GList *null)
 {
-	GntEntry *entry = GNT_ENTRY(widget);
+	GntEntry *entry = GNT_ENTRY(bind);
 	entry->cursor = entry->end;
 	/* This should be better than this */
 	while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= GNT_WIDGET(entry)->priv.width)
@@ -248,9 +247,9 @@
 }
 
 static gboolean
-history_prev(GntWidget *widget, GList *null)
+history_prev(GntBindable *bind, GList *null)
 {
-	GntEntry *entry = GNT_ENTRY(widget);
+	GntEntry *entry = GNT_ENTRY(bind);
 	if (entry->histlength && entry->history->prev)
 	{
 		entry->history = entry->history->prev;
@@ -263,9 +262,9 @@
 }
 
 static gboolean
-history_next(GntWidget *widget, GList *null)
+history_next(GntBindable *bind, GList *null)
 {
-	GntEntry *entry = GNT_ENTRY(widget);
+	GntEntry *entry = GNT_ENTRY(bind);
 	if (entry->histlength && entry->history->next)
 	{
 		if (entry->history->prev == NULL)
@@ -286,52 +285,52 @@
 }
 
 static gboolean
-suggest_show(GntWidget *widget, GList *null)
+suggest_show(GntBindable *bind, GList *null)
 {
-	return show_suggest_dropdown(GNT_ENTRY(widget));
+	return show_suggest_dropdown(GNT_ENTRY(bind));
 }
 
 static gboolean
-suggest_next(GntWidget *widget, GList *null)
+suggest_next(GntBindable *bind, GList *null)
 {
-	GntEntry *entry = GNT_ENTRY(widget);
+	GntEntry *entry = GNT_ENTRY(bind);
 	if (entry->ddown) {
-		gnt_widget_perform_action_named(entry->ddown, "move-down", NULL);
+		gnt_bindable_perform_action_named(GNT_BINDABLE(entry->ddown), "move-down", NULL);
 		return TRUE;
 	}
 	return FALSE;
 }
 
 static gboolean
-suggest_prev(GntWidget *widget, GList *null)
+suggest_prev(GntBindable *bind, GList *null)
 {
-	GntEntry *entry = GNT_ENTRY(widget);
+	GntEntry *entry = GNT_ENTRY(bind);
 	if (entry->ddown) {
-		gnt_widget_perform_action_named(entry->ddown, "move-up", NULL);
+		gnt_bindable_perform_action_named(GNT_BINDABLE(entry->ddown), "move-up", NULL);
 		return TRUE;
 	}
 	return FALSE;
 }
 
 static gboolean
-del_to_home(GntWidget *widget, GList *null)
+del_to_home(GntBindable *bind, GList *null)
 {
-	GntEntry *entry = GNT_ENTRY(widget);
+	GntEntry *entry = GNT_ENTRY(bind);
 	memmove(entry->start, entry->cursor, entry->end - entry->cursor);
 	entry->end -= (entry->cursor - entry->start);
 	entry->cursor = entry->scroll = entry->start;
 	memset(entry->end, '\0', entry->buffer - (entry->end - entry->start));
-	entry_redraw(widget);
+	entry_redraw(GNT_WIDGET(bind));
 	return TRUE;
 }
 
 static gboolean
-del_to_end(GntWidget *widget, GList *null)
+del_to_end(GntBindable *bind, GList *null)
 {
-	GntEntry *entry = GNT_ENTRY(widget);
+	GntEntry *entry = GNT_ENTRY(bind);
 	entry->end = entry->cursor;
 	memset(entry->end, '\0', entry->buffer - (entry->end - entry->start));
-	entry_redraw(widget);
+	entry_redraw(GNT_WIDGET(bind));
 	return TRUE;
 }
 
@@ -351,9 +350,9 @@
 }
 
 static gboolean
-move_back_word(GntWidget *widget, GList *null)
+move_back_word(GntBindable *bind, GList *null)
 {
-	GntEntry *entry = GNT_ENTRY(widget);
+	GntEntry *entry = GNT_ENTRY(bind);
 	const char *iter = entry->cursor - 1;
 
 	if (iter < entry->start)
@@ -362,14 +361,15 @@
 	entry->cursor = (char*)iter;
 	if (entry->cursor < entry->scroll)
 		entry->scroll = entry->cursor;
-	entry_redraw(widget);
+	entry_redraw(GNT_WIDGET(bind));
 	return TRUE;
 }
 
 static gboolean
-del_prev_word(GntWidget *widget, GList *null)
+del_prev_word(GntBindable *bind, GList *null)
 {
-	GntEntry *entry = GNT_ENTRY(widget);
+	GntWidget *widget = GNT_WIDGET(bind);
+	GntEntry *entry = GNT_ENTRY(bind);
 	char *iter = entry->cursor - 1;
 	int count;
 
@@ -535,6 +535,7 @@
 static void
 gnt_entry_class_init(GntEntryClass *klass)
 {
+	GntBindableClass *bindable = GNT_BINDABLE_CLASS(klass);
 	parent_class = GNT_WIDGET_CLASS(klass);
 	parent_class->destroy = gnt_entry_destroy;
 	parent_class->draw = gnt_entry_draw;
@@ -543,53 +544,47 @@
 	parent_class->key_pressed = gnt_entry_key_pressed;
 	parent_class->lost_focus = gnt_entry_lost_focus;
 
-	parent_class->actions = g_hash_table_duplicate(parent_class->actions, g_str_hash,
-				g_str_equal, g_free, (GDestroyNotify)gnt_widget_action_free);
-	parent_class->bindings = g_hash_table_duplicate(parent_class->bindings, g_str_hash,
-				g_str_equal, g_free, (GDestroyNotify)gnt_widget_action_param_free);
-
-	gnt_widget_class_register_action(parent_class, "cursor-home", move_start,
+	gnt_bindable_class_register_action(bindable, "cursor-home", move_start,
 				GNT_KEY_CTRL_A, NULL);
-	gnt_widget_register_binding(parent_class, "cursor-home", GNT_KEY_HOME, NULL);
-	gnt_widget_class_register_action(parent_class, "cursor-end", move_end,
+	gnt_bindable_register_binding(bindable, "cursor-home", GNT_KEY_HOME, NULL);
+	gnt_bindable_class_register_action(bindable, "cursor-end", move_end,
 				GNT_KEY_CTRL_E, NULL);
-	gnt_widget_register_binding(parent_class, "cursor-end", GNT_KEY_END, NULL);
-	gnt_widget_class_register_action(parent_class, "delete-prev", backspace,
+	gnt_bindable_register_binding(bindable, "cursor-end", GNT_KEY_END, NULL);
+	gnt_bindable_class_register_action(bindable, "delete-prev", backspace,
 				GNT_KEY_BACKSPACE, NULL);
-	gnt_widget_class_register_action(parent_class, "delete-next", delkey,
+	gnt_bindable_class_register_action(bindable, "delete-next", delkey,
 				GNT_KEY_DEL, NULL);
-	gnt_widget_register_binding(parent_class, "delete-next", GNT_KEY_CTRL_D, NULL);
-	gnt_widget_class_register_action(parent_class, "delete-start", del_to_home,
+	gnt_bindable_register_binding(bindable, "delete-next", GNT_KEY_CTRL_D, NULL);
+	gnt_bindable_class_register_action(bindable, "delete-start", del_to_home,
 				GNT_KEY_CTRL_U, NULL);
-	gnt_widget_class_register_action(parent_class, "delete-end", del_to_end,
+	gnt_bindable_class_register_action(bindable, "delete-end", del_to_end,
 				GNT_KEY_CTRL_K, NULL);
-	gnt_widget_class_register_action(parent_class, "delete-prev-word", del_prev_word,
+	gnt_bindable_class_register_action(bindable, "delete-prev-word", del_prev_word,
 				NULL, NULL);
 #if 0
-	gnt_widget_class_register_action(parent_class, "delete-next-word", del_next_word,
+	gnt_bindable_class_register_action(bindable, "delete-next-word", del_next_word,
 				NULL, 1, NULL);
 #endif
-	gnt_widget_class_register_action(parent_class, "cursor-prev-word", move_back_word,
+	gnt_bindable_class_register_action(bindable, "cursor-prev-word", move_back_word,
 				NULL, NULL);
-	gnt_widget_class_register_action(parent_class, "cursor-prev", move_back,
+	gnt_bindable_class_register_action(bindable, "cursor-prev", move_back,
 				GNT_KEY_LEFT, NULL);
-	gnt_widget_register_binding(parent_class, "cursor-prev", GNT_KEY_CTRL_B, NULL);
-	gnt_widget_class_register_action(parent_class, "cursor-next", move_forward,
+	gnt_bindable_register_binding(bindable, "cursor-prev", GNT_KEY_CTRL_B, NULL);
+	gnt_bindable_class_register_action(bindable, "cursor-next", move_forward,
 				GNT_KEY_RIGHT, NULL);
-	gnt_widget_register_binding(parent_class, "cursor-next", GNT_KEY_CTRL_F, NULL);
-	gnt_widget_class_register_action(parent_class, "suggest-show", suggest_show,
+	gnt_bindable_register_binding(bindable, "cursor-next", GNT_KEY_CTRL_F, NULL);
+	gnt_bindable_class_register_action(bindable, "suggest-show", suggest_show,
 				"\t", NULL);
-	gnt_widget_class_register_action(parent_class, "suggest-next", suggest_next,
+	gnt_bindable_class_register_action(bindable, "suggest-next", suggest_next,
 				GNT_KEY_DOWN, NULL);
-	gnt_widget_class_register_action(parent_class, "suggest-prev", suggest_prev,
+	gnt_bindable_class_register_action(bindable, "suggest-prev", suggest_prev,
 				GNT_KEY_UP, NULL);
-	gnt_widget_class_register_action(parent_class, "history-prev", history_prev,
+	gnt_bindable_class_register_action(bindable, "history-prev", history_prev,
 				"\033" GNT_KEY_CTRL_DOWN, NULL);
-	gnt_widget_class_register_action(parent_class, "history-next", history_next,
+	gnt_bindable_class_register_action(bindable, "history-next", history_next,
 				"\033" GNT_KEY_CTRL_UP, NULL);
 
-	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), parent_class);
-
+	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
 	GNTDEBUG;
 }
 
--- a/console/libgnt/gntmain.c	Sun Nov 05 14:57:05 2006 +0000
+++ b/console/libgnt/gntmain.c	Sun Nov 05 17:28:33 2006 +0000
@@ -38,543 +38,16 @@
  * 	Need to wattrset for colors to use with PDCurses.
  */
 
-/**
- * There can be at most one menu at a time on the screen.
- * If there is a menu being displayed, then all the keystrokes will be sent to
- * the menu until it is closed, either when the user activates a menuitem, or
- * presses Escape to cancel the menu.
- */
-static GntMenu *menu;
-
-static int lock_focus_list;
-static GList *focus_list;
-static GList *ordered;
-
-static int X_MIN;
-static int X_MAX;
-static int Y_MIN;
-static int Y_MAX;
+static GIOChannel *channel = NULL;
 
 static gboolean ascii_only;
 static gboolean mouse_enabled;
 
-/**
- * 'event_stack' will be set to TRUE when a user-event, ie. a mouse-click
- * or a key-press is being processed. This variable will be used to determine
- * whether to give focus to a new window.
- */
-static gboolean event_stack;
-
-static GMainLoop *loop;
-
-static struct
-{
-	GntWidget *window;
-	GntWidget *tree;
-} _list, *window_list, *action_list;
-
-typedef struct
-{
-	GntWidget *me;
-
-	PANEL *panel;
-} GntNode;
-
-typedef enum
-{
-	GNT_KP_MODE_NORMAL,
-	GNT_KP_MODE_RESIZE,
-	GNT_KP_MODE_MOVE,
-	GNT_KP_MODE_MENU,
-	GNT_KP_MODE_WINDOW_LIST
-} GntKeyPressMode;
-
-static GHashTable *nodes;
-
-static void free_node(gpointer data);
-static void draw_taskbar(gboolean reposition);
-static void bring_on_top(GntWidget *widget);
+static void setup_io();
 
 static gboolean refresh_screen();
-static const GList *list_all_windows();
 
-static void show_actions_list();
-
-static GntWM wm = 
-{
-	NULL,   /* new_window */
-	NULL,   /* close_window */
-	NULL,   /* window_resize_confirm */
-	NULL,   /* window_resized */
-	NULL,   /* window_move_confirm */
-	NULL,   /* window_moved */
-	NULL,   /* window_update */
-	NULL,   /* key_pressed */
-	NULL,   /* mouse clicked */
-	bring_on_top, /* give_focus */
-	NULL,   /* uninit */
-	list_all_windows,  /* window_list */
-};
-
-static const GList *list_all_windows()
-{
-	return focus_list;
-}
-
-static GList *
-g_list_bring_to_front(GList *list, gpointer data)
-{
-	list = g_list_remove(list, data);
-	list = g_list_prepend(list, data);
-	return list;
-}
-
-static gboolean
-update_screen(gpointer null)
-{
-	if (menu) {
-		GntMenu *top = menu;
-		while (top) {
-			GntNode *node = g_hash_table_lookup(nodes, top);
-			if (node)
-				top_panel(node->panel);
-			top = top->submenu;
-		}
-	}
-	update_panels();
-	doupdate();
-	return TRUE;
-}
-
-void gnt_screen_take_focus(GntWidget *widget)
-{
-	GntWidget *w = NULL;
-
-	if (lock_focus_list)
-		return;
-	if (g_list_find(focus_list, widget))
-		return;
-
-	if (ordered)
-		w = ordered->data;
-
-	focus_list = g_list_append(focus_list, widget);
-
-	if (event_stack) {
-		ordered = g_list_prepend(ordered, widget);
-		g_object_set_data(G_OBJECT(widget), "give_focus", GINT_TO_POINTER(event_stack));
-	} else
-		ordered = g_list_append(ordered, widget);
-
-	gnt_widget_set_focus(widget, TRUE);
-	if (w)
-		gnt_widget_set_focus(w, FALSE);
-	draw_taskbar(FALSE);
-}
-
-void gnt_screen_remove_widget(GntWidget *widget)
-{
-	int pos = g_list_index(focus_list, widget);
-
-	if (lock_focus_list)
-		return;
-
-	if (pos == -1)
-		return;
-
-	focus_list = g_list_remove(focus_list, widget);
-	ordered = g_list_remove(ordered, widget);
-
-	if (ordered)
-	{
-		wm.give_focus(ordered->data);
-	}
-	draw_taskbar(FALSE);
-}
-
-static void
-bring_on_top(GntWidget *widget)
-{
-	GntNode *node = g_hash_table_lookup(nodes, widget);
-
-	if (!node)
-		return;
-	
-	if (ordered->data != widget) {
-		GntWidget *w = ordered->data;
-		ordered = g_list_bring_to_front(ordered, widget);
-		gnt_widget_set_focus(w, FALSE);
-	}
-
-	gnt_widget_set_focus(widget, TRUE);
-	gnt_widget_draw(widget);
-	top_panel(node->panel);
-
-	if (_list.window)
-	{
-		GntNode *nd = g_hash_table_lookup(nodes, _list.window);
-		top_panel(nd->panel);
-	}
-	update_screen(NULL);
-	draw_taskbar(FALSE);
-}
-
-static void
-update_window_in_list(GntWidget *wid)
-{
-	GntTextFormatFlags flag = 0;
-
-	if (window_list == NULL)
-		return;
-
-	if (wid == ordered->data)
-		flag |= GNT_TEXT_FLAG_DIM;
-	else if (GNT_WIDGET_IS_FLAG_SET(wid, GNT_WIDGET_URGENT))
-		flag |= GNT_TEXT_FLAG_BOLD;
-
-	gnt_tree_set_row_flags(GNT_TREE(window_list->tree), wid, flag);
-}
-
-static void
-draw_taskbar(gboolean reposition)
-{
-	static WINDOW *taskbar = NULL;
-	GList *iter;
-	int n, width = 0;
-	int i;
-
-	if (taskbar == NULL)
-	{
-		taskbar = newwin(1, getmaxx(stdscr), getmaxy(stdscr) - 1, 0);
-	}
-	else if (reposition)
-	{
-		mvwin(taskbar, Y_MAX, 0);
-	}
-
-	wbkgdset(taskbar, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL));
-	werase(taskbar);
-
-	n = g_list_length(focus_list);
-	if (n)
-		width = getmaxx(stdscr) / n;
-
-	for (i = 0, iter = focus_list; iter; iter = iter->next, i++)
-	{
-		GntWidget *w = iter->data;
-		int color;
-		const char *title;
-
-		if (w == ordered->data) {
-			/* This is the current window in focus */
-			color = GNT_COLOR_TITLE;
-			GNT_WIDGET_UNSET_FLAGS(w, GNT_WIDGET_URGENT);
-			if (wm.window_update) {
-				GntNode *node = g_hash_table_lookup(nodes, w);
-				wm.window_update(node ? node->panel : NULL, w);
-			}
-		} else if (GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_URGENT)) {
-			/* This is a window with the URGENT hint set */
-			color = GNT_COLOR_URGENT;
-		} else {
-			color = GNT_COLOR_NORMAL;
-		}
-		wbkgdset(taskbar, '\0' | COLOR_PAIR(color));
-		mvwhline(taskbar, 0, width * i, ' ' | COLOR_PAIR(color), width);
-		title = GNT_BOX(w)->title;
-		mvwprintw(taskbar, 0, width * i, "%s", title ? title : "<gnt>");
-		if (i)
-			mvwaddch(taskbar, 0, width *i - 1, ACS_VLINE | A_STANDOUT | COLOR_PAIR(GNT_COLOR_NORMAL));
-
-		update_window_in_list(w);
-	}
-
-	wrefresh(taskbar);
-}
-
-static void
-switch_window(int direction)
-{
-	GntWidget *w = NULL, *wid = NULL;
-	int pos;
-
-	if (!ordered || !ordered->next)
-		return;
-
-	w = ordered->data;
-	pos = g_list_index(focus_list, w);
-	pos += direction;
-
-	if (pos < 0)
-		wid = g_list_last(focus_list)->data;
-	else if (pos >= g_list_length(focus_list))
-		wid = focus_list->data;
-	else if (pos >= 0)
-		wid = g_list_nth_data(focus_list, pos);
-
-	ordered = g_list_bring_to_front(ordered, wid);
-
-	wm.give_focus(ordered->data);
-
-	if (w != wid)
-	{
-		gnt_widget_set_focus(w, FALSE);
-	}
-}
-
-static void
-switch_window_n(int n)
-{
-	GntWidget *w = NULL;
-	GList *l;
-
-	if (!ordered)
-		return;
-	
-	w = ordered->data;
-
-	if ((l = g_list_nth(focus_list, n)) != NULL)
-	{
-		ordered = g_list_bring_to_front(ordered, l->data);
-		wm.give_focus(ordered->data);
-	}
-
-	if (l && w != l->data)
-	{
-		gnt_widget_set_focus(w, FALSE);
-	}
-}
-
-static void
-window_list_activate(GntTree *tree, gpointer null)
-{
-	GntWidget *widget = gnt_tree_get_selection_data(GNT_TREE(tree));
-	GntWidget *old = NULL;
-
-	if (!ordered || !widget)
-		return;
-
-	old = ordered->data;
-	ordered = g_list_bring_to_front(ordered, widget);
-	wm.give_focus(widget);
-
-	if (old != widget)
-	{
-		gnt_widget_set_focus(old, FALSE);
-	}
-}
-
-static void
-setup__list()
-{
-	GntWidget *tree, *win;
-	win = _list.window = gnt_box_new(FALSE, FALSE);
-	gnt_box_set_toplevel(GNT_BOX(win), TRUE);
-	gnt_box_set_pad(GNT_BOX(win), 0);
-
-	tree = _list.tree = gnt_tree_new();
-	gnt_box_add_widget(GNT_BOX(win), tree);
-}
-
-static void
-show_window_list()
-{
-	GntWidget *tree, *win;
-	GList *iter;
-
-	if (window_list)
-		return;
-	
-	setup__list();
-
-	window_list = &_list;
-
-	win = window_list->window;
-	tree = window_list->tree;
-
-	gnt_box_set_title(GNT_BOX(win), "Window List");
-
-	for (iter = focus_list; iter; iter = iter->next)
-	{
-		GntBox *box = GNT_BOX(iter->data);
-
-		gnt_tree_add_row_last(GNT_TREE(tree), box,
-				gnt_tree_create_row(GNT_TREE(tree), box->title), NULL);
-		update_window_in_list(GNT_WIDGET(box));
-	}
-
-	gnt_tree_set_selected(GNT_TREE(tree), ordered->data);
-	g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(window_list_activate), NULL);
-
-	gnt_tree_set_col_width(GNT_TREE(tree), 0, getmaxx(stdscr) / 3);
-	gnt_widget_set_size(tree, 0, getmaxy(stdscr) / 2);
-	gnt_widget_set_position(win, getmaxx(stdscr) / 3, getmaxy(stdscr) / 4);
-
-	lock_focus_list = 1;
-	gnt_widget_show(win);
-	lock_focus_list = 0;
-}
-
-static void
-shift_window(GntWidget *widget, int dir)
-{
-	GList *all = focus_list;
-	GList *list = g_list_find(all, widget);
-	int length, pos;
-	if (!list)
-		return;
-
-	length = g_list_length(all);
-	pos = g_list_position(all, list);
-
-	pos += dir;
-	if (dir > 0)
-		pos++;
-
-	if (pos < 0)
-		pos = length;
-	else if (pos > length)
-		pos = 0;
-
-	all = g_list_insert(all, widget, pos);
-	all = g_list_delete_link(all, list);
-	focus_list = all;
-	draw_taskbar(FALSE);
-}
-
-static void
-dump_screen()
-{
-	int x, y;
-	chtype old = 0, now = 0;
-	FILE *file = fopen("dump.html", "w");
-
-	fprintf(file, "<pre>");
-	for (y = 0; y < getmaxy(stdscr); y++)
-	{
-		for (x = 0; x < getmaxx(stdscr); x++)
-		{
-			char ch;
-			now = mvwinch(curscr, y, x);
-			ch = now & A_CHARTEXT;
-			now ^= ch;
-
-#define CHECK(attr, start, end) \
-			do \
-			{  \
-				if (now & attr)  \
-				{  \
-					if (!(old & attr))  \
-						fprintf(file, start);  \
-				}  \
-				else if (old & attr)  \
-				{  \
-					fprintf(file, end);  \
-				}  \
-			} while (0) 
-
-			CHECK(A_BOLD, "<b>", "</b>");
-			CHECK(A_UNDERLINE, "<u>", "</u>");
-			CHECK(A_BLINK, "<blink>", "</blink>");
-
-			if ((now & A_COLOR) != (old & A_COLOR) ||
-				(now & A_REVERSE) != (old & A_REVERSE))
-			{
-				int ret;
-				short fgp, bgp, r, g, b;
-				struct
-				{
-					int r, g, b;
-				} fg, bg;
-
-				ret = pair_content(PAIR_NUMBER(now & A_COLOR), &fgp, &bgp);
-				if (fgp == -1)
-					fgp = COLOR_BLACK;
-				if (bgp == -1)
-					bgp = COLOR_WHITE;
-				if (now & A_REVERSE)
-					fgp ^= bgp ^= fgp ^= bgp;  /* *wink* */
-				ret = color_content(fgp, &r, &g, &b);
-				fg.r = r; fg.b = b; fg.g = g;
-				ret = color_content(bgp, &r, &g, &b);
-				bg.r = r; bg.b = b; bg.g = g;
-#define ADJUST(x) (x = x * 255 / 1000)
-				ADJUST(fg.r);
-				ADJUST(fg.g);
-				ADJUST(fg.b);
-				ADJUST(bg.r);
-				ADJUST(bg.b);
-				ADJUST(bg.g);
-				
-				if (x) fprintf(file, "</span>");
-				fprintf(file, "<span style=\"background:#%02x%02x%02x;color:#%02x%02x%02x\">",
-						bg.r, bg.g, bg.b, fg.r, fg.g, fg.b);
-			}
-			if (now & A_ALTCHARSET)
-			{
-				switch (ch)
-				{
-					case 'q':
-						ch = '-'; break;
-					case 't':
-					case 'u':
-					case 'x':
-						ch = '|'; break;
-					case 'v':
-					case 'w':
-					case 'l':
-					case 'm':
-					case 'k':
-					case 'j':
-					case 'n':
-						ch = '+'; break;
-					case '-':
-						ch = '^'; break;
-					case '.':
-						ch = 'v'; break;
-					case 'a':
-						ch = '#'; break;
-					default:
-						ch = ' '; break;
-				}
-			}
-			if (ch == '&')
-				fprintf(file, "&amp;");
-			else if (ch == '<')
-				fprintf(file, "&lt;");
-			else if (ch == '>')
-				fprintf(file, "&gt;");
-			else
-				fprintf(file, "%c", ch);
-			old = now;
-		}
-		fprintf(file, "</span>\n");
-		old = 0;
-	}
-	fprintf(file, "</pre>");
-	fclose(file);
-}
-
-static void
-refresh_node(GntWidget *widget, GntNode *node, gpointer null)
-{
-	int x, y, w, h;
-	int nw, nh;
-
-	gnt_widget_get_position(widget, &x, &y);
-	gnt_widget_get_size(widget, &w, &h);
-
-	if (x + w >= X_MAX)
-		x = MAX(0, X_MAX - w);
-	if (y + h >= Y_MAX)
-		y = MAX(0, Y_MAX - h);
-	gnt_screen_move_widget(widget, x, y);
-
-	nw = MIN(w, X_MAX);
-	nh = MIN(h, Y_MAX);
-	if (nw != w || nh != h)
-		gnt_screen_resize_widget(widget, nw, nh);
-}
+GntWM *wm;
 
 /**
  * Mouse support:
@@ -602,7 +75,7 @@
 	GntWidget *widget = NULL;
 	PANEL *p = NULL;
 
-	if (!ordered || buffer[0] != 27)
+	if (!wm->ordered || buffer[0] != 27)
 		return FALSE;
 	
 	buffer++;
@@ -653,16 +126,13 @@
 	} else
 		return FALSE;
 	
-	if (wm.mouse_clicked && wm.mouse_clicked(event, x, y, widget))
+	if (gnt_wm_process_click(wm, event, x, y, widget))
 		return TRUE;
 	
-	if (event == GNT_LEFT_MOUSE_DOWN && widget && widget != _list.window &&
+	if (event == GNT_LEFT_MOUSE_DOWN && widget && widget != wm->_list.window &&
 			!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_TRANSIENT)) {
-		if (widget != ordered->data) {
-			GntWidget *w = ordered->data;
-			ordered = g_list_bring_to_front(ordered, widget);
-			wm.give_focus(ordered->data);
-			gnt_widget_set_focus(w, FALSE);
+		if (widget != wm->ordered->data) {
+			gnt_wm_raise_window(wm, widget);
 		}
 		if (y == widget->priv.y) {
 			offset = x - widget->priv.x;
@@ -672,17 +142,16 @@
 	} else if (event == GNT_MOUSE_UP) {
 		if (button == MOUSE_NONE && y == getmaxy(stdscr) - 1) {
 			/* Clicked on the taskbar */
-			int n = g_list_length(focus_list);
+			int n = g_list_length(wm->list);
 			if (n) {
 				int width = getmaxx(stdscr) / n;
-				switch_window_n(x / width);
+				gnt_bindable_perform_action_named(GNT_BINDABLE(wm), "switch-window-n", x/width, NULL);
 			}
 		} else if (button == MOUSE_LEFT && remember) {
 			x -= offset;
 			if (x < 0)	x = 0;
 			if (y < 0)	y = 0;
 			gnt_screen_move_widget(remember, x, y);
-			refresh_node(remember, NULL, NULL);
 		}
 		button = MOUSE_NONE;
 		remember = NULL;
@@ -690,87 +159,25 @@
 	}
 
 	gnt_widget_clicked(widget, event, x, y);
-	return TRUE; /* XXX: this should be TRUE */
+	return TRUE;
 }
 
-#ifndef NO_WIDECHAR
-static int
-widestringwidth(wchar_t *wide)
+static gboolean
+io_invoke_error(GIOChannel *source, GIOCondition cond, gpointer data)
 {
-	int len, ret;
-	char *string;
-
-	len = wcstombs(NULL, wide, 0) + 1;
-	string = g_new0(char, len);
-	wcstombs(string, wide, len);
-	ret = gnt_util_onscreen_width(string, NULL);
-	g_free(string);
-	return ret;
-}
-#endif
-
-/* Returns the onscreen width of the character at the position */
-static int
-reverse_char(WINDOW *d, int y, int x, gboolean set)
-{
-#define DECIDE(ch) (set ? ((ch) | A_REVERSE) : ((ch) & ~A_REVERSE))
+	int id = GPOINTER_TO_INT(data);
+	g_source_remove(id);
+	g_io_channel_unref(source);
 
-#ifdef NO_WIDECHAR
-	chtype ch;
-	ch = mvwinch(d, y, x);
-	mvwaddch(d, y, x, DECIDE(ch));
-	return 1;
-#else
-	cchar_t ch;
-	int wc = 1;
-	if (mvwin_wch(d, y, x, &ch) == OK) {
-		wc = widestringwidth(ch.chars);
-		ch.attr = DECIDE(ch.attr);
-		ch.attr &= WA_ATTRIBUTES;   /* XXX: This is a workaround for a bug */
-		mvwadd_wch(d, y, x, &ch);
-	}
-
-	return wc;
-#endif
-}
-
-static void
-window_reverse(GntWidget *win, gboolean set)
-{
-	int i;
-	int w, h;
-	WINDOW *d;
-
-	if (GNT_WIDGET_IS_FLAG_SET(win, GNT_WIDGET_NO_BORDER))
-		return;
-	
-	d = win->window;
-	gnt_widget_get_size(win, &w, &h);
-
-	if (gnt_widget_has_shadow(win)) {
-		--w;
-		--h;
-	}
-
-	/* the top and bottom */
-	for (i = 0; i < w; i += reverse_char(d, 0, i, set));
-	for (i = 0; i < w; i += reverse_char(d, h-1, i, set));
-
-	/* the left and right */
-	for (i = 0; i < h; i += reverse_char(d, i, 0, set));
-	for (i = 0; i < h; i += reverse_char(d, i, w-1, set));
-
-	wrefresh(win->window);
+	channel = NULL;
+	setup_io();
+	return TRUE;
 }
 
 static gboolean
 io_invoke(GIOChannel *source, GIOCondition cond, gpointer null)
 {
 	char keys[256];
-	gboolean ret = FALSE;
-	static GntKeyPressMode mode = GNT_KP_MODE_NORMAL;
-	const char *buffer;
-
 	int rd = read(STDIN_FILENO, keys, sizeof(keys) - 1);
 	if (rd < 0)
 	{
@@ -787,255 +194,48 @@
 		raise(SIGABRT);
 	}
 
-	event_stack = TRUE;
 	keys[rd] = 0;
-
-	if (keys[0] == 27 && keys[1] == 'd' && keys[2] == 0)
-	{
-		/* This dumps the screen contents in an html file */
-		dump_screen();
-	}
-
 	gnt_keys_refine(keys);
 
 	if (mouse_enabled && detect_mouse_action(keys))
 		return TRUE;
 	
-	if (wm.key_pressed) {
-		buffer = wm.key_pressed(keys);
-		if (buffer == NULL) {
-			event_stack = FALSE;
-			return TRUE;
-		}
-	} else
-		buffer = keys;
+	gnt_wm_process_input(wm, keys);
 
-	if (mode == GNT_KP_MODE_NORMAL)
-	{
-		if (menu) {
-			ret = gnt_widget_key_pressed(GNT_WIDGET(menu), buffer);
-		} else if (ordered) {
-			ret = gnt_widget_key_pressed(ordered->data, buffer);
-		}
+	return TRUE;
+}
 
-		if (!ret)
-		{
-			if (buffer[0] == 27)
-			{
-				/* Some special key has been pressed */
-				if (strcmp(buffer, GNT_KEY_POPUP) == 0)
-				{}
-				else if (strcmp(buffer + 1, "c") == 0)
-				{
-					/* Alt + c was pressed. I am going to use it to close a window. */
-					if (ordered)
-					{
-						gnt_widget_destroy(ordered->data);
-					}
-				}
-				else if (strcmp(buffer + 1, "q") == 0)
-				{
-					/* I am going to use Alt + q to quit. */
-					g_main_loop_quit(loop);
-				}
-				else if (strcmp(buffer + 1, "n") == 0)
-				{
-					/* Alt + n to go to the next window */
-					switch_window(1);
-				}
-				else if (strcmp(buffer + 1, "p") == 0)
-				{
-					/* Alt + p to go to the previous window */
-					switch_window(-1);
-				}
-				else if (strcmp(buffer + 1, "m") == 0 && focus_list)
-				{
-					/* Move a window */
-					mode = GNT_KP_MODE_MOVE;
-					window_reverse(ordered->data, TRUE);
-				}
-				else if (strcmp(buffer + 1, "w") == 0 && focus_list)
-				{
-					/* Window list */
-					mode = GNT_KP_MODE_WINDOW_LIST;
-					show_window_list();
-				}
-				else if (strcmp(buffer + 1, "a") == 0)
-				{
-					mode = GNT_KP_MODE_WINDOW_LIST;
-					show_actions_list();
-				}
-				else if (strcmp(buffer + 1, "r") == 0 && focus_list)
-				{
-					/* Resize window */
-					mode = GNT_KP_MODE_RESIZE;
-					window_reverse(ordered->data, TRUE);
-				}
-				else if (strcmp(buffer + 1, ",") == 0 && focus_list)
-				{
-					/* Re-order the list of windows */
-					shift_window(ordered->data, -1);
-				}
-				else if (strcmp(buffer + 1, ".") == 0 && focus_list)
-				{
-					shift_window(ordered->data, 1);
-				}
-				else if (strcmp(buffer + 1, "l") == 0)
-				{
-					refresh_screen();
-				}
-				else if (strlen(buffer) == 2 && isdigit(*(buffer + 1)))
-				{
-					int n = *(buffer + 1) - '0';
-
-					if (n == 0)
-						n = 10;
-
-					switch_window_n(n - 1);
-				}
-			}
-		}
-	}
-	else if (mode == GNT_KP_MODE_MOVE && focus_list)
-	{
-		if (buffer[0] == 27)
-		{
-			gboolean changed = FALSE;
-			int x, y, w, h;
-			GntWidget *widget = GNT_WIDGET(ordered->data);
-
-			gnt_widget_get_position(widget, &x, &y);
-			gnt_widget_get_size(widget, &w, &h);
+static void
+setup_io()
+{
+	int result;
+	channel = g_io_channel_unix_new(STDIN_FILENO);
 
-			if (strcmp(buffer, GNT_KEY_LEFT) == 0)
-			{
-				if (x > X_MIN)
-				{
-					x--;
-					changed = TRUE;
-				}
-			}
-			else if (strcmp(buffer, GNT_KEY_RIGHT) == 0)
-			{
-				if (x + w < X_MAX)
-				{
-					x++;
-					changed = TRUE;
-				}
-			}
-			else if (strcmp(buffer, GNT_KEY_UP) == 0)
-			{
-				if (y > Y_MIN)
-				{
-					y--;
-					changed = TRUE;
-				}						
-			}
-			else if (strcmp(buffer, GNT_KEY_DOWN) == 0)
-			{
-				if (y + h < Y_MAX)
-				{
-					y++;
-					changed = TRUE;
-				}
-			}
-			else if (buffer[1] == 0)
-			{
-				mode = GNT_KP_MODE_NORMAL;
-				window_reverse(widget, FALSE);
-			}
-
-			if (changed)
-			{
-				gnt_screen_move_widget(widget, x, y);
-			}
-		}
-		else if (*buffer == '\r')
-		{
-			mode = GNT_KP_MODE_NORMAL;
-			window_reverse(ordered->data, FALSE);
-		}
-	}
-	else if (mode == GNT_KP_MODE_WINDOW_LIST && _list.window)
-	{
-		gnt_widget_key_pressed(_list.window, buffer);
+	g_io_channel_set_encoding(channel, NULL, NULL);
+	g_io_channel_set_buffered(channel, FALSE);
+#if 0
+	g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL );
+#endif
 
-		if (buffer[0] == '\r' || (buffer[0] == 27 && buffer[1] == 0))
-		{
-			mode = GNT_KP_MODE_NORMAL;
-			lock_focus_list = 1;
-			gnt_widget_destroy(_list.window);
-			_list.window = NULL;
-			_list.tree = NULL;
-			lock_focus_list = 0;
-			window_list = NULL;
-			action_list = NULL;
-		}
-	}
-	else if (mode == GNT_KP_MODE_RESIZE)
-	{
-		if (buffer[0] == '\r' || (buffer[0] == 27 && buffer[1] == 0)) {
-			mode = GNT_KP_MODE_NORMAL;
-			window_reverse(ordered->data, FALSE);
-		} else if (buffer[0] == 27) {
-			GntWidget *widget = ordered->data;
-			gboolean changed = FALSE;
-			int width, height;
-
-			gnt_widget_get_size(widget, &width, &height);
+	result = g_io_add_watch_full(channel,  G_PRIORITY_HIGH,
+					(G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI),
+					io_invoke, NULL, NULL);
+	
+	g_io_add_watch_full(channel,  G_PRIORITY_HIGH,
+					(G_IO_NVAL),
+					io_invoke_error, GINT_TO_POINTER(result), NULL);
+	
+	g_io_channel_unref(channel);  /* Apparently this caused crashes for some people.
+	                                 But irssi does this, so I am going to assume the
+	                                 crashes were caused by some other stuff. */
 
-			if (strcmp(buffer, GNT_KEY_DOWN) == 0)
-			{
-				if (widget->priv.y + height < Y_MAX)
-				{
-					height++;
-					changed = TRUE;
-				}
-			}
-			else if (strcmp(buffer, GNT_KEY_UP) == 0)
-			{
-				height--;
-				changed = TRUE;
-			}
-			else if (strcmp(buffer, GNT_KEY_LEFT) == 0)
-			{
-				width--;
-				changed = TRUE;
-			}
-			else if (strcmp(buffer, GNT_KEY_RIGHT) == 0)
-			{
-				if (widget->priv.x + width < X_MAX)
-				{
-					width++;
-					changed = TRUE;
-				}
-			}
-
-			if (changed)
-			{
-				gnt_screen_resize_widget(widget, width, height);
-				window_reverse(widget, TRUE);
-			}
-		}
-	}
-
-	event_stack = FALSE;
-	return TRUE;
+	g_printerr("gntmain: setting up IO\n");
 }
 
 static gboolean
 refresh_screen()
 {
-	endwin();
-	refresh();
-
-	X_MAX = getmaxx(stdscr);
-	Y_MAX = getmaxy(stdscr) - 1;
-
-	g_hash_table_foreach(nodes, (GHFunc)refresh_node, NULL);
-	update_screen(NULL);
-	draw_taskbar(TRUE);
-
+	gnt_bindable_perform_action_named(GNT_BINDABLE(wm), "refresh-screen", NULL);
 	return FALSE;
 }
 
@@ -1082,43 +282,28 @@
 	const char *name = gnt_style_get(GNT_STYLE_WM);
 	gpointer handle;
 	
-	if (!name || !*name)
-		return;
-	
-	handle = g_module_open(name, G_MODULE_BIND_LAZY);
-	if (handle) {
-		gboolean (*init)(GntWM *);
-		if (g_module_symbol(handle, "gntwm_init", (gpointer)&init)) {
-			init(&wm);
+	if (name && *name) {
+		handle = g_module_open(name, G_MODULE_BIND_LAZY);
+		if (handle) {
+			gboolean (*init)(GntWM **);
+			if (g_module_symbol(handle, "gntwm_init", (gpointer)&init)) {
+				init(&wm);
+			}
 		}
 	}
+	if (wm == NULL)
+		wm = g_object_new(GNT_TYPE_WM, NULL);
 }
 
 void gnt_init()
 {
-	static GIOChannel *channel = NULL;
 	char *filename;
-	int result;
 	const char *locale;
 
 	if (channel)
 		return;
 	
-	channel = g_io_channel_unix_new(STDIN_FILENO);
-
-	g_io_channel_set_encoding(channel, NULL, NULL);
-	g_io_channel_set_buffered(channel, FALSE);
-#if 0
-	g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL );
-#endif
-
-	result = g_io_add_watch_full(channel,  G_PRIORITY_HIGH,
-					(G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI | G_IO_NVAL),
-					io_invoke, NULL, NULL);
-	
-	g_io_channel_unref(channel);  /* Apparently this caused crashes for some people.
-	                                 But irssi does this, so I am going to assume the
-	                                 crashes were caused by some other stuff. */
+	setup_io();
 
 	locale = setlocale(LC_ALL, "");
 
@@ -1139,12 +324,6 @@
 	g_free(filename);
 
 	gnt_init_colors();
-	X_MIN = 0;
-	Y_MIN = 0;
-	X_MAX = getmaxx(stdscr);
-	Y_MAX = getmaxy(stdscr) - 1;
-
-	nodes = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_node);
 
 	wbkgdset(stdscr, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL));
 	refresh();
@@ -1171,112 +350,27 @@
 
 void gnt_main()
 {
-	loop = g_main_loop_new(NULL, FALSE);
-	g_main_loop_run(loop);
+	wm->loop = g_main_loop_new(NULL, FALSE);
+	g_main_loop_run(wm->loop);
 }
 
 /*********************************
  * Stuff for 'window management' *
  *********************************/
 
-static void
-free_node(gpointer data)
-{
-	GntNode *node = data;
-	hide_panel(node->panel);
-	del_panel(node->panel);
-	g_free(node);
-}
-
 void gnt_screen_occupy(GntWidget *widget)
 {
-	GntNode *node;
-
-	while (widget->parent)
-		widget = widget->parent;
-	
-	if (g_hash_table_lookup(nodes, widget))
-		return;		/* XXX: perhaps _update instead? */
-
-	node = g_new0(GntNode, 1);
-	node->me = widget;
-
-	g_hash_table_replace(nodes, widget, node);
-
-	refresh_node(widget, node, NULL);
-
-	if (window_list)
-	{
-		if ((GNT_IS_BOX(widget) && GNT_BOX(widget)->title) && window_list->window != widget
-				&& GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_CAN_TAKE_FOCUS))
-		{
-			gnt_tree_add_row_last(GNT_TREE(window_list->tree), widget,
-					gnt_tree_create_row(GNT_TREE(window_list->tree), GNT_BOX(widget)->title),
-					NULL);
-			update_window_in_list(widget);
-		}
-	}
-
-	update_screen(NULL);
+	gnt_wm_new_window(wm, widget);
 }
 
 void gnt_screen_release(GntWidget *widget)
 {
-	GntNode *node;
-
-	gnt_screen_remove_widget(widget);
-	node = g_hash_table_lookup(nodes, widget);
-
-	if (node == NULL)	/* Yay! Nothing to do. */
-		return;
-
-	if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_DESTROYING) && wm.close_window)
-		wm.close_window(widget);
-
-	g_hash_table_remove(nodes, widget);
-
-	if (window_list)
-	{
-		gnt_tree_remove(GNT_TREE(window_list->tree), widget);
-	}
-
-	update_screen(NULL);
+	gnt_wm_window_close(wm, widget);
 }
 
 void gnt_screen_update(GntWidget *widget)
 {
-	GntNode *node;
-	
-	while (widget->parent)
-		widget = widget->parent;
-	if (!GNT_IS_MENU(widget))
-		gnt_box_sync_children(GNT_BOX(widget));
-	node = g_hash_table_lookup(nodes, widget);
-	if (node && !node->panel)
-	{
-		if (wm.new_window && node->me != _list.window)
-			node->panel = wm.new_window(node->me);
-		else
-			node->panel = new_panel(node->me->window);
-		set_panel_userptr(node->panel, node);
-		if (!GNT_WIDGET_IS_FLAG_SET(node->me, GNT_WIDGET_TRANSIENT)) {
-			if (!g_object_get_data(G_OBJECT(node->me), "give_focus")) {
-				bottom_panel(node->panel);     /* New windows should not grab focus */
-				gnt_widget_set_urgent(node->me);
-			}
-			else {
-				bring_on_top(node->me);
-			}
-		}
-	}
-
-	if (_list.window)
-	{
-		GntNode *nd = g_hash_table_lookup(nodes, _list.window);
-		top_panel(nd->panel);
-	}
-
-	update_screen(NULL);
+	gnt_wm_update_window(wm, widget);
 }
 
 gboolean gnt_widget_has_focus(GntWidget *widget)
@@ -1293,16 +387,13 @@
 	while (widget->parent)
 		widget = widget->parent;
 
-	if (widget == _list.window)
+	if (widget == wm->_list.window)
 		return TRUE;
-
-	if (ordered && ordered->data == widget)
-	{
+	if (wm->ordered && wm->ordered->data == widget) {
 		if (GNT_IS_BOX(widget) &&
 				(GNT_BOX(widget)->active == w || widget == w))
 			return TRUE;
 	}
-
 	return FALSE;
 }
 
@@ -1311,21 +402,19 @@
 	while (widget->parent)
 		widget = widget->parent;
 
-	if (ordered && ordered->data == widget)
+	if (wm->ordered && wm->ordered->data == widget)
 		return;
 
 	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_URGENT);
 
-	if (wm.window_update) {
-		GntNode *node = g_hash_table_lookup(nodes, widget);
-		wm.window_update(node ? node->panel : NULL, widget);
-	}
-
-	draw_taskbar(FALSE);
+	gnt_wm_update_window(wm, widget);
 }
 
 void gnt_quit()
 {
+	g_hash_table_destroy(wm->nodes); /* XXX: */
+	update_panels();
+	doupdate();
 	gnt_uninit_colors();
 	gnt_uninit_styles();
 	endwin();
@@ -1338,145 +427,48 @@
 
 void gnt_screen_resize_widget(GntWidget *widget, int width, int height)
 {
-	if (widget->parent == NULL)
-	{
-		GntNode *node = g_hash_table_lookup(nodes, widget);
-		if (!node)
-			return;
-
-		if (wm.window_resize_confirm && !wm.window_resize_confirm(widget, &width, &height))
-			return;
-
-		hide_panel(node->panel);
-		gnt_widget_set_size(widget, width, height);
-		gnt_widget_draw(widget);
-		if (wm.window_resized)
-			node->panel = wm.window_resized(node->panel, widget);
-		else
-			replace_panel(node->panel, widget->window);
-		show_panel(node->panel);
-		update_screen(NULL);
-	}
+	gnt_wm_resize_window(wm, widget, width, height);
 }
 
 void gnt_screen_move_widget(GntWidget *widget, int x, int y)
 {
-	GntNode *node = g_hash_table_lookup(nodes, widget);
-
-	if (wm.window_move_confirm && !wm.window_move_confirm(widget, &x, &y))
-		return;
-
-	gnt_widget_set_position(widget, x, y);
-	move_panel(node->panel, y, x);
-
-	if (wm.window_moved)
-		wm.window_moved(node->panel, widget);
-
-	update_screen(NULL);
+	gnt_wm_move_window(wm, widget, x, y);
 }
 
 void gnt_screen_rename_widget(GntWidget *widget, const char *text)
 {
 	gnt_box_set_title(GNT_BOX(widget), text);
 	gnt_widget_draw(widget);
-
-	if (wm.window_update) {
-		GntNode *node = g_hash_table_lookup(nodes, widget);
-		wm.window_update(node ? node->panel : NULL, widget);
-	}
-
-	draw_taskbar(FALSE);
+	gnt_wm_update_window(wm, widget);
 }
 
-/**
- * An application can register actions which will show up in a 'start-menu' like popup
- */
-typedef struct _GnAction
-{
-	const char *label;
-	void (*callback)();
-} GntAction;
-
-static GList *actions;
-
 void gnt_register_action(const char *label, void (*callback)())
 {
 	GntAction *action = g_new0(GntAction, 1);
 	action->label = g_strdup(label);
 	action->callback = callback;
 
-	actions = g_list_append(actions, action);
-}
-
-static void
-action_list_activate(GntTree *tree, gpointer null)
-{
-	GntAction *action = gnt_tree_get_selection_data(tree);
-	action->callback();
-}
-
-static int
-compare_action(gconstpointer p1, gconstpointer p2)
-{
-	const GntAction *a1 = p1;
-	const GntAction *a2 = p2;
-
-	return g_utf8_collate(a1->label, a2->label);
-}
-
-static void
-show_actions_list()
-{
-	GntWidget *tree, *win;
-	GList *iter;
-	int h;
-
-	if (action_list)
-		return;
-	
-	setup__list();
-	action_list = &_list;
-	win = action_list->window;
-	tree = action_list->tree;
-
-	gnt_box_set_title(GNT_BOX(win), "Actions");
-	GNT_WIDGET_SET_FLAGS(tree, GNT_WIDGET_NO_BORDER);
-	/* XXX: Do we really want this? */
-	gnt_tree_set_compare_func(GNT_TREE(tree), compare_action);
-
-	for (iter = actions; iter; iter = iter->next) {
-		GntAction *action = iter->data;
-		gnt_tree_add_row_last(GNT_TREE(tree), action,
-				gnt_tree_create_row(GNT_TREE(tree), action->label), NULL);
-	}
-	g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(action_list_activate), NULL);
-	gnt_widget_set_size(tree, 0, g_list_length(actions));
-	gnt_widget_get_size(win, NULL, &h);
-	gnt_widget_set_position(win, 0, getmaxy(stdscr) - 1 - h);
-
-	lock_focus_list = 1;
-	gnt_widget_show(win);
-	lock_focus_list = 0;
+	wm->acts = g_list_append(wm->acts, action);
 }
 
 static void
 reset_menu(GntWidget *widget, gpointer null)
 {
-	menu = NULL;
+	wm->menu = NULL;
 }
 
 gboolean gnt_screen_menu_show(gpointer newmenu)
 {
-	if (menu) {
+	if (wm->menu) {
 		/* For now, if a menu is being displayed, then another menu
 		 * can NOT take over. */
 		return FALSE;
 	}
 
-	menu = newmenu;
-	gnt_widget_draw(GNT_WIDGET(menu));
+	wm->menu = newmenu;
+	gnt_widget_draw(GNT_WIDGET(wm->menu));
 
-	g_signal_connect(G_OBJECT(menu), "hide", G_CALLBACK(reset_menu), NULL);
+	g_signal_connect(G_OBJECT(wm->menu), "hide", G_CALLBACK(reset_menu), NULL);
 
 	return TRUE;
 }
--- a/console/libgnt/gntmarshal.c	Sun Nov 05 14:57:05 2006 +0000
+++ b/console/libgnt/gntmarshal.c	Sun Nov 05 17:28:33 2006 +0000
@@ -1,237 +1,427 @@
-#include "gntmarshal.h"
 
-void gnt_closure_marshal_BOOLEAN__VOID(GClosure *closure,
-										GValue *ret_value,
-										guint n_param_values,
-										const GValue *param_values,
-										gpointer invocation_hint,
-										gpointer marshal_data)
-{
-	typedef gboolean (*func) (gpointer data1, gpointer data2);
-	register func callback;
-	register GCClosure *cc = (GCClosure*)closure;
-	register gpointer data1, data2;
-	gboolean ret;
+#include	<glib-object.h>
+
 
-	g_return_if_fail(ret_value != NULL);
-	g_return_if_fail(n_param_values == 1);
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v)     g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v)      g_value_get_int (v)
+#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
+#define g_marshal_value_peek_long(v)     g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
+#define g_marshal_value_peek_float(v)    g_value_get_float (v)
+#define g_marshal_value_peek_double(v)   g_value_get_double (v)
+#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v)    g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v)   g_value_get_object (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ *          Do not access GValues directly in your code. Instead, use the
+ *          g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
+#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
+#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
+#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
 
-	if (G_CCLOSURE_SWAP_DATA(closure))
-	{
-		data1 = closure->data;
-		data2 = g_value_peek_pointer(param_values + 0);
-	}
-	else
-	{
-		data1 = g_value_peek_pointer(param_values + 0);
-		data2 = closure->data;
-	}
+
+/* BOOLEAN:VOID (/dev/stdin:1) */
+void
+gnt_closure_marshal_BOOLEAN__VOID (GClosure     *closure,
+                                   GValue       *return_value,
+                                   guint         n_param_values,
+                                   const GValue *param_values,
+                                   gpointer      invocation_hint,
+                                   gpointer      marshal_data)
+{
+  typedef gboolean (*GMarshalFunc_BOOLEAN__VOID) (gpointer     data1,
+                                                  gpointer     data2);
+  register GMarshalFunc_BOOLEAN__VOID callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gboolean v_return;
 
-	callback = (func) (marshal_data ? marshal_data : cc->callback);
-	ret = callback(data1, data2);
-	g_value_set_boolean(ret_value, ret);
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 1);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_BOOLEAN__VOID) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       data2);
+
+  g_value_set_boolean (return_value, v_return);
 }
 
-void gnt_closure_marshal_BOOLEAN__STRING(GClosure *closure,
-										GValue *ret_value,
-										guint n_param_values,
-										const GValue *param_values,
-										gpointer invocation_hint,
-										gpointer marshal_data)
+/* BOOLEAN:STRING (/dev/stdin:2) */
+void
+gnt_closure_marshal_BOOLEAN__STRING (GClosure     *closure,
+                                     GValue       *return_value,
+                                     guint         n_param_values,
+                                     const GValue *param_values,
+                                     gpointer      invocation_hint,
+                                     gpointer      marshal_data)
 {
-	typedef gboolean (*func) (gpointer data1, const char *arg1, gpointer data2);
-	register func callback;
-	register GCClosure *cc = (GCClosure*)closure;
-	register gpointer data1, data2;
-	gboolean ret;
+  typedef gboolean (*GMarshalFunc_BOOLEAN__STRING) (gpointer     data1,
+                                                    gpointer     arg_1,
+                                                    gpointer     data2);
+  register GMarshalFunc_BOOLEAN__STRING callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gboolean v_return;
 
-	g_return_if_fail(ret_value != NULL);
-	g_return_if_fail(n_param_values == 2);
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 2);
 
-	if (G_CCLOSURE_SWAP_DATA(closure))
-	{
-		data1 = closure->data;
-		data2 = g_value_peek_pointer(param_values + 0);
-	}
-	else
-	{
-		data1 = g_value_peek_pointer(param_values + 0);
-		data2 = closure->data;
-	}
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_BOOLEAN__STRING) (marshal_data ? marshal_data : cc->callback);
 
-	callback = (func) (marshal_data ? marshal_data : cc->callback);
-	ret = callback(data1, g_value_get_string(param_values + 1) , data2);
-	g_value_set_boolean(ret_value, ret);
+  v_return = callback (data1,
+                       g_marshal_value_peek_string (param_values + 1),
+                       data2);
+
+  g_value_set_boolean (return_value, v_return);
 }
 
-void gnt_closure_marshal_VOID__INT_INT_INT_INT(GClosure *closure,
-										GValue *ret_value,
-										guint n_param_values,
-										const GValue *param_values,
-										gpointer invocation_hint,
-										gpointer marshal_data)
+/* VOID:INT,INT,INT,INT (/dev/stdin:3) */
+void
+gnt_closure_marshal_VOID__INT_INT_INT_INT (GClosure     *closure,
+                                           GValue       *return_value,
+                                           guint         n_param_values,
+                                           const GValue *param_values,
+                                           gpointer      invocation_hint,
+                                           gpointer      marshal_data)
 {
-	typedef void (*func) (gpointer data1, int, int, int, int, gpointer data2);
-	register func callback;
-	register GCClosure *cc = (GCClosure*)closure;
-	register gpointer data1, data2;
+  typedef void (*GMarshalFunc_VOID__INT_INT_INT_INT) (gpointer     data1,
+                                                      gint         arg_1,
+                                                      gint         arg_2,
+                                                      gint         arg_3,
+                                                      gint         arg_4,
+                                                      gpointer     data2);
+  register GMarshalFunc_VOID__INT_INT_INT_INT callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 5);
 
-	g_return_if_fail(n_param_values == 5);
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__INT_INT_INT_INT) (marshal_data ? marshal_data : cc->callback);
 
-	if (G_CCLOSURE_SWAP_DATA(closure))
-	{
-		data1 = closure->data;
-		data2 = g_value_peek_pointer(param_values + 0);
-	}
-	else
-	{
-		data1 = g_value_peek_pointer(param_values + 0);
-		data2 = closure->data;
-	}
+  callback (data1,
+            g_marshal_value_peek_int (param_values + 1),
+            g_marshal_value_peek_int (param_values + 2),
+            g_marshal_value_peek_int (param_values + 3),
+            g_marshal_value_peek_int (param_values + 4),
+            data2);
+}
 
-	callback = (func) (marshal_data ? marshal_data : cc->callback);
-	callback(data1,
-			g_value_get_int(param_values + 1) ,
-			g_value_get_int(param_values + 2) ,
-			g_value_get_int(param_values + 3) ,
-			g_value_get_int(param_values + 4) ,
-			data2);
+/* VOID:INT,INT (/dev/stdin:4) */
+void
+gnt_closure_marshal_VOID__INT_INT (GClosure     *closure,
+                                   GValue       *return_value,
+                                   guint         n_param_values,
+                                   const GValue *param_values,
+                                   gpointer      invocation_hint,
+                                   gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__INT_INT) (gpointer     data1,
+                                              gint         arg_1,
+                                              gint         arg_2,
+                                              gpointer     data2);
+  register GMarshalFunc_VOID__INT_INT callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 3);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__INT_INT) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_int (param_values + 1),
+            g_marshal_value_peek_int (param_values + 2),
+            data2);
 }
 
-void gnt_closure_marshal_VOID__INT_INT(GClosure *closure,
-										GValue *ret_value,
-										guint n_param_values,
-										const GValue *param_values,
-										gpointer invocation_hint,
-										gpointer marshal_data)
+/* VOID:POINTER,POINTER (/dev/stdin:5) */
+void
+gnt_closure_marshal_VOID__POINTER_POINTER (GClosure     *closure,
+                                           GValue       *return_value,
+                                           guint         n_param_values,
+                                           const GValue *param_values,
+                                           gpointer      invocation_hint,
+                                           gpointer      marshal_data)
 {
-	typedef void (*func) (gpointer data1, int, int, gpointer data2);
-	register func callback;
-	register GCClosure *cc = (GCClosure*)closure;
-	register gpointer data1, data2;
-
-	g_return_if_fail(n_param_values == 3);
+  typedef void (*GMarshalFunc_VOID__POINTER_POINTER) (gpointer     data1,
+                                                      gpointer     arg_1,
+                                                      gpointer     arg_2,
+                                                      gpointer     data2);
+  register GMarshalFunc_VOID__POINTER_POINTER callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
 
-	if (G_CCLOSURE_SWAP_DATA(closure))
-	{
-		data1 = closure->data;
-		data2 = g_value_peek_pointer(param_values + 0);
-	}
-	else
-	{
-		data1 = g_value_peek_pointer(param_values + 0);
-		data2 = closure->data;
-	}
+  g_return_if_fail (n_param_values == 3);
 
-	callback = (func) (marshal_data ? marshal_data : cc->callback);
-	callback(data1,
-			g_value_get_int(param_values + 1) ,
-			g_value_get_int(param_values + 2) ,
-			data2);
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__POINTER_POINTER) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_pointer (param_values + 1),
+            g_marshal_value_peek_pointer (param_values + 2),
+            data2);
 }
 
-void gnt_closure_marshal_VOID__POINTER_POINTER(GClosure *closure,
-										GValue *ret_value,
-										guint n_param_values,
-										const GValue *param_values,
-										gpointer invocation_hint,
-										gpointer marshal_data)
+/* BOOLEAN:INT,INT (/dev/stdin:6) */
+void
+gnt_closure_marshal_BOOLEAN__INT_INT (GClosure     *closure,
+                                      GValue       *return_value,
+                                      guint         n_param_values,
+                                      const GValue *param_values,
+                                      gpointer      invocation_hint,
+                                      gpointer      marshal_data)
 {
-	typedef void (*func) (gpointer data1, gpointer, gpointer, gpointer data2);
-	register func callback;
-	register GCClosure *cc = (GCClosure*)closure;
-	register gpointer data1, data2;
-
-	g_return_if_fail(n_param_values == 3);
+  typedef gboolean (*GMarshalFunc_BOOLEAN__INT_INT) (gpointer     data1,
+                                                     gint         arg_1,
+                                                     gint         arg_2,
+                                                     gpointer     data2);
+  register GMarshalFunc_BOOLEAN__INT_INT callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gboolean v_return;
 
-	if (G_CCLOSURE_SWAP_DATA(closure))
-	{
-		data1 = closure->data;
-		data2 = g_value_peek_pointer(param_values + 0);
-	}
-	else
-	{
-		data1 = g_value_peek_pointer(param_values + 0);
-		data2 = closure->data;
-	}
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 3);
 
-	callback = (func) (marshal_data ? marshal_data : cc->callback);
-	callback(data1,
-			g_value_get_pointer(param_values + 1) ,
-			g_value_get_pointer(param_values + 2) ,
-			data2);
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_BOOLEAN__INT_INT) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_int (param_values + 1),
+                       g_marshal_value_peek_int (param_values + 2),
+                       data2);
+
+  g_value_set_boolean (return_value, v_return);
 }
 
-void gnt_closure_marshal_BOOLEAN__INT_INT(GClosure *closure,
-										GValue *ret_value,
-										guint n_param_values,
-										const GValue *param_values,
-										gpointer invocation_hint,
-										gpointer marshal_data)
+/* BOOLEAN:INT,INT,INT (/dev/stdin:7) */
+void
+gnt_closure_marshal_BOOLEAN__INT_INT_INT (GClosure     *closure,
+                                          GValue       *return_value,
+                                          guint         n_param_values,
+                                          const GValue *param_values,
+                                          gpointer      invocation_hint,
+                                          gpointer      marshal_data)
 {
-	typedef gboolean (*func) (gpointer data1, int, int, gpointer data2);
-	register func callback;
-	register GCClosure *cc = (GCClosure*)closure;
-	register gpointer data1, data2;
-	gboolean ret;
-
-	g_return_if_fail(ret_value != NULL);
-	g_return_if_fail(n_param_values == 3);
+  typedef gboolean (*GMarshalFunc_BOOLEAN__INT_INT_INT) (gpointer     data1,
+                                                         gint         arg_1,
+                                                         gint         arg_2,
+                                                         gint         arg_3,
+                                                         gpointer     data2);
+  register GMarshalFunc_BOOLEAN__INT_INT_INT callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gboolean v_return;
 
-	if (G_CCLOSURE_SWAP_DATA(closure))
-	{
-		data1 = closure->data;
-		data2 = g_value_peek_pointer(param_values + 0);
-	}
-	else
-	{
-		data1 = g_value_peek_pointer(param_values + 0);
-		data2 = closure->data;
-	}
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 4);
 
-	callback = (func) (marshal_data ? marshal_data : cc->callback);
-	ret = callback(data1,
-			g_value_get_int(param_values + 1) ,
-			g_value_get_int(param_values + 2) ,
-			data2);
-	g_value_set_boolean(ret_value, ret);
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_BOOLEAN__INT_INT_INT) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_int (param_values + 1),
+                       g_marshal_value_peek_int (param_values + 2),
+                       g_marshal_value_peek_int (param_values + 3),
+                       data2);
+
+  g_value_set_boolean (return_value, v_return);
 }
 
-
-void gnt_closure_marshal_BOOLEAN__INT_INT_INT(GClosure *closure,
-										GValue *ret_value,
-										guint n_param_values,
-										const GValue *param_values,
-										gpointer invocation_hint,
-										gpointer marshal_data)
+/* BOOLEAN:POINTER,POINTER,POINTER (/dev/stdin:8) */
+void
+gnt_closure_marshal_BOOLEAN__POINTER_POINTER_POINTER (GClosure     *closure,
+                                                      GValue       *return_value,
+                                                      guint         n_param_values,
+                                                      const GValue *param_values,
+                                                      gpointer      invocation_hint,
+                                                      gpointer      marshal_data)
 {
-	typedef gboolean (*func) (gpointer data1, int, int, int, gpointer data2);
-	register func callback;
-	register GCClosure *cc = (GCClosure*)closure;
-	register gpointer data1, data2;
-	gboolean ret;
-
-	g_return_if_fail(ret_value != NULL);
-	g_return_if_fail(n_param_values == 4);
+  typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER_POINTER_POINTER) (gpointer     data1,
+                                                                     gpointer     arg_1,
+                                                                     gpointer     arg_2,
+                                                                     gpointer     arg_3,
+                                                                     gpointer     data2);
+  register GMarshalFunc_BOOLEAN__POINTER_POINTER_POINTER callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gboolean v_return;
 
-	if (G_CCLOSURE_SWAP_DATA(closure))
-	{
-		data1 = closure->data;
-		data2 = g_value_peek_pointer(param_values + 0);
-	}
-	else
-	{
-		data1 = g_value_peek_pointer(param_values + 0);
-		data2 = closure->data;
-	}
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 4);
 
-	callback = (func) (marshal_data ? marshal_data : cc->callback);
-	ret = callback(data1,
-			g_value_get_int(param_values + 1) ,
-			g_value_get_int(param_values + 2) ,
-			g_value_get_int(param_values + 3) ,
-			data2);
-	g_value_set_boolean(ret_value, ret);
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_BOOLEAN__POINTER_POINTER_POINTER) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_pointer (param_values + 1),
+                       g_marshal_value_peek_pointer (param_values + 2),
+                       g_marshal_value_peek_pointer (param_values + 3),
+                       data2);
+
+  g_value_set_boolean (return_value, v_return);
 }
 
+/* BOOLEAN:INT,INT,INT,POINTER (/dev/stdin:9) */
+void
+gnt_closure_marshal_BOOLEAN__INT_INT_INT_POINTER (GClosure     *closure,
+                                                  GValue       *return_value,
+                                                  guint         n_param_values,
+                                                  const GValue *param_values,
+                                                  gpointer      invocation_hint,
+                                                  gpointer      marshal_data)
+{
+  typedef gboolean (*GMarshalFunc_BOOLEAN__INT_INT_INT_POINTER) (gpointer     data1,
+                                                                 gint         arg_1,
+                                                                 gint         arg_2,
+                                                                 gint         arg_3,
+                                                                 gpointer     arg_4,
+                                                                 gpointer     data2);
+  register GMarshalFunc_BOOLEAN__INT_INT_INT_POINTER callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gboolean v_return;
 
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 5);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_BOOLEAN__INT_INT_INT_POINTER) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_int (param_values + 1),
+                       g_marshal_value_peek_int (param_values + 2),
+                       g_marshal_value_peek_int (param_values + 3),
+                       g_marshal_value_peek_pointer (param_values + 4),
+                       data2);
+
+  g_value_set_boolean (return_value, v_return);
+}
+
+gboolean gnt_boolean_handled_accumulator(GSignalInvocationHint *ihint,
+				  GValue                *return_accu,
+				  const GValue          *handler_return,
+				  gpointer               dummy)
+{
+	gboolean continue_emission;
+	gboolean signal_handled;
+
+	signal_handled = g_value_get_boolean (handler_return);
+	g_value_set_boolean (return_accu, signal_handled);
+	continue_emission = !signal_handled;
+
+	return continue_emission;
+}
+
--- a/console/libgnt/gntmarshal.h	Sun Nov 05 14:57:05 2006 +0000
+++ b/console/libgnt/gntmarshal.h	Sun Nov 05 17:28:33 2006 +0000
@@ -1,51 +1,91 @@
-#include "gntwidget.h"
+
+#ifndef __gnt_closure_marshal_MARSHAL_H__
+#define __gnt_closure_marshal_MARSHAL_H__
+
+#include	<glib-object.h>
+
+G_BEGIN_DECLS
 
-void gnt_closure_marshal_BOOLEAN__VOID(GClosure *closure,
-										GValue *ret_value,
-										guint n_param_values,
-										const GValue *param_values,
-										gpointer invocation_hint,
-										gpointer marshal_data);
+/* BOOLEAN:VOID (/dev/stdin:1) */
+extern void gnt_closure_marshal_BOOLEAN__VOID (GClosure     *closure,
+                                               GValue       *return_value,
+                                               guint         n_param_values,
+                                               const GValue *param_values,
+                                               gpointer      invocation_hint,
+                                               gpointer      marshal_data);
 
-void gnt_closure_marshal_BOOLEAN__STRING(GClosure *closure,
-										GValue *ret_value,
-										guint n_param_values,
-										const GValue *param_values,
-										gpointer invocation_hint,
-										gpointer marshal_data);
+/* BOOLEAN:STRING (/dev/stdin:2) */
+extern void gnt_closure_marshal_BOOLEAN__STRING (GClosure     *closure,
+                                                 GValue       *return_value,
+                                                 guint         n_param_values,
+                                                 const GValue *param_values,
+                                                 gpointer      invocation_hint,
+                                                 gpointer      marshal_data);
 
-void gnt_closure_marshal_VOID__INT_INT_INT_INT(GClosure *closure,
-										GValue *ret_value,
-										guint n_param_values,
-										const GValue *param_values,
-										gpointer invocation_hint,
-										gpointer marshal_data);
+/* VOID:INT,INT,INT,INT (/dev/stdin:3) */
+extern void gnt_closure_marshal_VOID__INT_INT_INT_INT (GClosure     *closure,
+                                                       GValue       *return_value,
+                                                       guint         n_param_values,
+                                                       const GValue *param_values,
+                                                       gpointer      invocation_hint,
+                                                       gpointer      marshal_data);
+
+/* VOID:INT,INT (/dev/stdin:4) */
+extern void gnt_closure_marshal_VOID__INT_INT (GClosure     *closure,
+                                               GValue       *return_value,
+                                               guint         n_param_values,
+                                               const GValue *param_values,
+                                               gpointer      invocation_hint,
+                                               gpointer      marshal_data);
 
-void gnt_closure_marshal_VOID__INT_INT(GClosure *closure,
-										GValue *ret_value,
-										guint n_param_values,
-										const GValue *param_values,
-										gpointer invocation_hint,
-										gpointer marshal_data);
+/* VOID:POINTER,POINTER (/dev/stdin:5) */
+extern void gnt_closure_marshal_VOID__POINTER_POINTER (GClosure     *closure,
+                                                       GValue       *return_value,
+                                                       guint         n_param_values,
+                                                       const GValue *param_values,
+                                                       gpointer      invocation_hint,
+                                                       gpointer      marshal_data);
 
-void gnt_closure_marshal_VOID__POINTER_POINTER(GClosure *closure,
-										GValue *ret_value,
-										guint n_param_values,
-										const GValue *param_values,
-										gpointer invocation_hint,
-										gpointer marshal_data);
+/* BOOLEAN:INT,INT (/dev/stdin:6) */
+extern void gnt_closure_marshal_BOOLEAN__INT_INT (GClosure     *closure,
+                                                  GValue       *return_value,
+                                                  guint         n_param_values,
+                                                  const GValue *param_values,
+                                                  gpointer      invocation_hint,
+                                                  gpointer      marshal_data);
+
+/* BOOLEAN:INT,INT,INT (/dev/stdin:7) */
+extern void gnt_closure_marshal_BOOLEAN__INT_INT_INT (GClosure     *closure,
+                                                      GValue       *return_value,
+                                                      guint         n_param_values,
+                                                      const GValue *param_values,
+                                                      gpointer      invocation_hint,
+                                                      gpointer      marshal_data);
 
-void gnt_closure_marshal_BOOLEAN__INT_INT(GClosure *closure,
-										GValue *ret_value,
-										guint n_param_values,
-										const GValue *param_values,
-										gpointer invocation_hint,
-										gpointer marshal_data);
+/* BOOLEAN:POINTER,POINTER,POINTER (/dev/stdin:8) */
+extern void gnt_closure_marshal_BOOLEAN__POINTER_POINTER_POINTER (GClosure     *closure,
+                                                                  GValue       *return_value,
+                                                                  guint         n_param_values,
+                                                                  const GValue *param_values,
+                                                                  gpointer      invocation_hint,
+                                                                  gpointer      marshal_data);
 
-void gnt_closure_marshal_BOOLEAN__INT_INT_INT(GClosure *closure,
-										GValue *ret_value,
-										guint n_param_values,
-										const GValue *param_values,
-										gpointer invocation_hint,
-										gpointer marshal_data);
+/* BOOLEAN:INT,INT,INT,POINTER (/dev/stdin:9) */
+extern void gnt_closure_marshal_BOOLEAN__INT_INT_INT_POINTER (GClosure     *closure,
+                                                              GValue       *return_value,
+                                                              guint         n_param_values,
+                                                              const GValue *param_values,
+                                                              gpointer      invocation_hint,
+                                                              gpointer      marshal_data);
+
+G_END_DECLS
 
+#endif /* __gnt_closure_marshal_MARSHAL_H__ */
+
+gboolean gnt_boolean_handled_accumulator(GSignalInvocationHint *ihint,
+				  GValue                *return_accu,
+				  const GValue          *handler_return,
+				  gpointer               dummy);
+
+
+
--- a/console/libgnt/gntmenu.c	Sun Nov 05 14:57:05 2006 +0000
+++ b/console/libgnt/gntmenu.c	Sun Nov 05 17:28:33 2006 +0000
@@ -175,7 +175,7 @@
 gnt_menu_destroy(GntWidget *widget)
 {
 	GntMenu *menu = GNT_MENU(widget);
-	g_list_foreach(menu->list, (GFunc)g_object_run_dispose, NULL);
+	g_list_foreach(menu->list, (GFunc)g_object_unref, NULL);
 	g_list_free(menu->list);
 	org_destroy(widget);
 }
@@ -252,7 +252,7 @@
 {
 	GntWidget *widget = GNT_WIDGET(instance);
 	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_SHADOW | GNT_WIDGET_NO_BORDER |
-			GNT_WIDGET_CAN_TAKE_FOCUS);
+			GNT_WIDGET_CAN_TAKE_FOCUS | GNT_WIDGET_TRANSIENT);
 	GNTDEBUG;
 }
 
--- a/console/libgnt/gntmenuitem.c	Sun Nov 05 14:57:05 2006 +0000
+++ b/console/libgnt/gntmenuitem.c	Sun Nov 05 17:28:33 2006 +0000
@@ -11,14 +11,16 @@
 	item->text = NULL;
 	if (item->submenu)
 		gnt_widget_destroy(GNT_WIDGET(item->submenu));
+	parent_class->dispose(obj);
 }
 
 static void
 gnt_menuitem_class_init(GntMenuItemClass *klass)
 {
-	parent_class = G_OBJECT_CLASS(klass);
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+	parent_class = g_type_class_peek_parent(klass);
 
-	parent_class->dispose = gnt_menuitem_destroy;
+	obj_class->dispose = gnt_menuitem_destroy;
 }
 
 static void
@@ -75,7 +77,7 @@
 void gnt_menuitem_set_submenu(GntMenuItem *item, GntMenu *menu)
 {
 	if (item->submenu)
-		gnt_widget_destroy(item->submenu);
+		gnt_widget_destroy(GNT_WIDGET(item->submenu));
 	item->submenu = menu;
 }
 
--- a/console/libgnt/gntstyle.c	Sun Nov 05 14:57:05 2006 +0000
+++ b/console/libgnt/gntstyle.c	Sun Nov 05 17:28:33 2006 +0000
@@ -161,7 +161,7 @@
 	return ret;
 }
 
-void gnt_style_read_actions(GType type, GntWidgetClass *klass)
+void gnt_style_read_actions(GType type, GntBindableClass *klass)
 {
 #if GLIB_CHECK_VERSION(2,6,0)
 	char *name;
@@ -202,7 +202,7 @@
 				if (keycode == NULL) {
 					g_printerr("GntStyle: Invalid key-binding %s\n", key);
 				} else {
-					gnt_widget_register_binding(klass, action, keycode, NULL);
+					gnt_bindable_register_binding(klass, action, keycode, NULL);
 					g_free(keycode);
 				}
 			}
--- a/console/libgnt/gntstyle.h	Sun Nov 05 14:57:05 2006 +0000
+++ b/console/libgnt/gntstyle.h	Sun Nov 05 17:28:33 2006 +0000
@@ -18,7 +18,7 @@
 /* This should be called only once for the each type */
 void gnt_styles_get_keyremaps(GType type, GHashTable *hash);
 
-void gnt_style_read_actions(GType type, GntWidgetClass *klass);
+void gnt_style_read_actions(GType type, GntBindableClass *klass);
 
 void gnt_init_styles();
 
--- a/console/libgnt/gnttree.c	Sun Nov 05 14:57:05 2006 +0000
+++ b/console/libgnt/gnttree.c	Sun Nov 05 17:28:33 2006 +0000
@@ -483,10 +483,10 @@
 }
 
 static gboolean
-action_down(GntWidget *widget, GList *null)
+action_down(GntBindable *bind, GList *null)
 {
 	int dist;
-	GntTree *tree = GNT_TREE(widget);
+	GntTree *tree = GNT_TREE(bind);
 	GntTreeRow *old = tree->current;
 	GntTreeRow *row = get_next(tree->current);
 	if (row == NULL)
@@ -502,10 +502,10 @@
 }
 
 static gboolean
-action_up(GntWidget *widget, GList *list)
+action_up(GntBindable *bind, GList *list)
 {
 	int dist;
-	GntTree *tree = GNT_TREE(widget);
+	GntTree *tree = GNT_TREE(bind);
 	GntTreeRow *old = tree->current;
 	GntTreeRow *row = get_prev(tree->current);
 	if (!row)
@@ -522,9 +522,9 @@
 }
 
 static gboolean
-action_page_down(GntWidget *widget, GList *null)
+action_page_down(GntBindable *bind, GList *null)
 {
-	GntTree *tree = GNT_TREE(widget);
+	GntTree *tree = GNT_TREE(bind);
 	GntTreeRow *old = tree->current;
 	GntTreeRow *row = get_next(tree->bottom);
 	if (row)
@@ -546,9 +546,10 @@
 }
 
 static gboolean
-action_page_up(GntWidget *widget, GList *null)
+action_page_up(GntBindable *bind, GList *null)
 {
-	GntTree *tree = GNT_TREE(widget);
+	GntWidget *widget = GNT_WIDGET(bind);
+	GntTree *tree = GNT_TREE(bind);
 	GntTreeRow *row;
 	GntTreeRow *old = tree->current;
 
@@ -631,9 +632,9 @@
 	GntTree *tree = GNT_TREE(widget);
 	GntTreeRow *old = tree->current;
 	if (event == GNT_MOUSE_SCROLL_UP) {
-		action_up(widget, NULL);
+		action_up(GNT_BINDABLE(widget), NULL);
 	} else if (event == GNT_MOUSE_SCROLL_DOWN) {
-		action_down(widget, NULL);
+		action_down(GNT_BINDABLE(widget), NULL);
 	} else if (event == GNT_LEFT_MOUSE_DOWN) {
 		GntTreeRow *row;
 		GntTree *tree = GNT_TREE(widget);
@@ -670,6 +671,7 @@
 static void
 gnt_tree_class_init(GntTreeClass *klass)
 {
+	GntBindableClass *bindable = GNT_BINDABLE_CLASS(klass);
 	parent_class = GNT_WIDGET_CLASS(klass);
 	parent_class->destroy = gnt_tree_destroy;
 	parent_class->draw = gnt_tree_draw;
@@ -703,24 +705,18 @@
 					 g_cclosure_marshal_VOID__POINTER,
 					 G_TYPE_NONE, 1, G_TYPE_POINTER);
 
-	parent_class->actions = g_hash_table_duplicate(parent_class->actions, g_str_hash,
-				g_str_equal, g_free, (GDestroyNotify)gnt_widget_action_free);
-	parent_class->bindings = g_hash_table_duplicate(parent_class->bindings, g_str_hash,
-				g_str_equal, g_free, (GDestroyNotify)gnt_widget_action_param_free);
-
-	gnt_widget_class_register_action(parent_class, "move-up", action_up,
+	gnt_bindable_class_register_action(bindable, "move-up", action_up,
 				GNT_KEY_UP, NULL);
-	gnt_widget_register_binding(parent_class, "move-up", GNT_KEY_CTRL_P, NULL);
-	gnt_widget_class_register_action(parent_class, "move-down", action_down,
+	gnt_bindable_register_binding(bindable, "move-up", GNT_KEY_CTRL_P, NULL);
+	gnt_bindable_class_register_action(bindable, "move-down", action_down,
 				GNT_KEY_DOWN, NULL);
-	gnt_widget_register_binding(parent_class, "move-down", GNT_KEY_CTRL_N, NULL);
-	gnt_widget_class_register_action(parent_class, "page-up", action_page_up,
+	gnt_bindable_register_binding(bindable, "move-down", GNT_KEY_CTRL_N, NULL);
+	gnt_bindable_class_register_action(bindable, "page-up", action_page_up,
 				GNT_KEY_PGUP, NULL);
-	gnt_widget_class_register_action(parent_class, "page-down", action_page_down,
+	gnt_bindable_class_register_action(bindable, "page-down", action_page_down,
 				GNT_KEY_PGDOWN, NULL);
 
-	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), parent_class);
-
+	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), bindable);
 	GNTDEBUG;
 }
 
--- a/console/libgnt/gntwidget.c	Sun Nov 05 14:57:05 2006 +0000
+++ b/console/libgnt/gntwidget.c	Sun Nov 05 17:28:33 2006 +0000
@@ -84,29 +84,13 @@
 }
 
 static gboolean
-context_menu(GntWidget *widget, GList *null)
+context_menu(GntBindable *bind, GList *null)
 {
 	gboolean ret = FALSE;
-	g_signal_emit(widget, signals[SIG_CONTEXT_MENU], 0, &ret);
+	g_signal_emit(bind, signals[SIG_CONTEXT_MENU], 0, &ret);
 	return ret;
 }
 
-static gboolean
-gnt_boolean_handled_accumulator(GSignalInvocationHint *ihint,
-				  GValue                *return_accu,
-				  const GValue          *handler_return,
-				  gpointer               dummy)
-{
-	gboolean continue_emission;
-	gboolean signal_handled;
-
-	signal_handled = g_value_get_boolean (handler_return);
-	g_value_set_boolean (return_accu, signal_handled);
-	continue_emission = !signal_handled;
-
-	return continue_emission;
-}
-
 static void
 gnt_widget_class_init(GntWidgetClass *klass)
 {
@@ -252,17 +236,11 @@
 					 gnt_closure_marshal_BOOLEAN__VOID,
 					 G_TYPE_BOOLEAN, 0);
 
-	klass->actions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
-				(GDestroyNotify)gnt_widget_action_free);
-	klass->bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
-				(GDestroyNotify)gnt_widget_action_param_free);
-
 	/* This is relevant for all widgets */
-	gnt_widget_class_register_action(klass, "context-menu", context_menu,
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "context-menu", context_menu,
 				GNT_KEY_POPUP, NULL);
 
-	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), klass);
-
+	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
 	GNTDEBUG;
 }
 
@@ -287,7 +265,7 @@
 			gnt_widget_init,					/* instance_init	*/
 		};
 
-		type = g_type_register_static(G_TYPE_OBJECT,
+		type = g_type_register_static(GNT_TYPE_BINDABLE,
 									  "GntWidget",
 									  &info, G_TYPE_FLAG_ABSTRACT);
 	}
@@ -295,30 +273,6 @@
 	return type;
 }
 
-static const char *
-gnt_widget_remap_keys(GntWidget *widget, const char *text)
-{
-	const char *remap = NULL;
-	GType type = G_OBJECT_TYPE(widget);
-	GntWidgetClass *klass = GNT_WIDGET_CLASS(G_OBJECT_GET_CLASS(widget));
-
-	if (klass->remaps == NULL)
-	{
-		klass->remaps = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-		gnt_styles_get_keyremaps(type, klass->remaps);
-	}
-
-	remap = g_hash_table_lookup(klass->remaps, text);
-
-	return (remap ? remap : text);
-}
-
-static void
-gnt_widget_take_focus(GntWidget *widget)
-{
-	gnt_screen_take_focus(widget);
-}
-
 void gnt_widget_set_take_focus(GntWidget *widget, gboolean can)
 {
 	if (can)
@@ -350,10 +304,9 @@
 gnt_widget_show(GntWidget *widget)
 {
 	/* Draw the widget and take focus */
-	if (GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_CAN_TAKE_FOCUS)
-	{
-		gnt_widget_take_focus(widget);
-	}
+	/*if (GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_CAN_TAKE_FOCUS) {*/
+		/*gnt_widget_take_focus(widget);*/
+	/*}*/
 	gnt_widget_draw(widget);
 }
 
@@ -365,10 +318,8 @@
 		return;
 
 	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_DRAWING);
-	if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_MAPPED))
-	{
+	if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_MAPPED)) {
 		gnt_widget_map(widget);
-		gnt_screen_occupy(widget);
 	}
 
 	if (widget->window == NULL)
@@ -405,6 +356,7 @@
 							widget->priv.y, widget->priv.x);
 		}
 		init_widget(widget);
+		gnt_screen_occupy(widget);
 	}
 
 	g_signal_emit(widget, signals[SIG_DRAW], 0);
@@ -413,55 +365,16 @@
 }
 
 gboolean
-gnt_widget_perform_action_named(GntWidget *widget, const char *name, ...)
-{
-	GntWidgetClass *klass = GNT_WIDGET_CLASS(G_OBJECT_GET_CLASS(widget));
-	GList *list = NULL;
-	va_list args;
-	GntWidgetAction *action;
-	void *p;
-
-	va_start(args, name);
-	while ((p = va_arg(args, void *)) != NULL)
-		list = g_list_append(list, p);
-	va_end(args);
-	
-	action = g_hash_table_lookup(klass->actions, name);
-	if (action && action->u.action) {
-		if (list)
-			return action->u.action(widget, list);
-		else
-			return action->u.action_noparam(widget);
-	}
-	return FALSE;
-}
-
-static gboolean
-gnt_widget_perform_action(GntWidget *widget, const char *keys)
-{
-	GntWidgetClass *klass = GNT_WIDGET_CLASS(G_OBJECT_GET_CLASS(widget));
-	GntWidgetActionParam *param = g_hash_table_lookup(klass->bindings, keys);
-
-	if (param && param->action) {
-		if (param->list)
-			return param->action->u.action(widget, param->list);
-		else
-			return param->action->u.action_noparam(widget);
-	}
-	return FALSE;
-}
-
-gboolean
 gnt_widget_key_pressed(GntWidget *widget, const char *keys)
 {
 	gboolean ret;
 	if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_CAN_TAKE_FOCUS))
 		return FALSE;
 
-	if (gnt_widget_perform_action(widget, keys))
+	if (gnt_bindable_perform_action_key(GNT_BINDABLE(widget), keys))
 		return TRUE;
 
-	keys = gnt_widget_remap_keys(widget, keys);
+	keys = gnt_bindable_remap_keys(GNT_BINDABLE(widget), keys);
 	g_signal_emit(widget, signals[SIG_KEY_PRESSED], 0, keys, &ret);
 	return ret;
 }
@@ -707,83 +620,3 @@
 			gnt_style_get_bool(GNT_STYLE_SHADOW, FALSE));
 }
 
-static void
-register_binding(GntWidgetClass *klass, const char *name, const char *trigger, GList *list)
-{
-	GntWidgetActionParam *param;
-	GntWidgetAction *action;
-
-	if (name == NULL || *name == '\0') {
-		g_hash_table_remove(klass->bindings, (char*)trigger);
-		return;
-	}
-
-	action = g_hash_table_lookup(klass->actions, name);
-	if (!action) {
-		g_printerr("GntWidget: Invalid action name %s for %s\n",
-				name, g_type_name(G_OBJECT_CLASS_TYPE(klass)));
-		if (list)
-			g_list_free(list);
-		return;
-	}
-
-	param = g_new0(GntWidgetActionParam, 1);
-	param->action = action;
-	param->list = list;
-	g_hash_table_replace(klass->bindings, g_strdup(trigger), param);
-}
-
-void gnt_widget_register_binding(GntWidgetClass *klass, const char *name,
-			const char *trigger, ...)
-{
-	GList *list = NULL;
-	va_list args;
-	void *data;
-
-	va_start(args, trigger);
-	while ((data = va_arg(args, void *))) {
-		list = g_list_append(list, data);
-	}
-	va_end(args);
-
-	register_binding(klass, name, trigger, list);
-}
-
-void gnt_widget_class_register_action(GntWidgetClass *klass, const char *name,
-			GntWidgetActionCallback callback,
-			const char *trigger, ...)
-{
-	void *data;
-	va_list args;
-	GntWidgetAction *action = g_new0(GntWidgetAction, 1);
-	GList *list;
-
-	action->name = g_strdup(name);
-	action->u.action = callback;
-
-	g_hash_table_replace(klass->actions, g_strdup(name), action);
-
-	if (trigger) {
-		list = NULL;
-		va_start(args, trigger);
-		while ((data = va_arg(args, void *))) {
-			list = g_list_append(list, data);
-		}
-		va_end(args);
-
-		register_binding(klass, name, trigger, list);
-	}
-}
-
-void gnt_widget_action_free(GntWidgetAction *action)
-{
-	g_free(action->name);
-	g_free(action);
-}
-
-void gnt_widget_action_param_free(GntWidgetActionParam *param)
-{
-	g_list_free(param->list);   /* XXX: There may be a leak here for string parameters */
-	g_free(param);
-}
-
--- a/console/libgnt/gntwidget.h	Sun Nov 05 14:57:05 2006 +0000
+++ b/console/libgnt/gntwidget.h	Sun Nov 05 17:28:33 2006 +0000
@@ -3,14 +3,15 @@
 
 #include <stdio.h>
 #include <glib.h>
-#include <glib-object.h>
 #include <ncurses.h>
 
+#include "gntbindable.h"
+
 #define GNT_TYPE_WIDGET				(gnt_widget_get_gtype())
 #define GNT_WIDGET(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_WIDGET, GntWidget))
 #define GNT_WIDGET_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_WIDGET, GntWidgetClass))
 #define GNT_IS_WIDGET(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_WIDGET))
-#define GNT_IS_OBJECT_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_WIDGET))
+#define GNT_IS_WIDGET_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_WIDGET))
 #define GNT_WIDGET_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_WIDGET, GntWidgetClass))
 
 #define GNT_WIDGET_FLAGS(obj)				(GNT_WIDGET(obj)->priv.flags)
@@ -18,8 +19,6 @@
 #define GNT_WIDGET_UNSET_FLAGS(obj, flags)	(GNT_WIDGET_FLAGS(obj) &= ~(flags))
 #define GNT_WIDGET_IS_FLAG_SET(obj, flags)	(GNT_WIDGET_FLAGS(obj) & (flags))
 
-#define	GNTDEBUG	fprintf(stderr, "%s\n", __FUNCTION__)
-
 typedef struct _GnWidget			GntWidget;
 typedef struct _GnWidgetPriv		GntWidgetPriv;
 typedef struct _GnWidgetClass		GntWidgetClass;
@@ -42,6 +41,7 @@
 	GNT_WIDGET_TRANSIENT      = 1 << 11,
 } GntWidgetFlags;
 
+/* XXX: This will probably move elsewhere */
 typedef enum _GnMouseEvent
 {
 	GNT_LEFT_MOUSE_DOWN = 1,
@@ -70,7 +70,7 @@
 
 struct _GnWidget
 {
-	GObject inherit;
+	GntBindable inherit;
 
 	GntWidget *parent;
 
@@ -85,11 +85,7 @@
 
 struct _GnWidgetClass
 {
-	GObjectClass parent;
-
-	GHashTable *remaps;   /* Key remaps */
-	GHashTable *actions;  /* name -> Action */
-	GHashTable *bindings; /* key -> ActionParam */
+	GntBindableClass parent;
 
 	void (*map)(GntWidget *obj);
 	void (*show)(GntWidget *obj);		/* This will call draw() and take focus (if it can take focus) */
@@ -151,44 +147,6 @@
 
 gboolean gnt_widget_has_shadow(GntWidget *widget);
 
-/******************/
-/* Widget Actions */
-/******************/
-typedef gboolean (*GntWidgetActionCallback) (GntWidget *widget, GList *params);
-typedef gboolean (*GntWidgetActionCallbackNoParam)(GntWidget *widget);
-
-typedef struct _GnWidgetAction GntWidgetAction;
-typedef struct _GnWidgetActionParam GntWidgetActionParam;
-
-struct _GnWidgetAction
-{
-	char *name;        /* The name of the action */
-	union {
-		gboolean (*action)(GntWidget *widget, GList *params);
-		gboolean (*action_noparam)(GntWidget *widget);
-	} u;
-};
-
-struct _GnWidgetActionParam
-{
-	GntWidgetAction *action;
-	GList *list;
-};
-
-
-GntWidgetAction *gnt_widget_action_parse(const char *name);
-
-void gnt_widget_action_free(GntWidgetAction *action);
-void gnt_widget_action_param_free(GntWidgetActionParam *param);
-
-void gnt_widget_register_binding(GntWidgetClass *klass, const char *name,
-			const char *trigger, ...);
-
-void gnt_widget_class_register_action(GntWidgetClass *klass, const char *name,
-			GntWidgetActionCallback callback, const char *trigger, ...);
-
-gboolean gnt_widget_perform_action_named(GntWidget *widget, const char *name, ...);
-
 G_END_DECLS
 
 #endif /* GNT_WIDGET_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gntwm.c	Sun Nov 05 17:28:33 2006 +0000
@@ -0,0 +1,1170 @@
+#define _GNU_SOURCE
+#if defined(__APPLE__)
+#define _XOPEN_SOURCE_EXTENDED
+#endif
+
+#include "gntwm.h"
+#include "gntstyle.h"
+#include "gntmarshal.h"
+#include "gnt.h"
+#include "gntbox.h"
+#include "gntmenu.h"
+#include "gnttextview.h"
+#include "gnttree.h"
+#include "gntutils.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+enum
+{
+	SIG_NEW_WIN,
+	SIG_DECORATE_WIN,
+	SIG_CLOSE_WIN,
+	SIG_CONFIRM_RESIZE,
+	SIG_RESIZED,
+	SIG_CONFIRM_MOVE,
+	SIG_MOVED,
+	SIG_UPDATE_WIN,
+	SIG_GIVE_FOCUS,
+	SIG_KEY_PRESS,
+	SIG_MOUSE_CLICK,
+	SIGS
+};
+
+static guint signals[SIGS] = { 0 };
+static void gnt_wm_new_window_real(GntWM *wm, GntWidget *widget);
+static void gnt_wm_win_resized(GntWM *wm, GntNode *node);
+static void gnt_wm_win_moved(GntWM *wm, GntNode *node);
+static void gnt_wm_give_focus(GntWM *wm, GntWidget *widget);
+static void update_window_in_list(GntWM *wm, GntWidget *wid);
+
+static GList *
+g_list_bring_to_front(GList *list, gpointer data)
+{
+	list = g_list_remove(list, data);
+	list = g_list_prepend(list, data);
+	return list;
+}
+
+static void
+free_node(gpointer data)
+{
+	GntNode *node = data;
+	hide_panel(node->panel);
+	del_panel(node->panel);
+	g_free(node);
+}
+
+static void
+draw_taskbar(GntWM *wm, gboolean reposition)
+{
+	static WINDOW *taskbar = NULL;
+	GList *iter;
+	int n, width = 0;
+	int i;
+
+	if (taskbar == NULL) {
+		taskbar = newwin(1, getmaxx(stdscr), getmaxy(stdscr) - 1, 0);
+	} else if (reposition) {
+		int Y_MAX = getmaxy(stdscr) - 1;
+		mvwin(taskbar, Y_MAX, 0);
+	}
+
+	wbkgdset(taskbar, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL));
+	werase(taskbar);
+
+	n = g_list_length(wm->list);
+	if (n)
+		width = getmaxx(stdscr) / n;
+
+	for (i = 0, iter = wm->list; iter; iter = iter->next, i++)
+	{
+		GntWidget *w = iter->data;
+		int color;
+		const char *title;
+
+		if (w == wm->ordered->data) {
+			/* This is the current window in focus */
+			color = GNT_COLOR_TITLE;
+		} else if (GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_URGENT)) {
+			/* This is a window with the URGENT hint set */
+			color = GNT_COLOR_URGENT;
+		} else {
+			color = GNT_COLOR_NORMAL;
+		}
+		wbkgdset(taskbar, '\0' | COLOR_PAIR(color));
+		mvwhline(taskbar, 0, width * i, ' ' | COLOR_PAIR(color), width);
+		title = GNT_BOX(w)->title;
+		mvwprintw(taskbar, 0, width * i, "%s", title ? title : "<gnt>");
+		if (i)
+			mvwaddch(taskbar, 0, width *i - 1, ACS_VLINE | A_STANDOUT | COLOR_PAIR(GNT_COLOR_NORMAL));
+
+		update_window_in_list(wm, w);
+	}
+
+	wrefresh(taskbar);
+}
+static gboolean
+update_screen(GntWM *wm)
+{
+	if (wm->menu) {
+		GntMenu *top = wm->menu;
+		while (top) {
+			GntNode *node = g_hash_table_lookup(wm->nodes, top);
+			if (node)
+				top_panel(node->panel);
+			top = top->submenu;
+		}
+	}
+	update_panels();
+	doupdate();
+	return TRUE;
+}
+static void
+refresh_node(GntWidget *widget, GntNode *node, gpointer null)
+{
+	int x, y, w, h;
+	int nw, nh, nx, ny;
+
+	int X_MAX = getmaxx(stdscr);
+	int Y_MAX = getmaxy(stdscr) - 1;
+
+	gnt_widget_get_position(widget, &x, &y);
+	gnt_widget_get_size(widget, &w, &h);
+	nx = x; ny = y;
+
+	if (x + w >= X_MAX)
+		nx = MAX(0, X_MAX - w);
+	if (y + h >= Y_MAX)
+		ny = MAX(0, Y_MAX - h);
+	if (x != nx || y != ny)
+		gnt_screen_move_widget(widget, nx, ny);
+
+	nw = MIN(w, X_MAX);
+	nh = MIN(h, Y_MAX);
+	if (nw != w || nh != h)
+		gnt_screen_resize_widget(widget, nw, nh);
+}
+static void
+gnt_wm_init(GTypeInstance *instance, gpointer class)
+{
+	GntWM *wm = GNT_WM(instance);
+	wm->list = NULL;
+	wm->ordered = NULL;
+	wm->event_stack = FALSE;
+	wm->windows = NULL;
+	wm->actions = NULL;
+	wm->nodes = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_node);
+}
+
+static void
+switch_window(GntWM *wm, int direction)
+{
+	GntWidget *w = NULL, *wid = NULL;
+	int pos;
+
+	if (wm->_list.window || wm->menu)
+		return;
+
+	if (!wm->ordered || !wm->ordered->next)
+		return;
+
+	w = wm->ordered->data;
+	pos = g_list_index(wm->list, w);
+	pos += direction;
+
+	if (pos < 0)
+		wid = g_list_last(wm->list)->data;
+	else if (pos >= g_list_length(wm->list))
+		wid = wm->list->data;
+	else if (pos >= 0)
+		wid = g_list_nth_data(wm->list, pos);
+
+	wm->ordered = g_list_bring_to_front(wm->ordered, wid);
+
+	gnt_wm_raise_window(wm, wm->ordered->data);
+
+	if (w != wid) {
+		gnt_widget_set_focus(w, FALSE);
+	}
+}
+
+static gboolean
+window_next(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+	switch_window(wm, 1);
+	return TRUE;
+}
+
+static gboolean
+window_prev(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+	switch_window(wm, -1);
+	return TRUE;
+}
+
+static gboolean
+switch_window_n(GntBindable *bind, GList *list)
+{
+	GntWM *wm = GNT_WM(bind);
+	GntWidget *w = NULL;
+	GList *l;
+	int n;
+
+	if (!wm->ordered || !list)
+		return TRUE;
+
+	n = GPOINTER_TO_INT(list->data);
+	
+	w = wm->ordered->data;
+
+	if ((l = g_list_nth(wm->list, n)) != NULL)
+	{
+		gnt_wm_raise_window(wm, l->data);
+	}
+
+	if (l && w != l->data)
+	{
+		gnt_widget_set_focus(w, FALSE);
+	}
+	return TRUE;
+}
+static gboolean
+window_close(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+
+	if (wm->_list.window)
+		return TRUE;
+
+	if (wm->ordered) {
+		gnt_widget_destroy(wm->ordered->data);
+	}
+
+	return TRUE;
+}
+
+static void
+destroy__list(GntWidget *widget, GntWM *wm)
+{
+	wm->_list.window = NULL;
+	wm->_list.tree = NULL;
+	wm->windows = NULL;
+	wm->actions = NULL;
+	update_screen(wm);
+}
+
+static void
+setup__list(GntWM *wm)
+{
+	GntWidget *tree, *win;
+	win = wm->_list.window = gnt_box_new(FALSE, FALSE);
+	gnt_box_set_toplevel(GNT_BOX(win), TRUE);
+	gnt_box_set_pad(GNT_BOX(win), 0);
+	GNT_WIDGET_SET_FLAGS(win, GNT_WIDGET_TRANSIENT);
+
+	tree = wm->_list.tree = gnt_tree_new();
+	gnt_box_add_widget(GNT_BOX(win), tree);
+
+	g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(destroy__list), wm);
+}
+
+static void
+window_list_activate(GntTree *tree, GntWM *wm)
+{
+	GntWidget *widget = gnt_tree_get_selection_data(GNT_TREE(tree));
+
+	if (!wm->ordered || !widget)
+		return;
+
+	gnt_widget_destroy(wm->_list.window);
+	gnt_wm_raise_window(wm, widget);
+}
+
+static gboolean
+window_list(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+	GntWidget *tree, *win;
+	GList *iter;
+
+	if (wm->_list.window || wm->menu)
+		return TRUE;
+
+	if (!wm->ordered)
+		return TRUE;
+
+	setup__list(wm);
+	wm->windows = &wm->_list;
+
+	win = wm->windows->window;
+	tree = wm->windows->tree;
+
+	gnt_box_set_title(GNT_BOX(win), "Window List");
+
+	for (iter = wm->list; iter; iter = iter->next) {
+		GntBox *box = GNT_BOX(iter->data);
+
+		gnt_tree_add_row_last(GNT_TREE(tree), box,
+				gnt_tree_create_row(GNT_TREE(tree), box->title), NULL);
+		update_window_in_list(wm, GNT_WIDGET(box));
+	}
+
+	gnt_tree_set_selected(GNT_TREE(tree), wm->ordered->data);
+	g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(window_list_activate), wm);
+
+	gnt_tree_set_col_width(GNT_TREE(tree), 0, getmaxx(stdscr) / 3);
+	gnt_widget_set_size(tree, 0, getmaxy(stdscr) / 2);
+	gnt_widget_set_position(win, getmaxx(stdscr) / 3, getmaxy(stdscr) / 4);
+
+	gnt_widget_show(win);
+	return TRUE;
+}
+
+static gboolean
+dump_screen(GntBindable *bindable, GList *null)
+{
+	int x, y;
+	chtype old = 0, now = 0;
+	FILE *file = fopen("dump.html", "w");
+
+	fprintf(file, "<pre>");
+	for (y = 0; y < getmaxy(stdscr); y++) {
+		for (x = 0; x < getmaxx(stdscr); x++) {
+			char ch;
+			now = mvwinch(curscr, y, x);
+			ch = now & A_CHARTEXT;
+			now ^= ch;
+
+#define CHECK(attr, start, end) \
+			do \
+			{  \
+				if (now & attr)  \
+				{  \
+					if (!(old & attr))  \
+						fprintf(file, start);  \
+				}  \
+				else if (old & attr)  \
+				{  \
+					fprintf(file, end);  \
+				}  \
+			} while (0) 
+
+			CHECK(A_BOLD, "<b>", "</b>");
+			CHECK(A_UNDERLINE, "<u>", "</u>");
+			CHECK(A_BLINK, "<blink>", "</blink>");
+
+			if ((now & A_COLOR) != (old & A_COLOR) ||
+				(now & A_REVERSE) != (old & A_REVERSE))
+			{
+				int ret;
+				short fgp, bgp, r, g, b;
+				struct
+				{
+					int r, g, b;
+				} fg, bg;
+
+				ret = pair_content(PAIR_NUMBER(now & A_COLOR), &fgp, &bgp);
+				if (fgp == -1)
+					fgp = COLOR_BLACK;
+				if (bgp == -1)
+					bgp = COLOR_WHITE;
+				if (now & A_REVERSE)
+					fgp ^= bgp ^= fgp ^= bgp;  /* *wink* */
+				ret = color_content(fgp, &r, &g, &b);
+				fg.r = r; fg.b = b; fg.g = g;
+				ret = color_content(bgp, &r, &g, &b);
+				bg.r = r; bg.b = b; bg.g = g;
+#define ADJUST(x) (x = x * 255 / 1000)
+				ADJUST(fg.r);
+				ADJUST(fg.g);
+				ADJUST(fg.b);
+				ADJUST(bg.r);
+				ADJUST(bg.b);
+				ADJUST(bg.g);
+				
+				if (x) fprintf(file, "</span>");
+				fprintf(file, "<span style=\"background:#%02x%02x%02x;color:#%02x%02x%02x\">",
+						bg.r, bg.g, bg.b, fg.r, fg.g, fg.b);
+			}
+			if (now & A_ALTCHARSET)
+			{
+				switch (ch)
+				{
+					case 'q':
+						ch = '-'; break;
+					case 't':
+					case 'u':
+					case 'x':
+						ch = '|'; break;
+					case 'v':
+					case 'w':
+					case 'l':
+					case 'm':
+					case 'k':
+					case 'j':
+					case 'n':
+						ch = '+'; break;
+					case '-':
+						ch = '^'; break;
+					case '.':
+						ch = 'v'; break;
+					case 'a':
+						ch = '#'; break;
+					default:
+						ch = ' '; break;
+				}
+			}
+			if (ch == '&')
+				fprintf(file, "&amp;");
+			else if (ch == '<')
+				fprintf(file, "&lt;");
+			else if (ch == '>')
+				fprintf(file, "&gt;");
+			else
+				fprintf(file, "%c", ch);
+			old = now;
+		}
+		fprintf(file, "</span>\n");
+		old = 0;
+	}
+	fprintf(file, "</pre>");
+	fclose(file);
+	return TRUE;
+}
+
+static void
+shift_window(GntWM *wm, GntWidget *widget, int dir)
+{
+	GList *all = wm->list;
+	GList *list = g_list_find(all, widget);
+	int length, pos;
+	if (!list)
+		return;
+
+	length = g_list_length(all);
+	pos = g_list_position(all, list);
+
+	pos += dir;
+	if (dir > 0)
+		pos++;
+
+	if (pos < 0)
+		pos = length;
+	else if (pos > length)
+		pos = 0;
+
+	all = g_list_insert(all, widget, pos);
+	all = g_list_delete_link(all, list);
+	wm->list = all;
+	draw_taskbar(wm, FALSE);
+}
+
+static gboolean
+shift_left(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+	if (wm->_list.window)
+		return TRUE;
+
+	shift_window(wm, wm->ordered->data, -1);
+	return TRUE;
+}
+
+static gboolean
+shift_right(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+	if (wm->_list.window)
+		return TRUE;
+
+	shift_window(wm, wm->ordered->data, 1);
+	return TRUE;
+}
+
+static void
+action_list_activate(GntTree *tree, GntWM *wm)
+{
+	GntAction *action = gnt_tree_get_selection_data(tree);
+	action->callback();
+	gnt_widget_destroy(wm->_list.window);
+}
+
+static int
+compare_action(gconstpointer p1, gconstpointer p2)
+{
+	const GntAction *a1 = p1;
+	const GntAction *a2 = p2;
+
+	return g_utf8_collate(a1->label, a2->label);
+}
+
+static gboolean
+list_actions(GntBindable *bindable, GList *null)
+{
+	GntWidget *tree, *win;
+	GList *iter;
+	GntWM *wm = GNT_WM(bindable);
+	if (wm->_list.window || wm->menu)
+		return TRUE;
+
+	if (wm->acts == NULL)
+		return TRUE;
+
+	setup__list(wm);
+	wm->actions = &wm->_list;
+
+	win = wm->actions->window;
+	tree = wm->actions->tree;
+
+	gnt_box_set_title(GNT_BOX(win), "Actions");
+	GNT_WIDGET_SET_FLAGS(tree, GNT_WIDGET_NO_BORDER);
+	/* XXX: Do we really want this? */
+	gnt_tree_set_compare_func(GNT_TREE(tree), compare_action);
+
+	for (iter = wm->acts; iter; iter = iter->next) {
+		GntAction *action = iter->data;
+		gnt_tree_add_row_last(GNT_TREE(tree), action,
+				gnt_tree_create_row(GNT_TREE(tree), action->label), NULL);
+	}
+	g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(action_list_activate), wm);
+	gnt_widget_set_size(tree, 0, g_list_length(wm->acts));
+	gnt_widget_set_position(win, 0, getmaxy(stdscr) - 3 - g_list_length(wm->acts));
+
+	gnt_widget_show(win);
+	return TRUE;
+}
+
+#ifndef NO_WIDECHAR
+static int
+widestringwidth(wchar_t *wide)
+{
+	int len, ret;
+	char *string;
+
+	len = wcstombs(NULL, wide, 0) + 1;
+	string = g_new0(char, len);
+	wcstombs(string, wide, len);
+	ret = gnt_util_onscreen_width(string, NULL);
+	g_free(string);
+	return ret;
+}
+#endif
+
+/* Returns the onscreen width of the character at the position */
+static int
+reverse_char(WINDOW *d, int y, int x, gboolean set)
+{
+#define DECIDE(ch) (set ? ((ch) | A_REVERSE) : ((ch) & ~A_REVERSE))
+
+#ifdef NO_WIDECHAR
+	chtype ch;
+	ch = mvwinch(d, y, x);
+	mvwaddch(d, y, x, DECIDE(ch));
+	return 1;
+#else
+	cchar_t ch;
+	int wc = 1;
+	if (mvwin_wch(d, y, x, &ch) == OK) {
+		wc = widestringwidth(ch.chars);
+		ch.attr = DECIDE(ch.attr);
+		ch.attr &= WA_ATTRIBUTES;   /* XXX: This is a workaround for a bug */
+		mvwadd_wch(d, y, x, &ch);
+	}
+
+	return wc;
+#endif
+}
+
+static void
+window_reverse(GntWidget *win, gboolean set)
+{
+	int i;
+	int w, h;
+	WINDOW *d;
+
+	if (GNT_WIDGET_IS_FLAG_SET(win, GNT_WIDGET_NO_BORDER))
+		return;
+	
+	d = win->window;
+	gnt_widget_get_size(win, &w, &h);
+
+	if (gnt_widget_has_shadow(win)) {
+		--w;
+		--h;
+	}
+
+	/* the top and bottom */
+	for (i = 0; i < w; i += reverse_char(d, 0, i, set));
+	for (i = 0; i < w; i += reverse_char(d, h-1, i, set));
+
+	/* the left and right */
+	for (i = 0; i < h; i += reverse_char(d, i, 0, set));
+	for (i = 0; i < h; i += reverse_char(d, i, w-1, set));
+
+	wrefresh(win->window);
+}
+
+static gboolean
+start_move(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+	if (wm->_list.window || wm->menu)
+		return TRUE;
+	if (!wm->ordered)
+		return TRUE;
+
+	wm->mode = GNT_KP_MODE_MOVE;
+	window_reverse(GNT_WIDGET(wm->ordered->data), TRUE);
+
+	return TRUE;
+}
+
+static gboolean
+start_resize(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+	if (wm->_list.window || wm->menu)
+		return TRUE;
+	if (!wm->ordered)
+		return TRUE;
+
+	wm->mode = GNT_KP_MODE_RESIZE;
+	window_reverse(GNT_WIDGET(wm->ordered->data), TRUE);
+
+	return TRUE;
+}
+
+static gboolean
+wm_quit(GntBindable *bindable, GList *list)
+{
+	GntWM *wm = GNT_WM(bindable);
+	g_main_loop_quit(wm->loop);
+	return TRUE;
+}
+
+static gboolean
+return_true(GntWM *wm, GntWidget *w, int *a, int *b)
+{
+	return TRUE;
+}
+
+static gboolean
+refresh_screen(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+
+	endwin();
+	refresh();
+
+	g_hash_table_foreach(wm->nodes, (GHFunc)refresh_node, NULL);
+	update_screen(wm);
+	draw_taskbar(wm, TRUE);
+
+	return FALSE;
+}
+
+static void
+gnt_wm_class_init(GntWMClass *klass)
+{
+	klass->new_window = gnt_wm_new_window_real;
+	klass->decorate_window = NULL;
+	klass->close_window = NULL;
+	klass->window_resize_confirm = return_true;
+	klass->window_resized = gnt_wm_win_resized;
+	klass->window_move_confirm = return_true;
+	klass->window_moved = gnt_wm_win_moved;
+	klass->window_update = NULL;
+	klass->key_pressed  = NULL;
+	klass->mouse_clicked = NULL;
+	klass->give_focus = gnt_wm_give_focus;
+	
+	signals[SIG_NEW_WIN] = 
+		g_signal_new("new_win",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWMClass, new_window),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__POINTER,
+					 G_TYPE_NONE, 1, G_TYPE_POINTER);
+	signals[SIG_DECORATE_WIN] = 
+		g_signal_new("decorate_win",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWMClass, decorate_window),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__POINTER,
+					 G_TYPE_NONE, 1, G_TYPE_POINTER);
+	signals[SIG_CLOSE_WIN] = 
+		g_signal_new("close_win",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWMClass, close_window),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__POINTER,
+					 G_TYPE_NONE, 1, G_TYPE_POINTER);
+	signals[SIG_CONFIRM_RESIZE] = 
+		g_signal_new("confirm_resize",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWMClass, window_resize_confirm),
+					 gnt_boolean_handled_accumulator, NULL,
+					 gnt_closure_marshal_BOOLEAN__POINTER_POINTER_POINTER,
+					 G_TYPE_BOOLEAN, 3, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER);
+
+	signals[SIG_CONFIRM_MOVE] = 
+		g_signal_new("confirm_move",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWMClass, window_move_confirm),
+					 gnt_boolean_handled_accumulator, NULL,
+					 gnt_closure_marshal_BOOLEAN__POINTER_POINTER_POINTER,
+					 G_TYPE_BOOLEAN, 3, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER);
+
+	signals[SIG_RESIZED] = 
+		g_signal_new("window_resized",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWMClass, window_resized),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__POINTER,
+					 G_TYPE_NONE, 1, G_TYPE_POINTER);
+	signals[SIG_MOVED] = 
+		g_signal_new("window_moved",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWMClass, window_moved),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__POINTER,
+					 G_TYPE_NONE, 1, G_TYPE_POINTER);
+	signals[SIG_UPDATE_WIN] = 
+		g_signal_new("window_update",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWMClass, window_update),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__POINTER,
+					 G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+	signals[SIG_GIVE_FOCUS] = 
+		g_signal_new("give_focus",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWMClass, give_focus),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__POINTER,
+					 G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+	signals[SIG_MOUSE_CLICK] = 
+		g_signal_new("mouse_clicked",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWMClass, mouse_clicked),
+					 gnt_boolean_handled_accumulator, NULL,
+					 gnt_closure_marshal_BOOLEAN__INT_INT_INT_POINTER,
+					 G_TYPE_BOOLEAN, 4, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_POINTER);
+
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-next", window_next,
+				"\033" "n", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-prev", window_prev,
+				"\033" "p", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-close", window_close,
+				"\033" "c", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-list", window_list,
+				"\033" "w", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "dump-screen", dump_screen,
+				"\033" "d", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "shift-left", shift_left,
+				"\033" ",", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "shift-right", shift_right,
+				"\033" ".", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "action-list", list_actions,
+				"\033" "a", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "start-move", start_move,
+				"\033" "m", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "start-resize", start_resize,
+				"\033" "r", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "wm-quit", wm_quit,
+				"\033" "q", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "refresh-screen", refresh_screen,
+				"\033" "l", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "switch-window-n", switch_window_n,
+				NULL, NULL);
+
+	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
+	GNTDEBUG;
+}
+
+/******************************************************************************
+ * GntWM API
+ *****************************************************************************/
+GType
+gnt_wm_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0) {
+		static const GTypeInfo info = {
+			sizeof(GntWMClass),
+			NULL,					/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_wm_class_init,
+			NULL,
+			NULL,					/* class_data		*/
+			sizeof(GntWM),
+			0,						/* n_preallocs		*/
+			gnt_wm_init,			/* instance_init	*/
+		};
+
+		type = g_type_register_static(GNT_TYPE_BINDABLE,
+									  "GntWM",
+									  &info, 0);
+	}
+
+	return type;
+}
+static void
+update_window_in_list(GntWM *wm, GntWidget *wid)
+{
+	GntTextFormatFlags flag = 0;
+
+	if (wm->windows == NULL)
+		return;
+
+	if (wid == wm->ordered->data)
+		flag |= GNT_TEXT_FLAG_DIM;
+	else if (GNT_WIDGET_IS_FLAG_SET(wid, GNT_WIDGET_URGENT))
+		flag |= GNT_TEXT_FLAG_BOLD;
+
+	gnt_tree_set_row_flags(GNT_TREE(wm->windows->tree), wid, flag);
+}
+
+static void
+gnt_wm_new_window_real(GntWM *wm, GntWidget *widget)
+{
+	GntNode *node;
+	gboolean transient = FALSE;
+
+	if (widget->window == NULL)
+		return;
+
+	node = g_new0(GntNode, 1);
+	node->me = widget;
+
+	g_hash_table_replace(wm->nodes, widget, node);
+
+	refresh_node(widget, node, NULL);
+
+	transient = !!GNT_WIDGET_IS_FLAG_SET(node->me, GNT_WIDGET_TRANSIENT);
+
+	node->panel = new_panel(node->me->window);
+	set_panel_userptr(node->panel, node);
+
+	if (!transient) {
+		if (node->me != wm->_list.window) {
+			GntWidget *w = NULL;
+
+			if (wm->ordered)
+				w = wm->ordered->data;
+
+			wm->list = g_list_append(wm->list, widget);
+
+			if (wm->event_stack)
+				wm->ordered = g_list_prepend(wm->ordered, widget);
+			else
+				wm->ordered = g_list_append(wm->ordered, widget);
+
+			gnt_widget_set_focus(widget, TRUE);
+			if (w)
+				gnt_widget_set_focus(w, FALSE);
+		}
+
+		if (wm->event_stack || node->me == wm->_list.window) {
+			gnt_wm_raise_window(wm, node->me);
+		} else {
+			bottom_panel(node->panel);     /* New windows should not grab focus */
+			gnt_widget_set_urgent(node->me);
+		}
+	}
+}
+
+void gnt_wm_new_window(GntWM *wm, GntWidget *widget)
+{
+	while (widget->parent)
+		widget = widget->parent;
+	
+	if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_INVISIBLE) ||
+			g_hash_table_lookup(wm->nodes, widget)) {
+		update_screen(wm);
+		return;
+	}
+
+	g_signal_emit(wm, signals[SIG_NEW_WIN], 0, widget);
+	g_signal_emit(wm, signals[SIG_DECORATE_WIN], 0, widget);
+
+	if (wm->windows && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_TRANSIENT)) {
+		if ((GNT_IS_BOX(widget) && GNT_BOX(widget)->title) && wm->_list.window != widget
+				&& GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_CAN_TAKE_FOCUS)) {
+			gnt_tree_add_row_last(GNT_TREE(wm->windows->tree), widget,
+					gnt_tree_create_row(GNT_TREE(wm->windows->tree), GNT_BOX(widget)->title),
+					NULL);
+			update_window_in_list(wm, widget);
+		}
+	}
+
+	update_screen(wm);
+	draw_taskbar(wm, FALSE);
+}
+
+void gnt_wm_window_decorate(GntWM *wm, GntWidget *widget)
+{
+	g_signal_emit(wm, signals[SIG_DECORATE_WIN], 0, widget);
+}
+
+void gnt_wm_window_close(GntWM *wm, GntWidget *widget)
+{
+	GntNode *node;
+	int pos;
+
+	if ((node = g_hash_table_lookup(wm->nodes, widget)) == NULL)
+		return;
+
+	g_signal_emit(wm, signals[SIG_CLOSE_WIN], 0, widget);
+	g_hash_table_remove(wm->nodes, widget);
+
+	if (wm->windows) {
+		gnt_tree_remove(GNT_TREE(wm->windows->tree), widget);
+	}
+
+	pos = g_list_index(wm->list, widget);
+
+	if (pos != -1) {
+		wm->list = g_list_remove(wm->list, widget);
+		wm->ordered = g_list_remove(wm->ordered, widget);
+
+		if (wm->ordered)
+			gnt_wm_raise_window(wm, wm->ordered->data);
+	}
+
+	update_screen(wm);
+	draw_taskbar(wm, FALSE);
+}
+
+void gnt_wm_process_input(GntWM *wm, const char *keys)
+{
+	keys = gnt_bindable_remap_keys(GNT_BINDABLE(wm), keys);
+
+	if (gnt_bindable_perform_action_key(GNT_BINDABLE(wm), keys))
+		return;
+
+	/* Do some manual checking */
+	if (wm->ordered && wm->mode != GNT_KP_MODE_NORMAL) {
+		int xmin = 0, ymin = 0, xmax = getmaxx(stdscr), ymax = getmaxy(stdscr) - 1;
+		int x, y, w, h;
+		GntWidget *widget = GNT_WIDGET(wm->ordered->data);
+		int ox, oy, ow, oh;
+
+		gnt_widget_get_position(widget, &x, &y);
+		gnt_widget_get_size(widget, &w, &h);
+		ox = x;	oy = y;
+		ow = w;	oh = h;
+
+		if (wm->mode == GNT_KP_MODE_MOVE) {
+			if (strcmp(keys, GNT_KEY_LEFT) == 0) {
+				if (x > xmin)
+					x--;
+			} else if (strcmp(keys, GNT_KEY_RIGHT) == 0) {
+				if (x + w < xmax)
+					x++;
+			} else if (strcmp(keys, GNT_KEY_UP) == 0) {
+				if (y > ymin)
+					y--;
+			} else if (strcmp(keys, GNT_KEY_DOWN) == 0) {
+				if (y + h < ymax)
+					y++;
+			}
+			if (ox != x || oy != y) {
+				gnt_screen_move_widget(widget, x, y);
+				window_reverse(widget, TRUE);
+				return;
+			}
+		} else if (wm->mode == GNT_KP_MODE_RESIZE) {
+			if (strcmp(keys, GNT_KEY_LEFT) == 0) {
+				w--;
+			} else if (strcmp(keys, GNT_KEY_RIGHT) == 0) {
+				if (x + w < xmax)
+					w++;
+			} else if (strcmp(keys, GNT_KEY_UP) == 0) {
+				h--;
+			} else if (strcmp(keys, GNT_KEY_DOWN) == 0) {
+				if (y + h < ymax)
+					h++;
+			}
+			if (oh != h || ow != w) {
+				gnt_screen_resize_widget(widget, w, h);
+				window_reverse(widget, TRUE);
+				return;
+			}
+		}
+		if (strcmp(keys, "\r") == 0 || strcmp(keys, "\033") == 0) {
+			window_reverse(widget, FALSE);
+			wm->mode = GNT_KP_MODE_NORMAL;
+			return;
+		}
+	}
+
+	wm->event_stack = TRUE;
+
+	/* Escape to close the window-list or action-list window */
+	if (strcmp(keys, "\033") == 0) {
+		if (wm->_list.window) {
+			gnt_widget_destroy(wm->_list.window);
+			wm->event_stack = FALSE;
+			return;
+		}
+	} else if (keys[0] == '\033' && isdigit(keys[1]) && keys[2] == '\0') {
+		/* Alt+x for quick switch */
+		int n = *(keys + 1) - '0';
+		GList *list = NULL;
+
+		if (n == 0)
+			n = 10;
+
+		list = g_list_append(list, GINT_TO_POINTER(n - 1));
+		switch_window_n(GNT_BINDABLE(wm), list);
+		g_list_free(list);
+		return;
+	}
+
+	if (wm->menu)
+		gnt_widget_key_pressed(GNT_WIDGET(wm->menu), keys);
+	else if (wm->_list.window)
+		gnt_widget_key_pressed(wm->_list.window, keys);
+	else if (wm->ordered)
+		gnt_widget_key_pressed(GNT_WIDGET(wm->ordered->data), keys);
+	wm->event_stack = FALSE;
+}
+
+static void
+gnt_wm_win_resized(GntWM *wm, GntNode *node)
+{
+	refresh_node(node->me, node, NULL);
+	replace_panel(node->panel, node->me->window);
+}
+
+static void
+gnt_wm_win_moved(GntWM *wm, GntNode *node)
+{
+	refresh_node(node->me, node, NULL);
+}
+
+void gnt_wm_resize_window(GntWM *wm, GntWidget *widget, int width, int height)
+{
+	gboolean ret = TRUE;
+	GntNode *node;
+	
+	while (widget->parent)
+		widget = widget->parent;
+	node = g_hash_table_lookup(wm->nodes, widget);
+	if (!node)
+		return;
+
+	g_signal_emit(wm, signals[SIG_CONFIRM_RESIZE], 0, widget, &width, &height, &ret);
+	if (!ret)
+		return;    /* resize is not permitted */
+	hide_panel(node->panel);
+	gnt_widget_set_size(widget, width, height);
+	gnt_widget_draw(widget);
+
+	g_signal_emit(wm, signals[SIG_RESIZED], 0, node);
+
+	show_panel(node->panel);
+	update_screen(wm);
+}
+
+void gnt_wm_move_window(GntWM *wm, GntWidget *widget, int x, int y)
+{
+	gboolean ret = TRUE;
+	GntNode *node;
+
+	while (widget->parent)
+		widget = widget->parent;
+	node = g_hash_table_lookup(wm->nodes, widget);
+	if (!node)
+		return;
+
+	g_signal_emit(wm, signals[SIG_CONFIRM_MOVE], 0, widget, &x, &y, &ret);
+	if (!ret)
+		return;    /* resize is not permitted */
+
+	gnt_widget_set_position(widget, x, y);
+	move_panel(node->panel, y, x);
+
+	g_signal_emit(wm, signals[SIG_MOVED], 0, node);
+
+	update_screen(wm);
+}
+
+static void
+gnt_wm_give_focus(GntWM *wm, GntWidget *widget)
+{
+	GntNode *node = g_hash_table_lookup(wm->nodes, widget);
+
+	if (!node)
+		return;
+	
+	if (widget != wm->_list.window && !GNT_IS_MENU(widget) &&
+				wm->ordered->data != widget) {
+		GntWidget *w = wm->ordered->data;
+		wm->ordered = g_list_bring_to_front(wm->ordered, widget);
+		gnt_widget_set_focus(w, FALSE);
+	}
+
+	gnt_widget_set_focus(widget, TRUE);
+	GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_URGENT);
+	gnt_widget_draw(widget);
+	top_panel(node->panel);
+
+	if (wm->_list.window) {
+		GntNode *nd = g_hash_table_lookup(wm->nodes, wm->_list.window);
+		top_panel(nd->panel);
+	}
+	update_screen(wm);
+	draw_taskbar(wm, FALSE);
+}
+
+void gnt_wm_update_window(GntWM *wm, GntWidget *widget)
+{
+	GntNode *node;
+
+	while (widget->parent)
+		widget = widget->parent;
+	if (!GNT_IS_MENU(widget))
+		gnt_box_sync_children(GNT_BOX(widget));
+
+	node = g_hash_table_lookup(wm->nodes, widget);
+	if (node == NULL) {
+		gnt_wm_new_window(wm, widget);
+	} else
+		g_signal_emit(wm, signals[SIG_UPDATE_WIN], 0, node);
+
+	update_screen(wm);
+	draw_taskbar(wm, FALSE);
+}
+
+gboolean gnt_wm_process_click(GntWM *wm, GntMouseEvent event, int x, int y, GntWidget *widget)
+{
+	gboolean ret = TRUE;
+	g_signal_emit(wm, signals[SIG_MOUSE_CLICK], 0, event, x, y, widget, &ret);
+	return ret;
+}
+
+void gnt_wm_raise_window(GntWM *wm, GntWidget *widget)
+{
+	g_signal_emit(wm, signals[SIG_GIVE_FOCUS], 0, widget);
+}
+
--- a/console/libgnt/gntwm.h	Sun Nov 05 14:57:05 2006 +0000
+++ b/console/libgnt/gntwm.h	Sun Nov 05 17:28:33 2006 +0000
@@ -1,55 +1,155 @@
 #include <panel.h>
 
 #include "gntwidget.h"
+#include "gntmenu.h"
 
-/* XXX: It might be a good idea to move GntNode from gntmain.c to here. */
+#define GNT_TYPE_WM				(gnt_wm_get_gtype())
+#define GNT_WM(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_WM, GntWM))
+#define GNT_WM_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_WM, GntWMClass))
+#define GNT_IS_WM(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_WM))
+#define GNT_IS_WM_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_WM))
+#define GNT_WM_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_WM, GntWMClass))
+
+typedef enum
+{
+	GNT_KP_MODE_NORMAL,
+	GNT_KP_MODE_RESIZE,
+	GNT_KP_MODE_MOVE,
+} GntKeyPressMode;
+
+typedef struct
+{
+	GntWidget *me;
+
+	PANEL *panel;
+} GntNode;
 
 typedef struct _GntWM GntWM;
 
+/**
+ * An application can register actions which will show up in a 'start-menu' like popup
+ */
+typedef struct _GnAction
+{
+	const char *label;
+	void (*callback)();
+} GntAction;
+
 struct _GntWM
 {
-	/* This should return a PANEL for the win */
-	PANEL *(*new_window)(GntWidget *win);
+	GntBindable inherit;
+
+	GMainLoop *loop;
+
+	GList *list;      /* List of windows ordered on their creation time */
+	GList *ordered;   /* List of windows ordered on their focus */
+
+	struct {
+		GntWidget *window;
+		GntWidget *tree;
+	} _list,
+		*windows,         /* Window-list window */
+		*actions;         /* Action-list window */
+
+	GHashTable *nodes;    /* GntWidget -> GntNode */
+
+	GList *acts;          /* List of actions */
+
+	/**
+	 * There can be at most one menu at a time on the screen.
+	 * If there is a menu being displayed, then all the keystrokes will be sent to
+	 * the menu until it is closed, either when the user activates a menuitem, or
+	 * presses Escape to cancel the menu.
+	 */
+	GntMenu *menu;        /* Currently active menu */
 
+	/**
+	 * 'event_stack' will be set to TRUE when a user-event, ie. a mouse-click
+	 * or a key-press is being processed. This variable will be used to determine
+	 * whether to give focus to a new window.
+	 */
+	gboolean event_stack;
+	
+	GntKeyPressMode mode;
+
+	void *res1;
+	void *res2;
+	void *res3;
+	void *res4;
+};
+
+typedef struct _GnWMClass GntWMClass;
+
+struct _GnWMClass
+{
+	GntBindableClass parent;
+
+	/* This is called when a new window is shown */
+	void (*new_window)(GntWM *wm, GntWidget *win);
+
+	void (*decorate_window)(GntWM *wm, GntWidget *win);
 	/* This is called when a window is being closed */
-	gboolean (*close_window)(GntWidget *win);
+	gboolean (*close_window)(GntWM *wm, GntWidget *win);
 
 	/* The WM may want to confirm a size for a window first */
-	gboolean (*window_resize_confirm)(GntWidget *win, int *w, int *h);
+	gboolean (*window_resize_confirm)(GntWM *wm, GntWidget *win, int *w, int *h);
 
-	/* Can del_panel the old panel and return a new_panel.
-	 * Otherwise, this should at least do a replace_panel. */
-	PANEL *(*window_resized)(PANEL *pan, GntWidget *win);
+	void (*window_resized)(GntWM *wm, GntNode *node);
 
 	/* The WM may want to confirm the position of a window */
-	gboolean (*window_move_confirm)(GntWidget *win, int *x, int *y);
+	gboolean (*window_move_confirm)(GntWM *wm, GntWidget *win, int *x, int *y);
 
-	void (*window_moved)(PANEL *pan, GntWidget *win);
+	void (*window_moved)(GntWM *wm, GntNode *node);
 
 	/* This gets called when:
 	 * 	 - the title of the window changes
 	 * 	 - the 'urgency' of the window changes
 	 */
-	void (*window_update)(PANEL *pan, GntWidget *win);
+	void (*window_update)(GntWM *wm, GntNode *node);
 
 	/* This should usually return NULL if the keys were processed by the WM.
 	 * If not, the WM can simply return the original string, which will be
 	 * processed by the default WM. The custom WM can also return a different
 	 * static string for the default WM to process.
 	 */
-	const char *(*key_pressed)(const char *key);
+	gboolean (*key_pressed)(GntWM *wm, const char *key);
 
-	gboolean (*mouse_clicked)(GntMouseEvent event, int x, int y, GntWidget *widget);
+	gboolean (*mouse_clicked)(GntWM *wm, GntMouseEvent event, int x, int y, GntWidget *widget);
 
 	/* Whatever the WM wants to do when a window is given focus */
-	void (*give_focus)(GntWidget *widget);
-
-	/* If something needs to be uninited */
-	void (*gntwm_uninit)();
+	void (*give_focus)(GntWM *wm, GntWidget *widget);
 
 	/* List of windows. Although the WM can keep a list of its own for the windows,
 	 * it'd be better if there was a way to share between the 'core' and the WM.
 	 */
-	const GList *(*window_list)();
+	/*const GList *(*window_list)();*/
+
+	void (*res1)(void);
+	void (*res2)(void);
+	void (*res3)(void);
+	void (*res4)(void);
 };
 
+G_BEGIN_DECLS
+
+GType gnt_wm_get_gtype(void);
+
+void gnt_wm_new_window(GntWM *wm, GntWidget *widget);
+
+void gnt_wm_window_decorate(GntWM *wm, GntWidget *widget);
+
+void gnt_wm_window_close(GntWM *wm, GntWidget *widget);
+
+void gnt_wm_process_input(GntWM *wm, const char *string);
+
+gboolean gnt_wm_process_click(GntWM *wm, GntMouseEvent event, int x, int y, GntWidget *widget);
+
+void gnt_wm_resize_window(GntWM *wm, GntWidget *widget, int width, int height);
+
+void gnt_wm_move_window(GntWM *wm, GntWidget *widget, int x, int y);
+
+void gnt_wm_update_window(GntWM *wm, GntWidget *widget);
+
+void gnt_wm_raise_window(GntWM *wm, GntWidget *widget);
+
+G_END_DECLS
--- a/console/libgnt/test/multiwin.c	Sun Nov 05 14:57:05 2006 +0000
+++ b/console/libgnt/test/multiwin.c	Sun Nov 05 17:28:33 2006 +0000
@@ -62,7 +62,6 @@
 
 	gnt_tree_add_row_after(GNT_TREE(tree), "6", gnt_tree_create_row(GNT_TREE(tree), "6", " long text", "a2"), "4", NULL);
 
-	gnt_tree_add_row_after(GNT_TREE(tree), NULL, NULL, NULL, "4");
 	int i;
 	for (i = 110; i < 430; i++)
 	{
--- a/console/libgnt/test/tv.c	Sun Nov 05 14:57:05 2006 +0000
+++ b/console/libgnt/test/tv.c	Sun Nov 05 17:28:33 2006 +0000
@@ -25,9 +25,9 @@
 	}
 	else if (key[0] == 27)
 	{
-		if (strcmp(key+1, GNT_KEY_UP) == 0)
+		if (strcmp(key, GNT_KEY_UP) == 0)
 			gnt_text_view_scroll(GNT_TEXT_VIEW(view), -1);
-		else if (strcmp(key+1, GNT_KEY_DOWN) == 0)
+		else if (strcmp(key, GNT_KEY_DOWN) == 0)
 			gnt_text_view_scroll(GNT_TEXT_VIEW(view), 1);
 		else
 			return FALSE;
--- a/console/libgnt/wms/s.c	Sun Nov 05 14:57:05 2006 +0000
+++ b/console/libgnt/wms/s.c	Sun Nov 05 17:28:33 2006 +0000
@@ -1,13 +1,30 @@
 #include "gnt.h"
 #include "gntbox.h"
 #include "gntmenu.h"
+#include "gntstyle.h"
 #include "gntwm.h"
 
 #include "gntblist.h"
 
 #include <string.h>
 
-static GntWM *gwm;
+#define TYPE_S				(s_get_gtype())
+
+typedef struct _S
+{
+	GntWM inherit;
+} S;
+
+typedef struct _SClass
+{
+	GntWMClass inherit;
+} SClass;
+
+GType s_get_gtype(void);
+void gntwm_init(GntWM **wm);
+
+static void (*org_new_window)(GntWM *wm, GntWidget *win);
+static gboolean (*org_mouse_clicked)(GntWM *wm, GntMouseEvent event, int cx, int cy, GntWidget *widget);
 
 static void
 envelope_buddylist(GntWidget *win)
@@ -24,7 +41,7 @@
 {
 	int w, h;
 
-	if (GNT_WIDGET_IS_FLAG_SET(win, GNT_WIDGET_NO_BORDER))
+	if (GNT_WIDGET_IS_FLAG_SET(win, GNT_WIDGET_NO_BORDER | GNT_WIDGET_TRANSIENT))
 		return;
 
 	gnt_widget_get_size(win, &w, &h);
@@ -32,8 +49,8 @@
 	mvwprintw(win->window, 0, w - 4, "[X]");
 }
 
-static PANEL *
-s_resize_window(PANEL *panel, GntWidget *win)
+static void
+s_decorate_window(GntWM *wm, GntWidget *win)
 {
 	const char *name;
 
@@ -43,67 +60,69 @@
 	} else {
 		envelope_normal_window(win);
 	}
-	replace_panel(panel, win->window);
-	return panel;
 }
 
-static PANEL *
-s_new_window(GntWidget *win)
+static void
+s_window_update(GntWM *wm, GntNode *node)
+{
+	s_decorate_window(wm, node->me);
+}
+
+static void
+s_new_window(GntWM *wm, GntWidget *win)
 {
 	int x, y, w, h;
 	int maxx, maxy;
 	const char *name;
+	gboolean blist = FALSE;
 
-	if (GNT_IS_MENU(win))
-		return new_panel(win->window);
-	getmaxyx(stdscr, maxy, maxx);
+	if (!GNT_IS_MENU(win)) {
+		getmaxyx(stdscr, maxy, maxx);
 
-	gnt_widget_get_position(win, &x, &y);
-	gnt_widget_get_size(win, &w, &h);
+		gnt_widget_get_position(win, &x, &y);
+		gnt_widget_get_size(win, &w, &h);
 
-	name = gnt_widget_get_name(win);
+		name = gnt_widget_get_name(win);
 
-	if (name && strcmp(name, "buddylist") == 0) {
-		/* The buddylist doesn't have no border nor nothing! */
-		x = 0;
-		y = 0;
-		h = maxy - 1;
+		if (name && strcmp(name, "buddylist") == 0) {
+			/* The buddylist doesn't have no border nor nothing! */
+			x = 0;
+			y = 0;
+			h = maxy - 1;
+			blist = TRUE;
 
-		gnt_box_set_toplevel(GNT_BOX(win), FALSE);
-		GNT_WIDGET_SET_FLAGS(win, GNT_WIDGET_CAN_TAKE_FOCUS);
-		gnt_box_readjust(GNT_BOX(win));
-
-		gnt_widget_set_position(win, x, y);
-		mvwin(win->window, y, x);
+			gnt_box_set_toplevel(GNT_BOX(win), FALSE);
+			GNT_WIDGET_SET_FLAGS(win, GNT_WIDGET_CAN_TAKE_FOCUS);
 
-		gnt_widget_set_size(win, -1, h);
-		gnt_widget_draw(win);
-		envelope_buddylist(win);
-	} else if (name && strcmp(name, "conversation-window") == 0) {
-		/* Put the conversation windows to the far-right */
-		x = maxx - w;
-		y = 0;
-		gnt_widget_set_position(win, x, y);
-		mvwin(win->window, y, x);
-		gnt_widget_draw(win);
-		envelope_normal_window(win);
-	} else if (!GNT_WIDGET_IS_FLAG_SET(win, GNT_WIDGET_TRANSIENT)) {
-		/* In the middle of the screen */
-		x = (maxx - w) / 2;
-		y = (maxy - h) / 2;
+			gnt_widget_set_position(win, x, y);
+			mvwin(win->window, y, x);
 
-		gnt_widget_set_position(win, x, y);
-		mvwin(win->window, y, x);
-		envelope_normal_window(win);
+			gnt_widget_set_size(win, -1, h + 2);  /* XXX: Why is the +2 needed here? -- sadrul */
+		} else if (name && strcmp(name, "conversation-window") == 0) {
+			/* Put the conversation windows to the far-right */
+			x = maxx - w;
+			y = 0;
+			gnt_widget_set_position(win, x, y);
+			mvwin(win->window, y, x);
+		} else if (!GNT_WIDGET_IS_FLAG_SET(win, GNT_WIDGET_TRANSIENT)) {
+			/* In the middle of the screen */
+			x = (maxx - w) / 2;
+			y = (maxy - h) / 2;
+
+			gnt_widget_set_position(win, x, y);
+			mvwin(win->window, y, x);
+		}
 	}
+	org_new_window(wm, win);
 
-	return new_panel(win->window);
+	if (blist)
+		gnt_wm_raise_window(wm, win);
 }
 
 static GntWidget *
-find_widget(const char *wname)
+find_widget(GntWM *wm, const char *wname)
 {
-	const GList *iter = gwm->window_list();
+	const GList *iter = wm->list;
 	for (; iter; iter = iter->next) {
 		GntWidget *widget = iter->data;
 		const char *name = gnt_widget_get_name(widget);
@@ -115,41 +134,17 @@
 }
 
 static gboolean
-give_the_darned_focus(gpointer w)
-{
-	gwm->give_focus(w);
-	return FALSE;
-}
-
-static const char*
-s_key_pressed(const char *key)
-{
-	/* Alt+b to toggle the buddylist */
-	if (key[0] == 27 && key[1] == 'b' && key[2] == '\0') {
-		GntWidget *w = find_widget("buddylist");
-		if (w == NULL) {
-			gg_blist_show();
-			w = find_widget("buddylist");
-			g_timeout_add(0, give_the_darned_focus, w);
-		} else {
-			gnt_widget_destroy(w);
-		}
-		return NULL;
-	}
-	return key;
-}
-
-static gboolean
-s_mouse_clicked(GntMouseEvent event, int cx, int cy, GntWidget *widget)
+s_mouse_clicked(GntWM *wm, GntMouseEvent event, int cx, int cy, GntWidget *widget)
 {
 	int x, y, w, h;
 
 	if (!widget)
-		return FALSE;       /* This might a place to bring up a context menu */
+		return org_mouse_clicked(wm, event, cx, cy, widget);
+		/* This might be a place to bring up a context menu */
 	
 	if (event != GNT_LEFT_MOUSE_DOWN ||
 			GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER))
-		return FALSE;       /* For now, just the left-button to close a window */
+		return org_mouse_clicked(wm, event, cx, cy, widget);
 	
 	gnt_widget_get_position(widget, &x, &y);
 	gnt_widget_get_size(widget, &w, &h);
@@ -158,25 +153,69 @@
 		gnt_widget_destroy(widget);
 		return TRUE;
 	}
-	return FALSE;
+
+	return org_mouse_clicked(wm, event, cx, cy, widget);
+}
+
+static gboolean
+toggle_buddylist(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+	GntWidget *blist = find_widget(wm, "buddylist");
+	if (blist)
+		gnt_widget_destroy(blist);
+	else
+		gg_blist_show();
+	return TRUE;
 }
 
 static void
-s_window_update(PANEL *panel, GntWidget *window)
+s_class_init(SClass *klass)
 {
-	const char *name = gnt_widget_get_name(window);
-	if (name && strcmp(name, "buddylist"))
-		envelope_normal_window(window);
+	GntWMClass *pclass = GNT_WM_CLASS(klass);
+
+	org_new_window = pclass->new_window;
+	org_mouse_clicked = pclass->mouse_clicked;
+
+	pclass->new_window = s_new_window;
+	pclass->decorate_window = s_decorate_window;
+	pclass->window_update = s_window_update;
+	pclass->mouse_clicked = s_mouse_clicked;
+
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "toggle-buddylist",
+				toggle_buddylist, "\033" "b", NULL);
+	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
+	GNTDEBUG;
+}
+
+void gntwm_init(GntWM **wm)
+{
+	*wm = g_object_new(TYPE_S, NULL);
 }
 
-void gntwm_init(GntWM *wm);
-void gntwm_init(GntWM *wm)
+GType s_get_gtype(void)
 {
-	gwm = wm;
-	wm->new_window = s_new_window;
-	wm->window_resized = s_resize_window;
-	wm->key_pressed = s_key_pressed;
-	wm->mouse_clicked = s_mouse_clicked;
-	wm->window_update = s_window_update;
+	static GType type = 0;
+
+	if(type == 0) {
+		static const GTypeInfo info = {
+			sizeof(SClass),
+			NULL,					/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)s_class_init,
+			NULL,
+			NULL,                   /* class_data		*/
+			sizeof(S),
+			0,                      /* n_preallocs		*/
+			NULL,	            /* instance_init	*/
+			NULL
+		};
+
+		type = g_type_register_static(GNT_TYPE_WM,
+									  "GntS",
+									  &info, 0);
+	}
+
+	return type;
 }