summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Nelson <wabz@pidgin.im>2007-04-29 01:09:18 +0000
committerRichard Nelson <wabz@pidgin.im>2007-04-29 01:09:18 +0000
commitffdf7a2b2b6c9661911a58270b78df95b067381d (patch)
treeac95b43198b3a0cbbd60a8415358729bb889e940
parent19fae316850ecd937d82bb5a8cd312121e59c474 (diff)
parentaa3950df2c10a55404570fdd2a3922b9e3f7161c (diff)
downloadpidgin-ffdf7a2b2b6c9661911a58270b78df95b067381d.tar.gz
propagate from branch 'im.pidgin.pidgin' (head fd1ed13fb8f64c35282cf195a91d5440c3b4c750)
to branch 'im.pidgin.finch.workspaces' (head 6e207d99ffd937a5cbf5681dd506a8ecf5d5d5de)
-rw-r--r--finch/libgnt/Makefile.am4
-rw-r--r--finch/libgnt/gntmain.c10
-rw-r--r--finch/libgnt/gntstyle.c43
-rw-r--r--finch/libgnt/gntstyle.h3
-rw-r--r--finch/libgnt/gntwm.c553
-rw-r--r--finch/libgnt/gntwm.h29
-rw-r--r--finch/libgnt/gntws.c158
-rw-r--r--finch/libgnt/gntws.h59
-rw-r--r--finch/libgnt/wms/s.c2
9 files changed, 704 insertions, 157 deletions
diff --git a/finch/libgnt/Makefile.am b/finch/libgnt/Makefile.am
index e4ebddaa76..933a264e51 100644
--- a/finch/libgnt/Makefile.am
+++ b/finch/libgnt/Makefile.am
@@ -1,6 +1,6 @@
EXTRA_DIST=genmarshal
-SUBDIRS = . wms
+SUBDIRS = .
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = gnt.pc
@@ -32,6 +32,7 @@ libgnt_la_SOURCES = \
gntutils.c \
gntwindow.c \
gntwm.c \
+ gntws.c \
gntmain.c
libgnt_la_headers = \
@@ -58,6 +59,7 @@ libgnt_la_headers = \
gntutils.h \
gntwindow.h \
gntwm.h \
+ gntws.h \
gnt.h
CLEANFILES = \
diff --git a/finch/libgnt/gntmain.c b/finch/libgnt/gntmain.c
index e7b70e95d1..a949f7ffb9 100644
--- a/finch/libgnt/gntmain.c
+++ b/finch/libgnt/gntmain.c
@@ -91,7 +91,7 @@ detect_mouse_action(const char *buffer)
GntWidget *widget = NULL;
PANEL *p = NULL;
- if (!wm->ordered || buffer[0] != 27)
+ if (!wm->cws->ordered || buffer[0] != 27)
return FALSE;
buffer++;
@@ -147,7 +147,7 @@ detect_mouse_action(const char *buffer)
if (event == GNT_LEFT_MOUSE_DOWN && widget && widget != wm->_list.window &&
!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_TRANSIENT)) {
- if (widget != wm->ordered->data) {
+ if (widget != wm->cws->ordered->data) {
gnt_wm_raise_window(wm, widget);
}
if (y == widget->priv.y) {
@@ -158,7 +158,7 @@ detect_mouse_action(const char *buffer)
} else if (event == GNT_MOUSE_UP) {
if (button == MOUSE_NONE && y == getmaxy(stdscr) - 1) {
/* Clicked on the taskbar */
- int n = g_list_length(wm->list);
+ int n = g_list_length(wm->cws->list);
if (n) {
int width = getmaxx(stdscr) / n;
gnt_bindable_perform_action_named(GNT_BINDABLE(wm), "switch-window-n", x/width, NULL);
@@ -437,7 +437,7 @@ gboolean gnt_widget_has_focus(GntWidget *widget)
if (widget == wm->_list.window)
return TRUE;
- if (wm->ordered && wm->ordered->data == widget) {
+ if (wm->cws->ordered && wm->cws->ordered->data == widget) {
if (GNT_IS_BOX(widget) &&
(GNT_BOX(widget)->active == w || widget == w))
return TRUE;
@@ -450,7 +450,7 @@ void gnt_widget_set_urgent(GntWidget *widget)
while (widget->parent)
widget = widget->parent;
- if (wm->ordered && wm->ordered->data == widget)
+ if (wm->cws->ordered && wm->cws->ordered->data == widget)
return;
GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_URGENT);
diff --git a/finch/libgnt/gntstyle.c b/finch/libgnt/gntstyle.c
index bbe5db52ae..3cd4eaf9fc 100644
--- a/finch/libgnt/gntstyle.c
+++ b/finch/libgnt/gntstyle.c
@@ -1,9 +1,13 @@
#include "gntstyle.h"
#include "gntcolors.h"
+#include "gntws.h"
#include <ctype.h>
+#include <glib/gprintf.h>
#include <string.h>
+#define MAX_WORKSPACES 99
+
#if GLIB_CHECK_VERSION(2,6,0)
static GKeyFile *gkfile;
#endif
@@ -87,6 +91,45 @@ parse_key(const char *key)
return (char *)gnt_key_translate(key);
}
+void gnt_style_read_workspaces(GntWM *wm)
+{
+#if GLIB_CHECK_VERSION(2,6,0)
+ int i;
+ gchar *name;
+ gsize c;
+
+ for (i = 1; i < MAX_WORKSPACES; ++i) {
+ int j;
+ GntWS *ws;
+ gchar **titles;
+ char *group = calloc(12, 1);
+ g_sprintf(group, "Workspace-%d", i);
+ name = g_key_file_get_value(gkfile, group, "name", NULL);
+ if (!name)
+ return;
+
+ ws = g_object_new(GNT_TYPE_WS, NULL);
+ gnt_ws_set_name(ws, name);
+ gnt_wm_add_workspace(wm, ws);
+ g_free(name);
+
+ titles = g_key_file_get_string_list(gkfile, group, "window-names", &c, NULL);
+ if (titles) {
+ for (j = 0; j < c; ++j)
+ g_hash_table_replace(wm->name_places, g_strdup(titles[j]), ws);
+ g_strfreev(titles);
+ }
+
+ titles = g_key_file_get_string_list(gkfile, group, "window-titles", &c, NULL);
+ if (titles) {
+ for (j = 0; j < c; ++j)
+ g_hash_table_replace(wm->title_places, g_strdup(titles[j]), ws);
+ g_strfreev(titles);
+ }
+ g_free(group);
+ }
+#endif
+}
void gnt_style_read_actions(GType type, GntBindableClass *klass)
{
#if GLIB_CHECK_VERSION(2,6,0)
diff --git a/finch/libgnt/gntstyle.h b/finch/libgnt/gntstyle.h
index 8550f34320..c3a65043cc 100644
--- a/finch/libgnt/gntstyle.h
+++ b/finch/libgnt/gntstyle.h
@@ -1,4 +1,5 @@
#include "gnt.h"
+#include "gntwm.h"
typedef enum
{
@@ -21,6 +22,8 @@ void gnt_styles_get_keyremaps(GType type, GHashTable *hash);
void gnt_style_read_actions(GType type, GntBindableClass *klass);
+void gnt_style_read_workspaces(GntWM *wm);
+
void gnt_init_styles(void);
void gnt_uninit_styles(void);
diff --git a/finch/libgnt/gntwm.c b/finch/libgnt/gntwm.c
index 6889c39954..227e64f014 100644
--- a/finch/libgnt/gntwm.c
+++ b/finch/libgnt/gntwm.c
@@ -6,6 +6,8 @@
#include "config.h"
#include <ctype.h>
+#include <glib/gprintf.h>
+#include <gmodule.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
@@ -47,11 +49,14 @@ 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 void shift_window(GntWM *wm, GntWidget *widget, int dir);
+static gboolean workspace_next(GntBindable *wm, GList *n);
+static gboolean workspace_prev(GntBindable *wm, GList *n);
static gboolean write_already(gpointer data);
static int write_timeout;
static time_t last_active_time;
static gboolean idle_update;
+static GList *act = NULL; /* list of WS with unseen activitiy */
static GList *
g_list_bring_to_front(GList *list, gpointer data)
@@ -70,61 +75,8 @@ free_node(gpointer data)
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));
- if (iter->next)
- mvwhline(taskbar, 0, width * i, ' ' | COLOR_PAIR(color), width);
- else
- mvwhline(taskbar, 0, width * i, ' ' | COLOR_PAIR(color), getmaxx(stdscr) - width * i);
- 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 void
-copy_win(GntWidget *widget, GntNode *node)
+void
+gnt_wm_copy_win(GntWidget *widget, GntNode *node)
{
WINDOW *src, *dst;
int shadow;
@@ -136,6 +88,32 @@ copy_win(GntWidget *widget, GntNode *node)
copywin(src, dst, node->scroll, 0, 0, 0, getmaxy(dst) - 1, getmaxx(dst) - 1, 0);
}
+static void
+update_act_msg()
+{
+ GntWidget *label;
+ GList *iter;
+ static GntWidget *message = NULL;
+ GString *text = g_string_new("act: ");
+ if (message)
+ gnt_widget_destroy(message);
+ if (g_list_length(act) == 0)
+ return;
+ for (iter = act; iter; iter = iter->next) {
+ GntWS *ws = iter->data;
+ g_string_sprintfa(text, "%s, ", gnt_ws_get_name(ws));
+ }
+ g_string_erase(text, text->len - 2, 2);
+ message = gnt_vbox_new(FALSE);
+ label = gnt_label_new_with_format(text->str, GNT_TEXT_FLAG_BOLD | GNT_TEXT_FLAG_HIGHLIGHT);
+ GNT_WIDGET_UNSET_FLAGS(GNT_BOX(message), GNT_WIDGET_CAN_TAKE_FOCUS);
+ GNT_WIDGET_SET_FLAGS(GNT_BOX(message), GNT_WIDGET_TRANSIENT);
+ gnt_box_add_widget(GNT_BOX(message), label);
+ gnt_widget_set_name(message, "wm-message");
+ gnt_widget_set_position(message, 0, 0);
+ gnt_widget_draw(message);
+ g_string_free(text, TRUE);
+}
static gboolean
update_screen(GntWM *wm)
{
@@ -265,9 +243,19 @@ static void
gnt_wm_init(GTypeInstance *instance, gpointer class)
{
GntWM *wm = GNT_WM(instance);
- wm->list = NULL;
- wm->ordered = NULL;
+ wm->workspaces = NULL;
+ wm->name_places = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+ wm->title_places = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+ gnt_style_read_workspaces(wm);
+ if (wm->workspaces == NULL) {
+ wm->cws = g_object_new(GNT_TYPE_WS, NULL);
+ gnt_ws_set_name(wm->cws, "default");
+ gnt_wm_add_workspace(wm, wm->cws);
+ } else {
+ wm->cws = wm->workspaces->data;
+ }
wm->event_stack = FALSE;
+ wm->tagged = NULL;
wm->windows = NULL;
wm->actions = NULL;
wm->nodes = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_node);
@@ -276,6 +264,7 @@ gnt_wm_init(GTypeInstance *instance, gpointer class)
read_window_positions(wm);
g_timeout_add(IDLE_CHECK_INTERVAL * 1000, check_idle, NULL);
time(&last_active_time);
+ gnt_wm_switch_workspace(wm, 0);
}
static void
@@ -287,23 +276,23 @@ switch_window(GntWM *wm, int direction)
if (wm->_list.window || wm->menu)
return;
- if (!wm->ordered || !wm->ordered->next)
+ if (!wm->cws->ordered || !wm->cws->ordered->next)
return;
- w = wm->ordered->data;
- pos = g_list_index(wm->list, w);
+ w = wm->cws->ordered->data;
+ pos = g_list_index(wm->cws->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;
+ wid = g_list_last(wm->cws->list)->data;
+ else if (pos >= g_list_length(wm->cws->list))
+ wid = wm->cws->list->data;
else if (pos >= 0)
- wid = g_list_nth_data(wm->list, pos);
+ wid = g_list_nth_data(wm->cws->list, pos);
- wm->ordered = g_list_bring_to_front(wm->ordered, wid);
+ wm->cws->ordered = g_list_bring_to_front(wm->cws->ordered, wid);
- gnt_wm_raise_window(wm, wm->ordered->data);
+ gnt_wm_raise_window(wm, wm->cws->ordered->data);
if (w != wid) {
gnt_widget_set_focus(w, FALSE);
@@ -334,7 +323,7 @@ switch_window_n(GntBindable *bind, GList *list)
GList *l;
int n;
- if (!wm->ordered)
+ if (!wm->cws->ordered)
return TRUE;
if (list)
@@ -342,9 +331,9 @@ switch_window_n(GntBindable *bind, GList *list)
else
n = 0;
- w = wm->ordered->data;
+ w = wm->cws->ordered->data;
- if ((l = g_list_nth(wm->list, n)) != NULL)
+ if ((l = g_list_nth(wm->cws->list, n)) != NULL)
{
gnt_wm_raise_window(wm, l->data);
}
@@ -363,17 +352,17 @@ window_scroll_up(GntBindable *bindable, GList *null)
GntWidget *window;
GntNode *node;
- if (!wm->ordered)
+ if (!wm->cws->ordered)
return TRUE;
- window = wm->ordered->data;
+ window = wm->cws->ordered->data;
node = g_hash_table_lookup(wm->nodes, window);
if (!node)
return TRUE;
if (node->scroll) {
node->scroll--;
- copy_win(window, node);
+ gnt_wm_copy_win(window, node);
update_screen(wm);
}
return TRUE;
@@ -387,10 +376,10 @@ window_scroll_down(GntBindable *bindable, GList *null)
GntNode *node;
int w, h;
- if (!wm->ordered)
+ if (!wm->cws->ordered)
return TRUE;
- window = wm->ordered->data;
+ window = wm->cws->ordered->data;
node = g_hash_table_lookup(wm->nodes, window);
if (!node)
return TRUE;
@@ -398,7 +387,7 @@ window_scroll_down(GntBindable *bindable, GList *null)
gnt_widget_get_size(window, &w, &h);
if (h - node->scroll > getmaxy(node->window)) {
node->scroll++;
- copy_win(window, node);
+ gnt_wm_copy_win(window, node);
update_screen(wm);
}
return TRUE;
@@ -412,8 +401,8 @@ window_close(GntBindable *bindable, GList *null)
if (wm->_list.window)
return TRUE;
- if (wm->ordered) {
- gnt_widget_destroy(wm->ordered->data);
+ if (wm->cws->ordered) {
+ gnt_widget_destroy(wm->cws->ordered->data);
}
return TRUE;
@@ -426,10 +415,10 @@ help_for_widget(GntBindable *bindable, GList *null)
GntWidget *widget, *tree, *win, *active;
char *title;
- if (!wm->ordered)
+ if (!wm->cws->ordered)
return TRUE;
- widget = wm->ordered->data;
+ widget = wm->cws->ordered->data;
if (!GNT_IS_BOX(widget))
return TRUE;
active = GNT_BOX(widget)->active;
@@ -476,85 +465,126 @@ setup__list(GntWM *wm)
static void
window_list_activate(GntTree *tree, GntWM *wm)
{
- GntWidget *widget = gnt_tree_get_selection_data(GNT_TREE(tree));
+ GntBindable *sel = gnt_tree_get_selection_data(GNT_TREE(tree));
+
+ gnt_widget_destroy(wm->_list.window);
- if (!wm->ordered || !widget)
+ if (!sel)
return;
- gnt_widget_destroy(wm->_list.window);
- gnt_wm_raise_window(wm, widget);
+ if (GNT_IS_WS(sel)) {
+ gnt_wm_switch_workspace(wm, g_list_index(wm->workspaces, sel));
+ } else {
+ GntNode *node = g_hash_table_lookup(wm->nodes, sel);
+ if (node && node->ws != wm->cws)
+ gnt_wm_switch_workspace(wm, g_list_index(wm->workspaces, node->ws));
+ gnt_wm_raise_window(wm, GNT_WIDGET(sel));
+ }
}
static void
-populate_window_list(GntWM *wm)
+populate_window_list(GntWM *wm, gboolean workspace)
{
GList *iter;
GntTree *tree = GNT_TREE(wm->windows->tree);
- for (iter = wm->list; iter; iter = iter->next) {
- GntBox *box = GNT_BOX(iter->data);
+ if (!workspace) {
+ for (iter = wm->cws->list; iter; iter = iter->next) {
+ GntBox *box = GNT_BOX(iter->data);
- gnt_tree_add_row_last(tree, box,
- gnt_tree_create_row(tree, box->title), NULL);
- update_window_in_list(wm, GNT_WIDGET(box));
+ gnt_tree_add_row_last(tree, box,
+ gnt_tree_create_row(tree, box->title), NULL);
+ update_window_in_list(wm, GNT_WIDGET(box));
+ }
+ } else {
+ GList *ws = wm->workspaces;
+ for (; ws; ws = ws->next) {
+ gnt_tree_add_row_last(tree, ws->data,
+ gnt_tree_create_row(tree, gnt_ws_get_name(GNT_WS(ws->data))), NULL);
+ for (iter = GNT_WS(ws->data)->list; iter; iter = iter->next) {
+ GntBox *box = GNT_BOX(iter->data);
+
+ gnt_tree_add_row_last(tree, box,
+ gnt_tree_create_row(tree, box->title), ws->data);
+ update_window_in_list(wm, GNT_WIDGET(box));
+ }
+ }
}
}
static gboolean
window_list_key_pressed(GntWidget *widget, const char *text, GntWM *wm)
{
- if (text[1] == 0 && wm->ordered) {
- GntWidget *sel = gnt_tree_get_selection_data(GNT_TREE(widget));
+ if (text[1] == 0 && wm->cws->ordered) {
+ GntBindable *sel = gnt_tree_get_selection_data(GNT_TREE(widget));
switch (text[0]) {
case '-':
case ',':
- shift_window(wm, sel, -1);
+ if (GNT_IS_WS(sel)) {
+ /* reorder the workspace. */
+ } else
+ shift_window(wm, GNT_WIDGET(sel), -1);
break;
case '=':
case '.':
- shift_window(wm, sel, 1);
+ if (GNT_IS_WS(sel)) {
+ /* reorder the workspace. */
+ } else
+ shift_window(wm, GNT_WIDGET(sel), 1);
break;
default:
return FALSE;
}
gnt_tree_remove_all(GNT_TREE(widget));
- populate_window_list(wm);
+ populate_window_list(wm, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "workspace")));
gnt_tree_set_selected(GNT_TREE(widget), sel);
return TRUE;
}
return FALSE;
}
-static gboolean
-window_list(GntBindable *bindable, GList *null)
+static void
+list_of_windows(GntWM *wm, gboolean workspace)
{
- GntWM *wm = GNT_WM(bindable);
GntWidget *tree, *win;
-
- 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");
+ gnt_box_set_title(GNT_BOX(win), workspace ? "Workspace List" : "Window List");
- populate_window_list(wm);
+ populate_window_list(wm, workspace);
+
+ if (wm->cws->ordered)
+ gnt_tree_set_selected(GNT_TREE(tree), wm->cws->ordered->data);
+ else if (workspace)
+ gnt_tree_set_selected(GNT_TREE(tree), wm->cws);
- gnt_tree_set_selected(GNT_TREE(tree), wm->ordered->data);
g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(window_list_activate), wm);
g_signal_connect(G_OBJECT(tree), "key_pressed", G_CALLBACK(window_list_key_pressed), wm);
+ g_object_set_data(G_OBJECT(tree), "workspace", GINT_TO_POINTER(workspace));
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);
+}
+
+static gboolean
+window_list(GntBindable *bindable, GList *null)
+{
+ GntWM *wm = GNT_WM(bindable);
+
+ if (wm->_list.window || wm->menu)
+ return TRUE;
+
+ if (!wm->cws->ordered)
+ return TRUE;
+
+ list_of_windows(wm, FALSE);
+
return TRUE;
}
@@ -673,7 +703,7 @@ dump_screen(GntBindable *bindable, GList *null)
static void
shift_window(GntWM *wm, GntWidget *widget, int dir)
{
- GList *all = wm->list;
+ GList *all = wm->cws->list;
GList *list = g_list_find(all, widget);
int length, pos;
if (!list)
@@ -693,8 +723,8 @@ shift_window(GntWM *wm, GntWidget *widget, int dir)
all = g_list_insert(all, widget, pos);
all = g_list_delete_link(all, list);
- wm->list = all;
- draw_taskbar(wm, FALSE);
+ wm->cws->list = all;
+ gnt_ws_draw_taskbar(wm->cws, FALSE);
}
static gboolean
@@ -704,7 +734,7 @@ shift_left(GntBindable *bindable, GList *null)
if (wm->_list.window)
return TRUE;
- shift_window(wm, wm->ordered->data, -1);
+ shift_window(wm, wm->cws->ordered->data, -1);
return TRUE;
}
@@ -715,7 +745,7 @@ shift_right(GntBindable *bindable, GList *null)
if (wm->_list.window)
return TRUE;
- shift_window(wm, wm->ordered->data, 1);
+ shift_window(wm, wm->cws->ordered->data, 1);
return TRUE;
}
@@ -839,7 +869,7 @@ window_reverse(GntWidget *win, gboolean set, GntWM *wm)
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));
- copy_win(win, g_hash_table_lookup(wm->nodes, win));
+ gnt_wm_copy_win(win, g_hash_table_lookup(wm->nodes, win));
update_screen(wm);
}
@@ -849,11 +879,11 @@ start_move(GntBindable *bindable, GList *null)
GntWM *wm = GNT_WM(bindable);
if (wm->_list.window || wm->menu)
return TRUE;
- if (!wm->ordered)
+ if (!wm->cws->ordered)
return TRUE;
wm->mode = GNT_KP_MODE_MOVE;
- window_reverse(GNT_WIDGET(wm->ordered->data), TRUE, wm);
+ window_reverse(GNT_WIDGET(wm->cws->ordered->data), TRUE, wm);
return TRUE;
}
@@ -864,11 +894,11 @@ start_resize(GntBindable *bindable, GList *null)
GntWM *wm = GNT_WM(bindable);
if (wm->_list.window || wm->menu)
return TRUE;
- if (!wm->ordered)
+ if (!wm->cws->ordered)
return TRUE;
wm->mode = GNT_KP_MODE_RESIZE;
- window_reverse(GNT_WIDGET(wm->ordered->data), TRUE, wm);
+ window_reverse(GNT_WIDGET(wm->cws->ordered->data), TRUE, wm);
return TRUE;
}
@@ -900,7 +930,7 @@ refresh_screen(GntBindable *bindable, GList *null)
g_hash_table_foreach(wm->nodes, (GHFunc)refresh_node, NULL);
update_screen(wm);
- draw_taskbar(wm, TRUE);
+ gnt_ws_draw_taskbar(wm->cws, TRUE);
return FALSE;
}
@@ -931,6 +961,68 @@ toggle_clipboard(GntBindable *bindable, GList *n)
return TRUE;
}
+static void remove_tag(gpointer wid, gpointer wim)
+{
+ GntWM *wm = GNT_WM(wim);
+ GntWidget *w = GNT_WIDGET(wid);
+ wm->tagged = g_list_remove(wm->tagged, w);
+ mvwhline(w->window, 0, 1, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL), 3);
+ gnt_widget_draw(w);
+}
+
+static gboolean
+tag_widget(GntBindable *b, GList *params)
+{
+ GntWM *wm = GNT_WM(b);
+ GntWidget *widget;
+
+ if (!wm->cws->ordered)
+ return FALSE;
+ widget = wm->cws->ordered->data;
+
+ if (g_list_find(wm->tagged, widget)) {
+ remove_tag(widget, wm);
+ return TRUE;
+ }
+
+ wm->tagged = g_list_prepend(wm->tagged, widget);
+ wbkgdset(widget->window, ' ' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT));
+ mvwprintw(widget->window, 0, 1, "[T]");
+ gnt_widget_draw(widget);
+ return TRUE;
+}
+
+static void
+widget_move_ws(gpointer wid, gpointer w)
+{
+ GntWM *wm = GNT_WM(w);
+ gnt_wm_widget_move_workspace(wm, wm->cws, GNT_WIDGET(wid));
+}
+
+static gboolean
+place_tagged(GntBindable *b, GList *params)
+{
+ GntWM *wm = GNT_WM(b);
+ g_list_foreach(wm->tagged, widget_move_ws, wm);
+ g_list_foreach(wm->tagged, remove_tag, wm);
+ g_list_free(wm->tagged);
+ wm->tagged = NULL;
+ return TRUE;
+}
+
+static gboolean
+workspace_list(GntBindable *b, GList *params)
+{
+ GntWM *wm = GNT_WM(b);
+
+ if (wm->_list.window || wm->menu)
+ return TRUE;
+
+ list_of_windows(wm, TRUE);
+
+ return TRUE;
+}
+
static void
gnt_wm_class_init(GntWMClass *klass)
{
@@ -1065,6 +1157,16 @@ gnt_wm_class_init(GntWMClass *klass)
"\033" GNT_KEY_CTRL_K, NULL);
gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "help-for-widget", help_for_widget,
"\033" "/", NULL);
+ gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "workspace-next", workspace_next,
+ "\033" ">", NULL);
+ gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "workspace-prev", workspace_prev,
+ "\033" "<", NULL);
+ gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-tag", tag_widget,
+ "\033" "t", NULL);
+ gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "place-tagged", place_tagged,
+ "\033" "T", NULL);
+ gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "workspace-list", workspace_list,
+ "\033" "s", NULL);
gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "toggle-clipboard",
toggle_clipboard, "\033" "C", NULL);
@@ -1109,6 +1211,118 @@ gnt_wm_get_gtype(void)
return type;
}
+void
+gnt_wm_add_workspace(GntWM *wm, GntWS *ws)
+{
+ wm->workspaces = g_list_append(wm->workspaces, ws);
+}
+
+gboolean
+gnt_wm_switch_workspace(GntWM *wm, gint n)
+{
+ GntWS *s = g_list_nth_data(wm->workspaces, n);
+ if (!s)
+ return FALSE;
+
+ if (wm->_list.window) {
+ gnt_widget_destroy(wm->_list.window);
+ }
+ gnt_ws_hide(wm->cws, wm->nodes);
+ wm->cws = s;
+ gnt_ws_show(wm->cws, wm->nodes);
+
+ gnt_ws_draw_taskbar(wm->cws, TRUE);
+ update_screen(wm);
+ if (wm->cws->ordered) {
+ gnt_widget_set_focus(wm->cws->ordered->data, TRUE);
+ gnt_wm_raise_window(wm, wm->cws->ordered->data);
+ }
+
+ if (act && g_list_find(act, wm->cws)) {
+ act = g_list_remove(act, wm->cws);
+ update_act_msg();
+ }
+ return TRUE;
+}
+
+gboolean
+gnt_wm_switch_workspace_prev(GntWM *wm)
+{
+ int n = g_list_index(wm->workspaces, wm->cws);
+ return gnt_wm_switch_workspace(wm, --n);
+}
+
+gboolean
+gnt_wm_switch_workspace_next(GntWM *wm)
+{
+ int n = g_list_index(wm->workspaces, wm->cws);
+ return gnt_wm_switch_workspace(wm, ++n);
+}
+
+static gboolean
+workspace_next(GntBindable *wm, GList *n)
+{
+ return gnt_wm_switch_workspace_next(GNT_WM(wm));
+}
+
+static gboolean
+workspace_prev(GntBindable *wm, GList *n)
+{
+ return gnt_wm_switch_workspace_prev(GNT_WM(wm));
+}
+
+void
+gnt_wm_widget_move_workspace(GntWM *wm, GntWS *neww, GntWidget *widget)
+{
+ GntWS *oldw = gnt_wm_widget_find_workspace(wm, widget);
+ GntNode *node;
+ if (!oldw || oldw == neww)
+ return;
+ node = g_hash_table_lookup(wm->nodes, widget);
+ if (node && node->ws == neww)
+ return;
+
+ if (node)
+ node->ws = neww;
+
+ gnt_ws_remove_widget(oldw, widget);
+ gnt_ws_add_widget(neww, widget);
+ if (neww == wm->cws) {
+ gnt_ws_widget_show(widget, wm->nodes);
+ } else {
+ gnt_ws_widget_hide(widget, wm->nodes);
+ }
+}
+
+static gint widget_in_workspace(gconstpointer workspace, gconstpointer wid)
+{
+ GntWS *s = (GntWS *)workspace;
+ if (s->list && g_list_find(s->list, wid))
+ return 0;
+ return 1;
+}
+
+GntWS *gnt_wm_widget_find_workspace(GntWM *wm, GntWidget *widget)
+{
+ GList *l = g_list_find_custom(wm->workspaces, widget, widget_in_workspace);
+ if (l)
+ return l->data;
+ return NULL;
+}
+
+static void free_workspaces(gpointer data, gpointer n)
+{
+ GntWS *s = data;
+ g_free(s->name);
+}
+
+void gnt_wm_set_workspaces(GntWM *wm, GList *workspaces)
+{
+ g_list_foreach(wm->workspaces, free_workspaces, NULL);
+ wm->workspaces = workspaces;
+ gnt_wm_switch_workspace(wm, 0);
+}
+
static void
update_window_in_list(GntWM *wm, GntWidget *wid)
{
@@ -1117,7 +1331,7 @@ update_window_in_list(GntWM *wm, GntWidget *wid)
if (wm->windows == NULL)
return;
- if (wid == wm->ordered->data)
+ if (wm->cws->ordered && wid == wm->cws->ordered->data)
flag |= GNT_TEXT_FLAG_DIM;
else if (GNT_WIDGET_IS_FLAG_SET(wid, GNT_WIDGET_URGENT))
flag |= GNT_TEXT_FLAG_BOLD;
@@ -1125,6 +1339,29 @@ update_window_in_list(GntWM *wm, GntWidget *wid)
gnt_tree_set_row_flags(GNT_TREE(wm->windows->tree), wid, flag);
}
+static gboolean
+match_title(gpointer title, gpointer n, gpointer wid_title)
+{
+ /* maybe check for regex.h? */
+ if (g_strrstr((gchar *)wid_title, (gchar *)title))
+ return TRUE;
+ return FALSE;
+}
+
+static GntWS *
+new_widget_find_workspace(GntWM *wm, GntWidget *widget, gchar *wid_title)
+{
+ GntWS *ret;
+ const gchar *name;
+ ret = g_hash_table_find(wm->title_places, match_title, wid_title);
+ if (ret)
+ return ret;
+ name = gnt_widget_get_name(widget);
+ if (name)
+ ret = g_hash_table_lookup(wm->name_places, name);
+ return ret ? ret : wm->cws;
+}
+
static void
gnt_wm_new_window_real(GntWM *wm, GntWidget *widget)
{
@@ -1171,7 +1408,7 @@ gnt_wm_new_window_real(GntWM *wm, GntWidget *widget)
w = MIN(w, maxx);
h = MIN(h, maxy);
node->window = newwin(h + shadow, w + shadow, y, x);
- copy_win(widget, node);
+ gnt_wm_copy_win(widget, node);
}
#endif
@@ -1179,18 +1416,25 @@ gnt_wm_new_window_real(GntWM *wm, GntWidget *widget)
set_panel_userptr(node->panel, node);
if (!transient) {
+ GntWS *ws = wm->cws;
if (node->me != wm->_list.window) {
GntWidget *w = NULL;
- if (wm->ordered)
- w = wm->ordered->data;
+ if (GNT_IS_BOX(widget)) {
+ char *title = GNT_BOX(widget)->title;
+ ws = new_widget_find_workspace(wm, widget, title);
+ }
- wm->list = g_list_append(wm->list, widget);
+ if (ws->ordered)
+ w = ws->ordered->data;
+
+ node->ws = ws;
+ ws->list = g_list_append(ws->list, widget);
if (wm->event_stack)
- wm->ordered = g_list_prepend(wm->ordered, widget);
+ ws->ordered = g_list_prepend(ws->ordered, widget);
else
- wm->ordered = g_list_append(wm->ordered, widget);
+ ws->ordered = g_list_append(ws->ordered, widget);
gnt_widget_set_focus(widget, TRUE);
if (w)
@@ -1198,10 +1442,14 @@ gnt_wm_new_window_real(GntWM *wm, GntWidget *widget)
}
if (wm->event_stack || node->me == wm->_list.window) {
+ if (wm->cws != ws)
+ gnt_wm_switch_workspace(wm, g_list_index(wm->workspaces, ws));
gnt_wm_raise_window(wm, node->me);
} else {
bottom_panel(node->panel); /* New windows should not grab focus */
gnt_widget_set_urgent(node->me);
+ if (wm->cws != ws)
+ gnt_ws_widget_hide(widget, wm->nodes);
}
}
}
@@ -1235,13 +1483,13 @@ void gnt_wm_new_window(GntWM *wm, GntWidget *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);
+ g_object_get_data(G_OBJECT(wm->windows->tree), "workspace") ? wm->cws : NULL);
update_window_in_list(wm, widget);
}
}
update_screen(wm);
- draw_taskbar(wm, FALSE);
+ gnt_ws_draw_taskbar(wm->cws, FALSE);
}
void gnt_wm_window_decorate(GntWM *wm, GntWidget *widget)
@@ -1251,9 +1499,12 @@ void gnt_wm_window_decorate(GntWM *wm, GntWidget *widget)
void gnt_wm_window_close(GntWM *wm, GntWidget *widget)
{
+ GntWS *s;
GntNode *node;
int pos;
+ s = gnt_wm_widget_find_workspace(wm, widget);
+
if ((node = g_hash_table_lookup(wm->nodes, widget)) == NULL)
return;
@@ -1264,18 +1515,20 @@ void gnt_wm_window_close(GntWM *wm, GntWidget *widget)
gnt_tree_remove(GNT_TREE(wm->windows->tree), widget);
}
- pos = g_list_index(wm->list, widget);
+ if (s) {
+ pos = g_list_index(s->list, widget);
- if (pos != -1) {
- wm->list = g_list_remove(wm->list, widget);
- wm->ordered = g_list_remove(wm->ordered, widget);
+ if (pos != -1) {
+ s->list = g_list_remove(s->list, widget);
+ s->ordered = g_list_remove(s->ordered, widget);
- if (wm->ordered)
- gnt_wm_raise_window(wm, wm->ordered->data);
+ if (s->ordered && wm->cws == s)
+ gnt_wm_raise_window(wm, s->ordered->data);
+ }
}
update_screen(wm);
- draw_taskbar(wm, FALSE);
+ gnt_ws_draw_taskbar(wm->cws, FALSE);
}
time_t gnt_wm_get_idle_time()
@@ -1296,10 +1549,10 @@ gboolean gnt_wm_process_input(GntWM *wm, const char *keys)
}
/* Do some manual checking */
- if (wm->ordered && wm->mode != GNT_KP_MODE_NORMAL) {
+ if (wm->cws->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);
+ GntWidget *widget = GNT_WIDGET(wm->cws->ordered->data);
int ox, oy, ow, oh;
gnt_widget_get_position(widget, &x, &y);
@@ -1375,8 +1628,8 @@ gboolean gnt_wm_process_input(GntWM *wm, const char *keys)
ret = gnt_widget_key_pressed(GNT_WIDGET(wm->menu), keys);
else if (wm->_list.window)
ret = gnt_widget_key_pressed(wm->_list.window, keys);
- else if (wm->ordered)
- ret = gnt_widget_key_pressed(GNT_WIDGET(wm->ordered->data), keys);
+ else if (wm->cws->ordered)
+ ret = gnt_widget_key_pressed(GNT_WIDGET(wm->cws->ordered->data), keys);
return ret;
}
@@ -1510,9 +1763,9 @@ gnt_wm_give_focus(GntWM *wm, GntWidget *widget)
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);
+ wm->cws->ordered->data != widget) {
+ GntWidget *w = wm->cws->ordered->data;
+ wm->cws->ordered = g_list_bring_to_front(wm->cws->ordered, widget);
gnt_widget_set_focus(w, FALSE);
}
@@ -1526,27 +1779,35 @@ gnt_wm_give_focus(GntWM *wm, GntWidget *widget)
top_panel(nd->panel);
}
update_screen(wm);
- draw_taskbar(wm, FALSE);
+ gnt_ws_draw_taskbar(wm->cws, FALSE);
}
void gnt_wm_update_window(GntWM *wm, GntWidget *widget)
{
- GntNode *node;
+ GntNode *node = NULL;
+ GntWS *ws;
while (widget->parent)
widget = widget->parent;
if (!GNT_IS_MENU(widget))
gnt_box_sync_children(GNT_BOX(widget));
+ ws = gnt_wm_widget_find_workspace(wm, 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);
- copy_win(widget, node);
- update_screen(wm);
- draw_taskbar(wm, FALSE);
+ if (ws == wm->cws || GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_TRANSIENT)) {
+ gnt_wm_copy_win(widget, node);
+ update_screen(wm);
+ gnt_ws_draw_taskbar(wm->cws, FALSE);
+ } else if (ws != wm->cws && GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_URGENT)) {
+ if (!act || (act && !g_list_find(act, ws)))
+ act = g_list_prepend(act, ws);
+ update_act_msg();
+ }
}
gboolean gnt_wm_process_click(GntWM *wm, GntMouseEvent event, int x, int y, GntWidget *widget)
diff --git a/finch/libgnt/gntwm.h b/finch/libgnt/gntwm.h
index d1a9393635..0d0bcbbba1 100644
--- a/finch/libgnt/gntwm.h
+++ b/finch/libgnt/gntwm.h
@@ -1,6 +1,9 @@
+#ifndef GNTWM_H
+#define GNTWM_H
#include "gntwidget.h"
#include "gntmenu.h"
+#include "gntws.h"
#include <panel.h>
#include <time.h>
@@ -26,9 +29,11 @@ typedef struct
WINDOW *window;
int scroll;
PANEL *panel;
+
+ GntWS *ws;
} GntNode;
-typedef struct _GnttWM GntWM;
+typedef struct _GntWM GntWM;
typedef struct _GntPosition
{
@@ -45,14 +50,15 @@ typedef struct _GntAction
void (*callback)();
} GntAction;
-struct _GnttWM
+struct _GntWM
{
GntBindable inherit;
GMainLoop *loop;
- GList *list; /* List of windows ordered on their creation time */
- GList *ordered; /* List of windows ordered on their focus */
+ GList *workspaces;
+ GList *tagged; /* tagged windows */
+ GntWS *cws;
struct {
GntWidget *window;
@@ -62,6 +68,8 @@ struct _GnttWM
*actions; /* Action-list window */
GHashTable *nodes; /* GntWidget -> GntNode */
+ GHashTable *name_places; /* window name -> ws*/
+ GHashTable *title_places; /* window title -> ws */
GList *acts; /* List of actions */
@@ -146,6 +154,15 @@ G_BEGIN_DECLS
GType gnt_wm_get_gtype(void);
+void gnt_wm_add_workspace(GntWM *wm, GntWS *ws);
+
+gboolean gnt_wm_switch_workspace(GntWM *wm, gint n);
+gboolean gnt_wm_switch_workspace_prev(GntWM *wm);
+gboolean gnt_wm_switch_workspace_next(GntWM *wm);
+void gnt_wm_widget_move_workspace(GntWM *wm, GntWS *neww, GntWidget *widget);
+void gnt_wm_set_workspaces(GntWM *wm, GList *workspaces);
+GntWS *gnt_wm_widget_find_workspace(GntWM *wm, GntWidget *widget);
+
void gnt_wm_new_window(GntWM *wm, GntWidget *widget);
void gnt_wm_window_decorate(GntWM *wm, GntWidget *widget);
@@ -166,6 +183,10 @@ void gnt_wm_raise_window(GntWM *wm, GntWidget *widget);
void gnt_wm_set_event_stack(GntWM *wm, gboolean set);
+void gnt_wm_copy_win(GntWidget *widget, GntNode *node);
+
time_t gnt_wm_get_idle_time(void);
G_END_DECLS
+
+#endif
diff --git a/finch/libgnt/gntws.c b/finch/libgnt/gntws.c
new file mode 100644
index 0000000000..b886fca9dc
--- /dev/null
+++ b/finch/libgnt/gntws.c
@@ -0,0 +1,158 @@
+#include <gmodule.h>
+
+#include "gntbox.h"
+#include "gntws.h"
+#include "gntwm.h"
+#include "gntwidget.h"
+
+static void
+widget_hide(gpointer data, gpointer nodes)
+{
+ GntWidget *widget = GNT_WIDGET(data);
+ GntNode *node = g_hash_table_lookup(nodes, widget);
+ hide_panel(node->panel);
+}
+
+static void
+widget_show(gpointer data, gpointer nodes)
+{
+ GntNode *node = g_hash_table_lookup(nodes, data);
+ GNT_WIDGET_UNSET_FLAGS(GNT_WIDGET(data), GNT_WIDGET_INVISIBLE);
+ if (node) {
+ show_panel(node->panel);
+ gnt_wm_copy_win(GNT_WIDGET(data), node);
+ }
+}
+
+void
+gnt_ws_draw_taskbar(GntWS *ws, 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(ws->list);
+ if (n)
+ width = getmaxx(stdscr) / n;
+
+ for (i = 0, iter = ws->list; iter; iter = iter->next, i++) {
+ GntWidget *w = iter->data;
+ int color;
+ const char *title;
+
+ if (w == ws->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));
+ if (iter->next)
+ mvwhline(taskbar, 0, width * i, ' ' | COLOR_PAIR(color), width);
+ else
+ mvwhline(taskbar, 0, width * i, ' ' | COLOR_PAIR(color), getmaxx(stdscr) - width * i);
+ 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));
+ }
+ wrefresh(taskbar);
+}
+
+static void
+gnt_ws_init(GTypeInstance *instance, gpointer class)
+{
+ GntWS *ws = GNT_WS(instance);
+ ws->list = NULL;
+ ws->ordered = NULL;
+ ws->name = NULL;
+}
+
+void gnt_ws_add_widget(GntWS *ws, GntWidget* wid)
+{
+ ws->list = g_list_append(ws->list, wid);
+ ws->ordered = g_list_prepend(ws->ordered, wid);
+}
+
+void gnt_ws_remove_widget(GntWS *ws, GntWidget* wid)
+{
+ ws->list = g_list_remove(ws->list, wid);
+ ws->ordered = g_list_remove(ws->ordered, wid);
+}
+
+void
+gnt_ws_set_name(GntWS *ws, const gchar *name)
+{
+ g_free(ws->name);
+ ws->name = g_strdup(name);
+}
+
+void
+gnt_ws_hide(GntWS *ws, GHashTable *nodes)
+{
+ g_list_foreach(ws->ordered, widget_hide, nodes);
+}
+
+void gnt_ws_widget_hide(GntWidget *widget, GHashTable *nodes) {
+ widget_hide(widget, nodes);
+}
+
+void gnt_ws_widget_show(GntWidget *widget, GHashTable *nodes) {
+ widget_show(widget, nodes);
+}
+
+void
+gnt_ws_show(GntWS *ws, GHashTable *nodes)
+{
+ GList *l;
+ for (l = g_list_last(ws->ordered); l; l = g_list_previous(l))
+ widget_show(l->data, nodes);
+}
+
+GType
+gnt_ws_get_gtype(void)
+{
+ static GType type = 0;
+
+ if(type == 0) {
+ static const GTypeInfo info = {
+ sizeof(GntWSClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ NULL,
+ /*(GClassInitFunc)gnt_ws_class_init,*/
+ NULL,
+ NULL, /* class_data */
+ sizeof(GntWS),
+ 0, /* n_preallocs */
+ gnt_ws_init, /* instance_init */
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static(GNT_TYPE_BINDABLE,
+ "GntWS",
+ &info, 0);
+ }
+
+ return type;
+}
+
+const char * gnt_ws_get_name(GntWS *ws)
+{
+ return ws->name;
+}
+
diff --git a/finch/libgnt/gntws.h b/finch/libgnt/gntws.h
new file mode 100644
index 0000000000..bf2d7ea7b0
--- /dev/null
+++ b/finch/libgnt/gntws.h
@@ -0,0 +1,59 @@
+#ifndef GNTWS_H
+#define GNTWS_H
+
+#include "gntwidget.h"
+
+#include <panel.h>
+
+#define GNT_TYPE_WS (gnt_ws_get_gtype())
+#define GNT_WS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_WS, GntWS))
+#define GNT_IS_WS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_WS))
+#define GNT_IS_WS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_WS))
+#define GNT_WS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_WS, GntWSClass))
+
+typedef struct _GntWS GntWS;
+
+struct _GntWS
+{
+ GntBindable inherit;
+ gchar *name;
+ GList *list;
+ GList *ordered;
+ gpointer ui_data;
+
+ void *res1;
+ void *res2;
+ void *res3;
+ void *res4;
+};
+
+typedef struct _GntWSClass GntWSClass;
+
+struct _GntWSClass
+{
+ GntBindableClass parent;
+
+ void (*draw_taskbar)(GntWS *ws, gboolean );
+
+ void (*res1)(void);
+ void (*res2)(void);
+ void (*res3)(void);
+ void (*res4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType gnt_ws_get_gtype(void);
+
+void gnt_ws_set_name(GntWS *, const gchar *);
+void gnt_ws_add_widget(GntWS *, GntWidget *);
+void gnt_ws_remove_widget(GntWS *, GntWidget *);
+void gnt_ws_widget_hide(GntWidget *, GHashTable *nodes);
+void gnt_ws_widget_show(GntWidget *, GHashTable *nodes);
+void gnt_ws_draw_taskbar(GntWS *, gboolean reposition);
+void gnt_ws_hide(GntWS *, GHashTable *);
+void gnt_ws_show(GntWS *, GHashTable *);
+
+const char * gnt_ws_get_name(GntWS *ws);
+
+#endif
diff --git a/finch/libgnt/wms/s.c b/finch/libgnt/wms/s.c
index 490b595c4e..627d31413b 100644
--- a/finch/libgnt/wms/s.c
+++ b/finch/libgnt/wms/s.c
@@ -121,7 +121,7 @@ s_new_window(GntWM *wm, GntWidget *win)
static GntWidget *
find_widget(GntWM *wm, const char *wname)
{
- const GList *iter = wm->list;
+ const GList *iter = wm->cws->list;
for (; iter; iter = iter->next) {
GntWidget *widget = iter->data;
const char *name = gnt_widget_get_name(widget);