2 * 1. Buddylist is aligned on the left.
3 * 2. The rest of the screen is split into MxN grid for conversation windows.
4 * - M = irssi-split-h in ~/.gntrc:[general]
5 * - N = irssi-split-v in ~/.gntrc:[general]
6 * - Press alt-shift-k/j/l/h to move the selected window to the frame
7 * above/below/left/right of the current frame.
8 * 3. All the other windows are always centered.
12 #include <sys/types.h>
19 #include "gntwindow.h"
22 #define TYPE_IRSSI (irssi_get_gtype())
30 /* This is changed whenever the buddylist is opened/closed or resized. */
34 typedef struct _IrssiClass
39 GType
irssi_get_gtype(void);
40 void gntwm_init(GntWM
**wm
);
42 static void (*org_new_window
)(GntWM
*wm
, GntWidget
*win
);
45 get_xywh_for_frame(Irssi
*irssi
, int hor
, int vert
, int *x
, int *y
, int *w
, int *h
)
47 int width
, height
, rx
, ry
;
49 width
= (getmaxx(stdscr
) - irssi
->buddylistwidth
) / irssi
->horiz
;
50 height
= (getmaxy(stdscr
) - 1) / irssi
->vert
;
52 rx
= irssi
->buddylistwidth
;
59 ry
+= vert
* height
+ 1;
64 *w
= (hor
== irssi
->horiz
- 1) ? (getmaxx(stdscr
) - rx
) : (width
- 1);
67 *h
= (vert
== irssi
->vert
- 1) ? (getmaxy(stdscr
) - 1 - ry
) : (height
- !!vert
);
72 draw_line_separators(Irssi
*irssi
)
78 /* Draw the separator for the buddylist */
79 if (irssi
->buddylistwidth
)
80 mvwvline(stdscr
, 0, irssi
->buddylistwidth
,
81 ACS_VLINE
| COLOR_PAIR(GNT_COLOR_NORMAL
), getmaxy(stdscr
) - 1);
83 /* Now the separators for the conversation windows */
84 width
= (getmaxx(stdscr
) - irssi
->buddylistwidth
) / irssi
->horiz
;
85 height
= (getmaxy(stdscr
) - 1) / irssi
->vert
;
86 for (x
= 1; x
< irssi
->horiz
; x
++) {
87 mvwvline(stdscr
, 0, irssi
->buddylistwidth
+ x
* width
,
88 ACS_VLINE
| COLOR_PAIR(GNT_COLOR_NORMAL
), getmaxy(stdscr
) - 1);
91 for (y
= 1; y
< irssi
->vert
; y
++) {
92 mvwhline(stdscr
, y
* height
, irssi
->buddylistwidth
+ 1, ACS_HLINE
| COLOR_PAIR(GNT_COLOR_NORMAL
),
93 getmaxx(stdscr
) - irssi
->buddylistwidth
);
94 for (x
= 1; x
< irssi
->horiz
; x
++) {
95 mvwaddch(stdscr
, y
* height
, x
* width
+ irssi
->buddylistwidth
, ACS_PLUS
| COLOR_PAIR(GNT_COLOR_NORMAL
));
97 if (irssi
->buddylistwidth
)
98 mvwaddch(stdscr
, y
* height
, irssi
->buddylistwidth
, ACS_LTEE
| COLOR_PAIR(GNT_COLOR_NORMAL
));
103 is_budddylist(GntWidget
*win
)
105 const char *name
= gnt_widget_get_name(win
);
106 if (name
&& strcmp(name
, "buddylist") == 0)
112 remove_border_set_position_size(GntWM
*wm
, GntWidget
*win
, int x
, int y
, int w
, int h
)
114 gnt_box_set_toplevel(GNT_BOX(win
), FALSE
);
115 GNT_WIDGET_SET_FLAGS(win
, GNT_WIDGET_CAN_TAKE_FOCUS
);
117 gnt_widget_set_position(win
, x
, y
);
118 mvwin(win
->window
, y
, x
);
119 gnt_widget_set_size(win
, (w
< 0) ? -1 : w
+ 2, h
+ 2);
123 irssi_new_window(GntWM
*wm
, GntWidget
*win
)
128 name
= gnt_widget_get_name(win
);
129 if (!name
|| !strstr(name
, "conversation-window")) {
130 if (!GNT_IS_MENU(win
) && !GNT_WIDGET_IS_FLAG_SET(win
, GNT_WIDGET_TRANSIENT
)) {
131 if ((!name
|| strcmp(name
, "buddylist"))) {
132 gnt_widget_get_size(win
, &w
, &h
);
133 x
= (getmaxx(stdscr
) - w
) / 2;
134 y
= (getmaxy(stdscr
) - h
) / 2;
135 gnt_widget_set_position(win
, x
, y
);
136 mvwin(win
->window
, y
, x
);
138 remove_border_set_position_size(wm
, win
, 0, 0, -1, getmaxy(stdscr
) - 1);
139 gnt_widget_get_size(win
, &((Irssi
*)wm
)->buddylistwidth
, NULL
);
140 draw_line_separators((Irssi
*)wm
);
143 org_new_window(wm
, win
);
147 /* The window we have here is a conversation window. */
149 /* XXX: There should be some way to remember which frame a conversation window
150 * was in the last time. Perhaps save them in some ~/.gntpositionirssi or some
152 get_xywh_for_frame((Irssi
*)wm
, 0, 0, &x
, &y
, &w
, &h
);
153 remove_border_set_position_size(wm
, win
, x
, y
, w
, h
);
154 org_new_window(wm
, win
);
158 irssi_window_resized(GntWM
*wm
, GntNode
*node
)
160 if (!is_budddylist(node
->me
))
163 gnt_widget_get_size(node
->me
, &((Irssi
*)wm
)->buddylistwidth
, NULL
);
164 draw_line_separators((Irssi
*)wm
);
168 irssi_close_window(GntWM
*wm
, GntWidget
*win
)
170 if (is_budddylist(win
))
171 ((Irssi
*)wm
)->buddylistwidth
= 0;
176 update_conv_window_title(GntNode
*node
)
179 snprintf(title
, sizeof(title
), "%d: %s",
180 GPOINTER_TO_INT(g_object_get_data(G_OBJECT(node
->me
), "irssi-index")) + 1,
181 GNT_BOX(node
->me
)->title
);
182 wbkgdset(node
->window
, '\0' | COLOR_PAIR(gnt_widget_has_focus(node
->me
) ? GNT_COLOR_TITLE
: GNT_COLOR_TITLE_D
));
183 mvwaddstr(node
->window
, 0, 0, title
);
184 if (!gnt_is_refugee()) {
192 irssi_update_window(GntWM
*wm
, GntNode
*node
)
194 GntWidget
*win
= node
->me
;
195 const char *name
= gnt_widget_get_name(win
);
196 if (!name
|| !GNT_IS_BOX(win
) || !strstr(name
, "conversation-window"))
198 g_object_set_data(G_OBJECT(win
), "irssi-index", GINT_TO_POINTER(g_list_index(wm
->cws
->list
, win
)));
199 g_timeout_add(0, (GSourceFunc
)update_conv_window_title
, node
);
203 find_window_position(Irssi
*irssi
, GntWidget
*win
, int *h
, int *v
)
208 gnt_widget_get_position(win
, &x
, &y
);
209 width
= (getmaxx(stdscr
) - irssi
->buddylistwidth
) / irssi
->horiz
;
210 height
= (getmaxy(stdscr
) - 1) / irssi
->vert
;
213 *h
= (x
- irssi
->buddylistwidth
) / width
;
219 move_direction(GntBindable
*bindable
, GList
*list
)
221 GntWM
*wm
= GNT_WM(bindable
);
222 Irssi
*irssi
= (Irssi
*)wm
;
227 if (wm
->cws
->ordered
== NULL
|| is_budddylist(win
= GNT_WIDGET(wm
->cws
->ordered
->data
)))
230 find_window_position(irssi
, win
, &hor
, &vert
);
232 switch (GPOINTER_TO_INT(list
->data
)) {
234 vert
= MAX(0, vert
- 1);
237 vert
= MIN(vert
+ 1, irssi
->vert
- 1);
240 hor
= MIN(hor
+ 1, irssi
->horiz
- 1);
243 hor
= MAX(0, hor
- 1);
246 get_xywh_for_frame(irssi
, hor
, vert
, &x
, &y
, &w
, &h
);
247 gnt_wm_move_window(wm
, win
, x
, y
);
248 gnt_wm_resize_window(wm
, win
, w
, h
);
253 irssi_terminal_refresh(GntWM
*wm
)
255 draw_line_separators((Irssi
*)wm
);
259 irssi_class_init(IrssiClass
*klass
)
261 GntWMClass
*pclass
= GNT_WM_CLASS(klass
);
263 org_new_window
= pclass
->new_window
;
265 pclass
->new_window
= irssi_new_window
;
266 pclass
->window_resized
= irssi_window_resized
;
267 pclass
->close_window
= irssi_close_window
;
268 pclass
->window_update
= irssi_update_window
;
269 pclass
->terminal_refresh
= irssi_terminal_refresh
;
271 gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass
), "move-up", move_direction
,
272 "\033" "K", GINT_TO_POINTER('k'), NULL
);
273 gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass
), "move-down", move_direction
,
274 "\033" "J", GINT_TO_POINTER('j'), NULL
);
275 gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass
), "move-right", move_direction
,
276 "\033" "L", GINT_TO_POINTER('l'), NULL
);
277 gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass
), "move-left", move_direction
,
278 "\033" "H", GINT_TO_POINTER('h'), NULL
);
280 gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass
), GNT_BINDABLE_CLASS(klass
));
284 void gntwm_init(GntWM
**wm
)
289 irssi
= g_object_new(TYPE_IRSSI
, NULL
);
292 style
= gnt_style_get_from_name("irssi", "split-v");
293 irssi
->vert
= style
? atoi(style
) : 1;
296 style
= gnt_style_get_from_name("irssi", "split-h");
297 irssi
->horiz
= style
? atoi(style
) : 1;
300 irssi
->vert
= MAX(irssi
->vert
, 1);
301 irssi
->horiz
= MAX(irssi
->horiz
, 1);
303 irssi
->buddylistwidth
= 0;
306 GType
irssi_get_gtype(void)
308 static GType type
= 0;
311 static const GTypeInfo info
= {
313 NULL
, /* base_init */
314 NULL
, /* base_finalize */
315 (GClassInitFunc
)irssi_class_init
,
317 NULL
, /* class_data */
320 NULL
, /* instance_init */
324 type
= g_type_register_static(GNT_TYPE_WM
,