soc.2008.finch: 4503fb8e: Added tiling window manager.
queueram at soc.pidgin.im
queueram at soc.pidgin.im
Sun Aug 17 00:12:41 EDT 2008
-----------------------------------------------------------------
Revision: 4503fb8ec936bd202fcbc7a42a0544b438e5b4d3
Ancestor: 87067453980aa21bf2ae667cacf8d8f8760a6e66
Author: queueram at soc.pidgin.im
Date: 2008-08-17T04:01:07
Branch: im.pidgin.soc.2008.finch
URL: http://d.pidgin.im/viewmtn/revision/info/4503fb8ec936bd202fcbc7a42a0544b438e5b4d3
Added files:
finch/libgnt/wms/tiling.c
ChangeLog:
Added tiling window manager.
-------------- next part --------------
============================================================
--- finch/libgnt/wms/tiling.c 063f2edd8838daf35f0420dc21d7b695fff68de6
+++ finch/libgnt/wms/tiling.c 063f2edd8838daf35f0420dc21d7b695fff68de6
@@ -0,0 +1,530 @@
+/**
+ * GNT - The GLib Ncurses Toolkit
+ *
+ * GNT is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ */
+
+/**
+ * Tiling Window Manger
+ * This window manager takes some of the ideas from the default gnt window manager,
+ * as well as X tiling window managers wmii and ratpoison
+ * Specifically, there will be a common mod key, used in conjunction with command
+ * keys to specify actions.
+ * Default Mod key: Mod1 (left-alt)
+ * Command keys:
+ * split screen V/H: s/S
+ * unsplit all: Q
+ * destroy split: D
+ * resize: r
+ * cycle frame to next window: n
+ * cycle frame to previous window: p
+ * move between splits: h,j,k,l,arrows
+ * get list of non-visible windows: v
+ * get list of all windows: w
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "gnt.h"
+#include "gntbox.h"
+#include "gntmenu.h"
+#include "gntstyle.h"
+#include "gntwm.h"
+#include "gntwindow.h"
+#include "gntlabel.h"
+
+#define TYPE_TILING_WM (tiling_wm_get_gtype())
+
+typedef struct _TilingFrame
+{
+ enum {
+ FRAME_SPLIT_NONE,
+ FRAME_SPLIT_V,
+ FRAME_SPLIT_H
+ } type;
+ int width;
+ int height;
+ int x;
+ int y;
+ struct _TilingFrame *left_top;
+ struct _TilingFrame *right_bottom;
+ struct _TilingFrame *parent;
+ struct _TilingFrame *sibling;
+ GntWidget *window;
+} TilingFrame;
+
+typedef struct _TilingWM
+{
+ GntWM inherit;
+ TilingFrame root;
+ TilingFrame *current;
+} TilingWM;
+
+typedef struct _TilingWMClass
+{
+ GntWMClass inherit;
+} TilingWMClass;
+
+GType tiling_wm_get_gtype(void);
+void gntwm_init(GntWM **wm);
+
+static void (*org_new_window)(GntWM *wm, GntWidget *win);
+
+static void
+tiling_wm_new_window(GntWM *wm, GntWidget *win)
+{
+ TilingWM *twm = (TilingWM*)wm;
+ int w, h, x, y;
+
+ if (!GNT_IS_MENU(win) && !GNT_WIDGET_IS_FLAG_SET(win, GNT_WIDGET_TRANSIENT)) {
+ w = twm->current->width;
+ h = twm->current->height;
+ x = twm->current->x;
+ y = twm->current->y;
+ gnt_widget_set_position(win, x, y);
+ gnt_widget_set_size(win, w, h);
+ mvwin(win->window, x, y);
+ if (twm->current->window) {
+ gnt_ws_widget_hide(twm->current->window, wm->nodes);
+ }
+ g_object_set_data(G_OBJECT(twm->current->window), "tiling-visible", GINT_TO_POINTER(0));
+ twm->current->window = win;
+ g_object_set_data(G_OBJECT(win), "tiling-visible", GINT_TO_POINTER(1));
+ org_new_window(wm, win);
+ }
+}
+
+static void
+tiling_wm_window_resized(GntWM *wm, GntNode *node)
+{
+ return;
+}
+
+static gboolean
+tiling_wm_close_window(GntWM *wm, GntWidget *win)
+{
+ return FALSE;
+}
+
+static void
+tiling_wm_update_window(GntWM *wm, GntNode *node)
+{
+ return;
+}
+
+
+static void
+tiling_wm_terminal_refresh(GntWM *wm)
+{
+}
+
+static GntWidget *
+get_next_window(GntWM *wm, GntWidget *win, int direction)
+{
+ GntWidget *w = NULL, *wid = NULL;
+ w = wm->cws->ordered->data;
+ int pos = g_list_index(wm->cws->list, win);
+ int visible = 1;
+
+ /* loop until non-visble window is found, or the entire list has been iterated through */
+ while (visible && wid != win) {
+ pos += direction;
+ if (pos < 0) {
+ wid = g_list_last(wm->cws->list)->data;
+ } else if (pos >= g_list_length(wm->cws->list)) {
+ wid = wm->cws->list->data;
+ } else
+ wid = g_list_nth_data(wm->cws->list, pos);
+ visible = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(wid), "tiling-visible"));
+ }
+
+ return wid;
+}
+
+static gboolean
+twm_next_window(GntBindable *bindable, GList *list)
+{
+ GntWM *wm = GNT_WM(bindable);
+ TilingWM *twm = (TilingWM*)wm;
+ GntWidget *w = NULL, *wid = NULL;
+ int direction = GPOINTER_TO_INT(list->data);
+
+ if (wm->_list.window || wm->menu)
+ return TRUE;
+
+ if (!wm->cws->ordered || !wm->cws->ordered->next)
+ return TRUE;
+
+ w = wm->cws->ordered->data;
+
+ wid = get_next_window(wm, w, direction);
+
+ /* hide previous window */
+ if (twm->current->window) {
+ g_object_set_data(G_OBJECT(twm->current->window), "tiling-visible", GINT_TO_POINTER(0));
+ gnt_ws_widget_hide(twm->current->window, wm->nodes);
+ }
+ twm->current->window = wid;
+ gnt_screen_resize_widget(wid, twm->current->width, twm->current->height);
+ gnt_screen_move_widget(wid, twm->current->x, twm->current->y);
+ /* show new window */
+ g_object_set_data(G_OBJECT(twm->current->window), "tiling-visible", GINT_TO_POINTER(1));
+ gnt_ws_widget_show(twm->current->window, wm->nodes);
+ gnt_wm_raise_window(wm, wid);
+
+ return TRUE;
+}
+
+static gboolean
+twm_split(GntBindable *bindable, GList *list)
+{
+ GntWM *wm = GNT_WM(bindable);
+ TilingWM *twm = (TilingWM*)wm;
+ TilingFrame *lft_top, *rgt_bot;
+ int type = GPOINTER_TO_INT(list->data);
+
+ lft_top = g_new0(TilingFrame, 1);
+ rgt_bot = g_new0(TilingFrame, 1);
+
+ twm->current->type = type;
+ twm->current->left_top = lft_top;
+ twm->current->right_bottom = rgt_bot;
+
+ if (type == FRAME_SPLIT_V) {
+ lft_top->width = rgt_bot->width = twm->current->width;
+ lft_top->height = twm->current->height / 2;
+ rgt_bot->height = twm->current->height - lft_top->height;
+ lft_top->x = rgt_bot->x = twm->current->x;
+ lft_top->y = twm->current->y;
+ rgt_bot->y = lft_top->y + lft_top->height;
+ } else {
+ lft_top->width = twm->current->width / 2;
+ rgt_bot->width = twm->current->width - lft_top->width;
+ lft_top->height = rgt_bot->height = twm->current->height;
+ lft_top->x = twm->current->x;
+ rgt_bot->x = lft_top->x + lft_top->width;
+ lft_top->y = rgt_bot->y = twm->current->y;
+ }
+
+ lft_top->parent = rgt_bot->parent = twm->current;
+ lft_top->left_top = rgt_bot->left_top = NULL;
+ lft_top->right_bottom = rgt_bot->right_bottom = NULL;
+ lft_top->sibling = rgt_bot;
+ rgt_bot->sibling = lft_top;
+ lft_top->type = rgt_bot->type = FRAME_SPLIT_NONE;
+
+ lft_top->window = twm->current->window;
+ rgt_bot->window = get_next_window(wm, lft_top->window, 1);
+ twm->current->window = NULL;
+
+ /* set current frame to the top or left */
+ twm->current = lft_top;
+
+ /* show other window */
+ if (rgt_bot->window) {
+ gnt_screen_resize_widget(rgt_bot->window, rgt_bot->width, rgt_bot->height);
+ gnt_screen_move_widget(rgt_bot->window, rgt_bot->x, rgt_bot->y);
+ g_object_set_data(G_OBJECT(rgt_bot->window), "tiling-visible", GINT_TO_POINTER(1));
+ gnt_ws_widget_show(rgt_bot->window, wm->nodes);
+ }
+
+ gnt_screen_resize_widget(twm->current->window, twm->current->width, twm->current->height);
+ gnt_screen_move_widget(twm->current->window, twm->current->x, twm->current->y);
+
+ return TRUE;
+}
+
+static TilingFrame *
+depth_search(TilingFrame *start)
+{
+ if (start->left_top) {
+ return depth_search(start->left_top);
+ } else {
+ return start;
+ }
+}
+
+static gboolean
+remove_split(GntBindable *bindable, GList *list)
+{
+ GntWM *wm = GNT_WM(bindable);
+ TilingWM *twm = (TilingWM*)wm;
+ TilingFrame *parent, *current, *sibling;
+
+ current = twm->current;
+ /* root doesn't have a sibling */
+ if (current->sibling) {
+ parent = current->parent;
+ sibling = current->sibling;
+ if (sibling->left_top) {
+ /* if the sibling has children, copy the sibling's properties to the parent */
+ if (parent->type == FRAME_SPLIT_V) {
+ if (sibling->type == FRAME_SPLIT_V) {
+ sibling->left_top->height = parent->height / 2;
+ sibling->right_bottom->height = parent->height - sibling->left_top->height;
+ } else {
+ sibling->left_top->height = parent->height;
+ sibling->right_bottom->height = parent->height;
+ }
+ } else {
+ if (sibling->type == FRAME_SPLIT_V) {
+ sibling->left_top->width = parent->width;
+ sibling->right_bottom->width = parent->width;
+ } else {
+ sibling->left_top->width = parent->width / 2;
+ sibling->right_bottom->width = parent->width - sibling->left_top->width;
+ }
+ }
+ parent->type = sibling->type;
+ parent->left_top = sibling->left_top;
+ parent->right_bottom = sibling->right_bottom;
+ twm->current = depth_search(sibling);
+ } else {
+ parent->type = FRAME_SPLIT_NONE;
+ parent->left_top = NULL;
+ parent->right_bottom = NULL;
+ parent->window = twm->current->window;
+ twm->current = parent;
+ }
+
+ gnt_screen_resize_widget(twm->current->window, twm->current->width, twm->current->height);
+ gnt_screen_move_widget(twm->current->window, twm->current->x, twm->current->y);
+ g_free(current);
+ g_free(sibling);
+ }
+
+ return TRUE;
+}
+
+
+static void
+free_tiling_frames(TilingFrame *frame)
+{
+ if (frame) {
+ free_tiling_frames(frame->left_top);
+ free_tiling_frames(frame->right_bottom);
+ g_free(frame);
+ }
+}
+
+
+static gboolean
+remove_all_split(GntBindable *bindable, GList *list)
+{
+ GntWM *wm = GNT_WM(bindable);
+ TilingWM *twm = (TilingWM*)wm;
+
+ /* set the root window to the current window and remove all the children */
+ if (twm->current != &twm->root) {
+ twm->root.window = twm->current->window;
+ twm->current = &twm->root;
+
+ free_tiling_frames(twm->root.left_top);
+ free_tiling_frames(twm->root.right_bottom);
+
+ if (twm->root.window) {
+ gnt_screen_resize_widget(twm->current->window, twm->current->width, twm->current->height);
+ gnt_screen_move_widget(twm->current->window, twm->current->x, twm->current->y);
+ }
+ }
+
+ return TRUE;
+}
+
+static TilingFrame *
+find_parent_with_left(TilingFrame *frame, int type)
+{
+ TilingFrame *find = frame;
+ while (find->parent) {
+ if (find->parent->type == type && find->parent->left_top != find) {
+ return find->parent->left_top;
+ }
+ find = find->parent;
+ }
+
+ return NULL;
+}
+
+static TilingFrame *
+find_parent_with_right(TilingFrame *frame, int type)
+{
+ TilingFrame *find = frame;
+ while (find->parent) {
+ if (find->parent->type == type && find->parent->right_bottom != find) {
+ return find->parent->right_bottom;
+ }
+ find = find->parent;
+ }
+
+ return NULL;
+}
+
+static TilingFrame *
+find_rightmost_child(TilingFrame *frame)
+{
+ TilingFrame *child = frame;
+ while (child->right_bottom) {
+ child = child->right_bottom;
+ }
+
+ return child;
+}
+
+static TilingFrame *
+find_leftmost_child(TilingFrame *frame)
+{
+ TilingFrame *child = frame;
+ while (child->left_top) {
+ child = child->left_top;
+ }
+
+ return child;
+}
+
+static gboolean
+twm_move_left_up(GntBindable *bindable, GList *list)
+{
+ GntWM *wm = GNT_WM(bindable);
+ TilingWM *twm = (TilingWM*)wm;
+ TilingFrame *left;
+ int type = GPOINTER_TO_INT(list->data);
+
+ left = find_parent_with_left(twm->current, type);
+ if (left) {
+ left = find_rightmost_child(left);
+ twm->current = left;
+ if (twm->current->window) {
+ gnt_wm_raise_window(wm, twm->current->window);
+ }
+ }
+
+ return TRUE;
+}
+
+
+static gboolean
+twm_move_right_down(GntBindable *bindable, GList *list)
+{
+ GntWM *wm = GNT_WM(bindable);
+ TilingWM *twm = (TilingWM*)wm;
+ TilingFrame *right;
+ int type = GPOINTER_TO_INT(list->data);
+
+ right = find_parent_with_right(twm->current, type);
+ if (right) {
+ right = find_leftmost_child(right);
+ twm->current = right;
+ if (twm->current->window) {
+ gnt_wm_raise_window(wm, twm->current->window);
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+tiling_wm_class_init(TilingWMClass *klass)
+{
+ GntWMClass *pclass = GNT_WM_CLASS(klass);
+
+ org_new_window = pclass->new_window;
+
+ pclass->new_window = tiling_wm_new_window;
+ pclass->window_resized = tiling_wm_window_resized;
+ pclass->close_window = tiling_wm_close_window;
+ pclass->window_update = tiling_wm_update_window;
+ pclass->terminal_refresh = tiling_wm_terminal_refresh;
+
+ /* moving between windows */
+ gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "next-window",
+ twm_next_window, "\033" "n", GINT_TO_POINTER(1), NULL);
+ gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "prev-window",
+ twm_next_window, "\033" "p", GINT_TO_POINTER(-1), NULL);
+
+ /* splitting frames */
+ gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "split-vertical",
+ twm_split, "\033" "s", GINT_TO_POINTER(FRAME_SPLIT_V), NULL);
+ gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "split-horizontal",
+ twm_split, "\033" "S", GINT_TO_POINTER(FRAME_SPLIT_H), NULL);
+ gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "remove-split",
+ remove_split, "\033" "R", NULL, NULL);
+ gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "remove-all-split",
+ remove_all_split, "\033" "Q", NULL, NULL);
+
+ /* moving between frames */
+ gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "move-left",
+ twm_move_left_up, "\033" "h", GINT_TO_POINTER(FRAME_SPLIT_H), NULL);
+ gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "move-right",
+ twm_move_right_down, "\033" "l", GINT_TO_POINTER(FRAME_SPLIT_H), NULL);
+ gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "move-down",
+ twm_move_right_down, "\033" "j", GINT_TO_POINTER(FRAME_SPLIT_V), NULL);
+ gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "move-up",
+ twm_move_left_up, "\033" "k", GINT_TO_POINTER(FRAME_SPLIT_V), NULL);
+
+ gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
+ GNTDEBUG;
+}
+
+void gntwm_init(GntWM **wm)
+{
+ TilingWM *twm;
+
+ twm = g_object_new(TYPE_TILING_WM, NULL);
+ *wm = GNT_WM(twm);
+
+ twm->root.width = getmaxx(stdscr);
+ twm->root.height = getmaxy(stdscr) - 1;
+ twm->root.x = 0;
+ twm->root.y = 0;
+ twm->root.parent = NULL;
+ twm->root.left_top = NULL;
+ twm->root.right_bottom = NULL;
+ twm->root.sibling = NULL;
+ twm->root.type = FRAME_SPLIT_NONE;
+ twm->current = &twm->root;
+}
+
+GType tiling_wm_get_gtype(void)
+{
+ static GType type = 0;
+
+ if(type == 0) {
+ static const GTypeInfo info = {
+ sizeof(TilingWMClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc)tiling_wm_class_init,
+ NULL,
+ NULL, /* class_data */
+ sizeof(TilingWM),
+ 0, /* n_preallocs */
+ NULL, /* instance_init */
+ NULL
+ };
+
+ type = g_type_register_static(GNT_TYPE_WM,
+ "GntTilingWM",
+ &info, 0);
+ }
+
+ return type;
+}
+
+
More information about the Commits
mailing list