Mercurial > pidgin.yaz
comparison console/libgnt/gntmain.c @ 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 | 5228f8cf2a6a |
children | 1bd0456fe1c3 |
comparison
equal
deleted
inserted
replaced
14899:a8f92a837590 | 14900:065e7ac30338 |
---|---|
36 * scr_dump, scr_init, scr_restore: for workspaces | 36 * scr_dump, scr_init, scr_restore: for workspaces |
37 * | 37 * |
38 * Need to wattrset for colors to use with PDCurses. | 38 * Need to wattrset for colors to use with PDCurses. |
39 */ | 39 */ |
40 | 40 |
41 /** | 41 static GIOChannel *channel = NULL; |
42 * There can be at most one menu at a time on the screen. | |
43 * If there is a menu being displayed, then all the keystrokes will be sent to | |
44 * the menu until it is closed, either when the user activates a menuitem, or | |
45 * presses Escape to cancel the menu. | |
46 */ | |
47 static GntMenu *menu; | |
48 | |
49 static int lock_focus_list; | |
50 static GList *focus_list; | |
51 static GList *ordered; | |
52 | |
53 static int X_MIN; | |
54 static int X_MAX; | |
55 static int Y_MIN; | |
56 static int Y_MAX; | |
57 | 42 |
58 static gboolean ascii_only; | 43 static gboolean ascii_only; |
59 static gboolean mouse_enabled; | 44 static gboolean mouse_enabled; |
60 | 45 |
61 /** | 46 static void setup_io(); |
62 * 'event_stack' will be set to TRUE when a user-event, ie. a mouse-click | |
63 * or a key-press is being processed. This variable will be used to determine | |
64 * whether to give focus to a new window. | |
65 */ | |
66 static gboolean event_stack; | |
67 | |
68 static GMainLoop *loop; | |
69 | |
70 static struct | |
71 { | |
72 GntWidget *window; | |
73 GntWidget *tree; | |
74 } _list, *window_list, *action_list; | |
75 | |
76 typedef struct | |
77 { | |
78 GntWidget *me; | |
79 | |
80 PANEL *panel; | |
81 } GntNode; | |
82 | |
83 typedef enum | |
84 { | |
85 GNT_KP_MODE_NORMAL, | |
86 GNT_KP_MODE_RESIZE, | |
87 GNT_KP_MODE_MOVE, | |
88 GNT_KP_MODE_MENU, | |
89 GNT_KP_MODE_WINDOW_LIST | |
90 } GntKeyPressMode; | |
91 | |
92 static GHashTable *nodes; | |
93 | |
94 static void free_node(gpointer data); | |
95 static void draw_taskbar(gboolean reposition); | |
96 static void bring_on_top(GntWidget *widget); | |
97 | 47 |
98 static gboolean refresh_screen(); | 48 static gboolean refresh_screen(); |
99 static const GList *list_all_windows(); | 49 |
100 | 50 GntWM *wm; |
101 static void show_actions_list(); | |
102 | |
103 static GntWM wm = | |
104 { | |
105 NULL, /* new_window */ | |
106 NULL, /* close_window */ | |
107 NULL, /* window_resize_confirm */ | |
108 NULL, /* window_resized */ | |
109 NULL, /* window_move_confirm */ | |
110 NULL, /* window_moved */ | |
111 NULL, /* window_update */ | |
112 NULL, /* key_pressed */ | |
113 NULL, /* mouse clicked */ | |
114 bring_on_top, /* give_focus */ | |
115 NULL, /* uninit */ | |
116 list_all_windows, /* window_list */ | |
117 }; | |
118 | |
119 static const GList *list_all_windows() | |
120 { | |
121 return focus_list; | |
122 } | |
123 | |
124 static GList * | |
125 g_list_bring_to_front(GList *list, gpointer data) | |
126 { | |
127 list = g_list_remove(list, data); | |
128 list = g_list_prepend(list, data); | |
129 return list; | |
130 } | |
131 | |
132 static gboolean | |
133 update_screen(gpointer null) | |
134 { | |
135 if (menu) { | |
136 GntMenu *top = menu; | |
137 while (top) { | |
138 GntNode *node = g_hash_table_lookup(nodes, top); | |
139 if (node) | |
140 top_panel(node->panel); | |
141 top = top->submenu; | |
142 } | |
143 } | |
144 update_panels(); | |
145 doupdate(); | |
146 return TRUE; | |
147 } | |
148 | |
149 void gnt_screen_take_focus(GntWidget *widget) | |
150 { | |
151 GntWidget *w = NULL; | |
152 | |
153 if (lock_focus_list) | |
154 return; | |
155 if (g_list_find(focus_list, widget)) | |
156 return; | |
157 | |
158 if (ordered) | |
159 w = ordered->data; | |
160 | |
161 focus_list = g_list_append(focus_list, widget); | |
162 | |
163 if (event_stack) { | |
164 ordered = g_list_prepend(ordered, widget); | |
165 g_object_set_data(G_OBJECT(widget), "give_focus", GINT_TO_POINTER(event_stack)); | |
166 } else | |
167 ordered = g_list_append(ordered, widget); | |
168 | |
169 gnt_widget_set_focus(widget, TRUE); | |
170 if (w) | |
171 gnt_widget_set_focus(w, FALSE); | |
172 draw_taskbar(FALSE); | |
173 } | |
174 | |
175 void gnt_screen_remove_widget(GntWidget *widget) | |
176 { | |
177 int pos = g_list_index(focus_list, widget); | |
178 | |
179 if (lock_focus_list) | |
180 return; | |
181 | |
182 if (pos == -1) | |
183 return; | |
184 | |
185 focus_list = g_list_remove(focus_list, widget); | |
186 ordered = g_list_remove(ordered, widget); | |
187 | |
188 if (ordered) | |
189 { | |
190 wm.give_focus(ordered->data); | |
191 } | |
192 draw_taskbar(FALSE); | |
193 } | |
194 | |
195 static void | |
196 bring_on_top(GntWidget *widget) | |
197 { | |
198 GntNode *node = g_hash_table_lookup(nodes, widget); | |
199 | |
200 if (!node) | |
201 return; | |
202 | |
203 if (ordered->data != widget) { | |
204 GntWidget *w = ordered->data; | |
205 ordered = g_list_bring_to_front(ordered, widget); | |
206 gnt_widget_set_focus(w, FALSE); | |
207 } | |
208 | |
209 gnt_widget_set_focus(widget, TRUE); | |
210 gnt_widget_draw(widget); | |
211 top_panel(node->panel); | |
212 | |
213 if (_list.window) | |
214 { | |
215 GntNode *nd = g_hash_table_lookup(nodes, _list.window); | |
216 top_panel(nd->panel); | |
217 } | |
218 update_screen(NULL); | |
219 draw_taskbar(FALSE); | |
220 } | |
221 | |
222 static void | |
223 update_window_in_list(GntWidget *wid) | |
224 { | |
225 GntTextFormatFlags flag = 0; | |
226 | |
227 if (window_list == NULL) | |
228 return; | |
229 | |
230 if (wid == ordered->data) | |
231 flag |= GNT_TEXT_FLAG_DIM; | |
232 else if (GNT_WIDGET_IS_FLAG_SET(wid, GNT_WIDGET_URGENT)) | |
233 flag |= GNT_TEXT_FLAG_BOLD; | |
234 | |
235 gnt_tree_set_row_flags(GNT_TREE(window_list->tree), wid, flag); | |
236 } | |
237 | |
238 static void | |
239 draw_taskbar(gboolean reposition) | |
240 { | |
241 static WINDOW *taskbar = NULL; | |
242 GList *iter; | |
243 int n, width = 0; | |
244 int i; | |
245 | |
246 if (taskbar == NULL) | |
247 { | |
248 taskbar = newwin(1, getmaxx(stdscr), getmaxy(stdscr) - 1, 0); | |
249 } | |
250 else if (reposition) | |
251 { | |
252 mvwin(taskbar, Y_MAX, 0); | |
253 } | |
254 | |
255 wbkgdset(taskbar, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL)); | |
256 werase(taskbar); | |
257 | |
258 n = g_list_length(focus_list); | |
259 if (n) | |
260 width = getmaxx(stdscr) / n; | |
261 | |
262 for (i = 0, iter = focus_list; iter; iter = iter->next, i++) | |
263 { | |
264 GntWidget *w = iter->data; | |
265 int color; | |
266 const char *title; | |
267 | |
268 if (w == ordered->data) { | |
269 /* This is the current window in focus */ | |
270 color = GNT_COLOR_TITLE; | |
271 GNT_WIDGET_UNSET_FLAGS(w, GNT_WIDGET_URGENT); | |
272 if (wm.window_update) { | |
273 GntNode *node = g_hash_table_lookup(nodes, w); | |
274 wm.window_update(node ? node->panel : NULL, w); | |
275 } | |
276 } else if (GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_URGENT)) { | |
277 /* This is a window with the URGENT hint set */ | |
278 color = GNT_COLOR_URGENT; | |
279 } else { | |
280 color = GNT_COLOR_NORMAL; | |
281 } | |
282 wbkgdset(taskbar, '\0' | COLOR_PAIR(color)); | |
283 mvwhline(taskbar, 0, width * i, ' ' | COLOR_PAIR(color), width); | |
284 title = GNT_BOX(w)->title; | |
285 mvwprintw(taskbar, 0, width * i, "%s", title ? title : "<gnt>"); | |
286 if (i) | |
287 mvwaddch(taskbar, 0, width *i - 1, ACS_VLINE | A_STANDOUT | COLOR_PAIR(GNT_COLOR_NORMAL)); | |
288 | |
289 update_window_in_list(w); | |
290 } | |
291 | |
292 wrefresh(taskbar); | |
293 } | |
294 | |
295 static void | |
296 switch_window(int direction) | |
297 { | |
298 GntWidget *w = NULL, *wid = NULL; | |
299 int pos; | |
300 | |
301 if (!ordered || !ordered->next) | |
302 return; | |
303 | |
304 w = ordered->data; | |
305 pos = g_list_index(focus_list, w); | |
306 pos += direction; | |
307 | |
308 if (pos < 0) | |
309 wid = g_list_last(focus_list)->data; | |
310 else if (pos >= g_list_length(focus_list)) | |
311 wid = focus_list->data; | |
312 else if (pos >= 0) | |
313 wid = g_list_nth_data(focus_list, pos); | |
314 | |
315 ordered = g_list_bring_to_front(ordered, wid); | |
316 | |
317 wm.give_focus(ordered->data); | |
318 | |
319 if (w != wid) | |
320 { | |
321 gnt_widget_set_focus(w, FALSE); | |
322 } | |
323 } | |
324 | |
325 static void | |
326 switch_window_n(int n) | |
327 { | |
328 GntWidget *w = NULL; | |
329 GList *l; | |
330 | |
331 if (!ordered) | |
332 return; | |
333 | |
334 w = ordered->data; | |
335 | |
336 if ((l = g_list_nth(focus_list, n)) != NULL) | |
337 { | |
338 ordered = g_list_bring_to_front(ordered, l->data); | |
339 wm.give_focus(ordered->data); | |
340 } | |
341 | |
342 if (l && w != l->data) | |
343 { | |
344 gnt_widget_set_focus(w, FALSE); | |
345 } | |
346 } | |
347 | |
348 static void | |
349 window_list_activate(GntTree *tree, gpointer null) | |
350 { | |
351 GntWidget *widget = gnt_tree_get_selection_data(GNT_TREE(tree)); | |
352 GntWidget *old = NULL; | |
353 | |
354 if (!ordered || !widget) | |
355 return; | |
356 | |
357 old = ordered->data; | |
358 ordered = g_list_bring_to_front(ordered, widget); | |
359 wm.give_focus(widget); | |
360 | |
361 if (old != widget) | |
362 { | |
363 gnt_widget_set_focus(old, FALSE); | |
364 } | |
365 } | |
366 | |
367 static void | |
368 setup__list() | |
369 { | |
370 GntWidget *tree, *win; | |
371 win = _list.window = gnt_box_new(FALSE, FALSE); | |
372 gnt_box_set_toplevel(GNT_BOX(win), TRUE); | |
373 gnt_box_set_pad(GNT_BOX(win), 0); | |
374 | |
375 tree = _list.tree = gnt_tree_new(); | |
376 gnt_box_add_widget(GNT_BOX(win), tree); | |
377 } | |
378 | |
379 static void | |
380 show_window_list() | |
381 { | |
382 GntWidget *tree, *win; | |
383 GList *iter; | |
384 | |
385 if (window_list) | |
386 return; | |
387 | |
388 setup__list(); | |
389 | |
390 window_list = &_list; | |
391 | |
392 win = window_list->window; | |
393 tree = window_list->tree; | |
394 | |
395 gnt_box_set_title(GNT_BOX(win), "Window List"); | |
396 | |
397 for (iter = focus_list; iter; iter = iter->next) | |
398 { | |
399 GntBox *box = GNT_BOX(iter->data); | |
400 | |
401 gnt_tree_add_row_last(GNT_TREE(tree), box, | |
402 gnt_tree_create_row(GNT_TREE(tree), box->title), NULL); | |
403 update_window_in_list(GNT_WIDGET(box)); | |
404 } | |
405 | |
406 gnt_tree_set_selected(GNT_TREE(tree), ordered->data); | |
407 g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(window_list_activate), NULL); | |
408 | |
409 gnt_tree_set_col_width(GNT_TREE(tree), 0, getmaxx(stdscr) / 3); | |
410 gnt_widget_set_size(tree, 0, getmaxy(stdscr) / 2); | |
411 gnt_widget_set_position(win, getmaxx(stdscr) / 3, getmaxy(stdscr) / 4); | |
412 | |
413 lock_focus_list = 1; | |
414 gnt_widget_show(win); | |
415 lock_focus_list = 0; | |
416 } | |
417 | |
418 static void | |
419 shift_window(GntWidget *widget, int dir) | |
420 { | |
421 GList *all = focus_list; | |
422 GList *list = g_list_find(all, widget); | |
423 int length, pos; | |
424 if (!list) | |
425 return; | |
426 | |
427 length = g_list_length(all); | |
428 pos = g_list_position(all, list); | |
429 | |
430 pos += dir; | |
431 if (dir > 0) | |
432 pos++; | |
433 | |
434 if (pos < 0) | |
435 pos = length; | |
436 else if (pos > length) | |
437 pos = 0; | |
438 | |
439 all = g_list_insert(all, widget, pos); | |
440 all = g_list_delete_link(all, list); | |
441 focus_list = all; | |
442 draw_taskbar(FALSE); | |
443 } | |
444 | |
445 static void | |
446 dump_screen() | |
447 { | |
448 int x, y; | |
449 chtype old = 0, now = 0; | |
450 FILE *file = fopen("dump.html", "w"); | |
451 | |
452 fprintf(file, "<pre>"); | |
453 for (y = 0; y < getmaxy(stdscr); y++) | |
454 { | |
455 for (x = 0; x < getmaxx(stdscr); x++) | |
456 { | |
457 char ch; | |
458 now = mvwinch(curscr, y, x); | |
459 ch = now & A_CHARTEXT; | |
460 now ^= ch; | |
461 | |
462 #define CHECK(attr, start, end) \ | |
463 do \ | |
464 { \ | |
465 if (now & attr) \ | |
466 { \ | |
467 if (!(old & attr)) \ | |
468 fprintf(file, start); \ | |
469 } \ | |
470 else if (old & attr) \ | |
471 { \ | |
472 fprintf(file, end); \ | |
473 } \ | |
474 } while (0) | |
475 | |
476 CHECK(A_BOLD, "<b>", "</b>"); | |
477 CHECK(A_UNDERLINE, "<u>", "</u>"); | |
478 CHECK(A_BLINK, "<blink>", "</blink>"); | |
479 | |
480 if ((now & A_COLOR) != (old & A_COLOR) || | |
481 (now & A_REVERSE) != (old & A_REVERSE)) | |
482 { | |
483 int ret; | |
484 short fgp, bgp, r, g, b; | |
485 struct | |
486 { | |
487 int r, g, b; | |
488 } fg, bg; | |
489 | |
490 ret = pair_content(PAIR_NUMBER(now & A_COLOR), &fgp, &bgp); | |
491 if (fgp == -1) | |
492 fgp = COLOR_BLACK; | |
493 if (bgp == -1) | |
494 bgp = COLOR_WHITE; | |
495 if (now & A_REVERSE) | |
496 fgp ^= bgp ^= fgp ^= bgp; /* *wink* */ | |
497 ret = color_content(fgp, &r, &g, &b); | |
498 fg.r = r; fg.b = b; fg.g = g; | |
499 ret = color_content(bgp, &r, &g, &b); | |
500 bg.r = r; bg.b = b; bg.g = g; | |
501 #define ADJUST(x) (x = x * 255 / 1000) | |
502 ADJUST(fg.r); | |
503 ADJUST(fg.g); | |
504 ADJUST(fg.b); | |
505 ADJUST(bg.r); | |
506 ADJUST(bg.b); | |
507 ADJUST(bg.g); | |
508 | |
509 if (x) fprintf(file, "</span>"); | |
510 fprintf(file, "<span style=\"background:#%02x%02x%02x;color:#%02x%02x%02x\">", | |
511 bg.r, bg.g, bg.b, fg.r, fg.g, fg.b); | |
512 } | |
513 if (now & A_ALTCHARSET) | |
514 { | |
515 switch (ch) | |
516 { | |
517 case 'q': | |
518 ch = '-'; break; | |
519 case 't': | |
520 case 'u': | |
521 case 'x': | |
522 ch = '|'; break; | |
523 case 'v': | |
524 case 'w': | |
525 case 'l': | |
526 case 'm': | |
527 case 'k': | |
528 case 'j': | |
529 case 'n': | |
530 ch = '+'; break; | |
531 case '-': | |
532 ch = '^'; break; | |
533 case '.': | |
534 ch = 'v'; break; | |
535 case 'a': | |
536 ch = '#'; break; | |
537 default: | |
538 ch = ' '; break; | |
539 } | |
540 } | |
541 if (ch == '&') | |
542 fprintf(file, "&"); | |
543 else if (ch == '<') | |
544 fprintf(file, "<"); | |
545 else if (ch == '>') | |
546 fprintf(file, ">"); | |
547 else | |
548 fprintf(file, "%c", ch); | |
549 old = now; | |
550 } | |
551 fprintf(file, "</span>\n"); | |
552 old = 0; | |
553 } | |
554 fprintf(file, "</pre>"); | |
555 fclose(file); | |
556 } | |
557 | |
558 static void | |
559 refresh_node(GntWidget *widget, GntNode *node, gpointer null) | |
560 { | |
561 int x, y, w, h; | |
562 int nw, nh; | |
563 | |
564 gnt_widget_get_position(widget, &x, &y); | |
565 gnt_widget_get_size(widget, &w, &h); | |
566 | |
567 if (x + w >= X_MAX) | |
568 x = MAX(0, X_MAX - w); | |
569 if (y + h >= Y_MAX) | |
570 y = MAX(0, Y_MAX - h); | |
571 gnt_screen_move_widget(widget, x, y); | |
572 | |
573 nw = MIN(w, X_MAX); | |
574 nh = MIN(h, Y_MAX); | |
575 if (nw != w || nh != h) | |
576 gnt_screen_resize_widget(widget, nw, nh); | |
577 } | |
578 | 51 |
579 /** | 52 /** |
580 * Mouse support: | 53 * Mouse support: |
581 * - bring a window on top if you click on its taskbar | 54 * - bring a window on top if you click on its taskbar |
582 * - click on the top-bar of the active window and drag+drop to move a window | 55 * - click on the top-bar of the active window and drag+drop to move a window |
600 static int offset = 0; | 73 static int offset = 0; |
601 GntMouseEvent event; | 74 GntMouseEvent event; |
602 GntWidget *widget = NULL; | 75 GntWidget *widget = NULL; |
603 PANEL *p = NULL; | 76 PANEL *p = NULL; |
604 | 77 |
605 if (!ordered || buffer[0] != 27) | 78 if (!wm->ordered || buffer[0] != 27) |
606 return FALSE; | 79 return FALSE; |
607 | 80 |
608 buffer++; | 81 buffer++; |
609 if (strlen(buffer) < 5) | 82 if (strlen(buffer) < 5) |
610 return FALSE; | 83 return FALSE; |
651 /* button up */ | 124 /* button up */ |
652 event = GNT_MOUSE_UP; | 125 event = GNT_MOUSE_UP; |
653 } else | 126 } else |
654 return FALSE; | 127 return FALSE; |
655 | 128 |
656 if (wm.mouse_clicked && wm.mouse_clicked(event, x, y, widget)) | 129 if (gnt_wm_process_click(wm, event, x, y, widget)) |
657 return TRUE; | 130 return TRUE; |
658 | 131 |
659 if (event == GNT_LEFT_MOUSE_DOWN && widget && widget != _list.window && | 132 if (event == GNT_LEFT_MOUSE_DOWN && widget && widget != wm->_list.window && |
660 !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_TRANSIENT)) { | 133 !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_TRANSIENT)) { |
661 if (widget != ordered->data) { | 134 if (widget != wm->ordered->data) { |
662 GntWidget *w = ordered->data; | 135 gnt_wm_raise_window(wm, widget); |
663 ordered = g_list_bring_to_front(ordered, widget); | |
664 wm.give_focus(ordered->data); | |
665 gnt_widget_set_focus(w, FALSE); | |
666 } | 136 } |
667 if (y == widget->priv.y) { | 137 if (y == widget->priv.y) { |
668 offset = x - widget->priv.x; | 138 offset = x - widget->priv.x; |
669 remember = widget; | 139 remember = widget; |
670 button = MOUSE_LEFT; | 140 button = MOUSE_LEFT; |
671 } | 141 } |
672 } else if (event == GNT_MOUSE_UP) { | 142 } else if (event == GNT_MOUSE_UP) { |
673 if (button == MOUSE_NONE && y == getmaxy(stdscr) - 1) { | 143 if (button == MOUSE_NONE && y == getmaxy(stdscr) - 1) { |
674 /* Clicked on the taskbar */ | 144 /* Clicked on the taskbar */ |
675 int n = g_list_length(focus_list); | 145 int n = g_list_length(wm->list); |
676 if (n) { | 146 if (n) { |
677 int width = getmaxx(stdscr) / n; | 147 int width = getmaxx(stdscr) / n; |
678 switch_window_n(x / width); | 148 gnt_bindable_perform_action_named(GNT_BINDABLE(wm), "switch-window-n", x/width, NULL); |
679 } | 149 } |
680 } else if (button == MOUSE_LEFT && remember) { | 150 } else if (button == MOUSE_LEFT && remember) { |
681 x -= offset; | 151 x -= offset; |
682 if (x < 0) x = 0; | 152 if (x < 0) x = 0; |
683 if (y < 0) y = 0; | 153 if (y < 0) y = 0; |
684 gnt_screen_move_widget(remember, x, y); | 154 gnt_screen_move_widget(remember, x, y); |
685 refresh_node(remember, NULL, NULL); | |
686 } | 155 } |
687 button = MOUSE_NONE; | 156 button = MOUSE_NONE; |
688 remember = NULL; | 157 remember = NULL; |
689 offset = 0; | 158 offset = 0; |
690 } | 159 } |
691 | 160 |
692 gnt_widget_clicked(widget, event, x, y); | 161 gnt_widget_clicked(widget, event, x, y); |
693 return TRUE; /* XXX: this should be TRUE */ | 162 return TRUE; |
694 } | 163 } |
695 | 164 |
696 #ifndef NO_WIDECHAR | 165 static gboolean |
697 static int | 166 io_invoke_error(GIOChannel *source, GIOCondition cond, gpointer data) |
698 widestringwidth(wchar_t *wide) | 167 { |
699 { | 168 int id = GPOINTER_TO_INT(data); |
700 int len, ret; | 169 g_source_remove(id); |
701 char *string; | 170 g_io_channel_unref(source); |
702 | 171 |
703 len = wcstombs(NULL, wide, 0) + 1; | 172 channel = NULL; |
704 string = g_new0(char, len); | 173 setup_io(); |
705 wcstombs(string, wide, len); | 174 return TRUE; |
706 ret = gnt_util_onscreen_width(string, NULL); | |
707 g_free(string); | |
708 return ret; | |
709 } | |
710 #endif | |
711 | |
712 /* Returns the onscreen width of the character at the position */ | |
713 static int | |
714 reverse_char(WINDOW *d, int y, int x, gboolean set) | |
715 { | |
716 #define DECIDE(ch) (set ? ((ch) | A_REVERSE) : ((ch) & ~A_REVERSE)) | |
717 | |
718 #ifdef NO_WIDECHAR | |
719 chtype ch; | |
720 ch = mvwinch(d, y, x); | |
721 mvwaddch(d, y, x, DECIDE(ch)); | |
722 return 1; | |
723 #else | |
724 cchar_t ch; | |
725 int wc = 1; | |
726 if (mvwin_wch(d, y, x, &ch) == OK) { | |
727 wc = widestringwidth(ch.chars); | |
728 ch.attr = DECIDE(ch.attr); | |
729 ch.attr &= WA_ATTRIBUTES; /* XXX: This is a workaround for a bug */ | |
730 mvwadd_wch(d, y, x, &ch); | |
731 } | |
732 | |
733 return wc; | |
734 #endif | |
735 } | |
736 | |
737 static void | |
738 window_reverse(GntWidget *win, gboolean set) | |
739 { | |
740 int i; | |
741 int w, h; | |
742 WINDOW *d; | |
743 | |
744 if (GNT_WIDGET_IS_FLAG_SET(win, GNT_WIDGET_NO_BORDER)) | |
745 return; | |
746 | |
747 d = win->window; | |
748 gnt_widget_get_size(win, &w, &h); | |
749 | |
750 if (gnt_widget_has_shadow(win)) { | |
751 --w; | |
752 --h; | |
753 } | |
754 | |
755 /* the top and bottom */ | |
756 for (i = 0; i < w; i += reverse_char(d, 0, i, set)); | |
757 for (i = 0; i < w; i += reverse_char(d, h-1, i, set)); | |
758 | |
759 /* the left and right */ | |
760 for (i = 0; i < h; i += reverse_char(d, i, 0, set)); | |
761 for (i = 0; i < h; i += reverse_char(d, i, w-1, set)); | |
762 | |
763 wrefresh(win->window); | |
764 } | 175 } |
765 | 176 |
766 static gboolean | 177 static gboolean |
767 io_invoke(GIOChannel *source, GIOCondition cond, gpointer null) | 178 io_invoke(GIOChannel *source, GIOCondition cond, gpointer null) |
768 { | 179 { |
769 char keys[256]; | 180 char keys[256]; |
770 gboolean ret = FALSE; | |
771 static GntKeyPressMode mode = GNT_KP_MODE_NORMAL; | |
772 const char *buffer; | |
773 | |
774 int rd = read(STDIN_FILENO, keys, sizeof(keys) - 1); | 181 int rd = read(STDIN_FILENO, keys, sizeof(keys) - 1); |
775 if (rd < 0) | 182 if (rd < 0) |
776 { | 183 { |
777 int ch = getch(); /* This should return ERR, but let's see what it really returns */ | 184 int ch = getch(); /* This should return ERR, but let's see what it really returns */ |
778 endwin(); | 185 endwin(); |
785 endwin(); | 192 endwin(); |
786 printf("EOF\n"); | 193 printf("EOF\n"); |
787 raise(SIGABRT); | 194 raise(SIGABRT); |
788 } | 195 } |
789 | 196 |
790 event_stack = TRUE; | |
791 keys[rd] = 0; | 197 keys[rd] = 0; |
792 | |
793 if (keys[0] == 27 && keys[1] == 'd' && keys[2] == 0) | |
794 { | |
795 /* This dumps the screen contents in an html file */ | |
796 dump_screen(); | |
797 } | |
798 | |
799 gnt_keys_refine(keys); | 198 gnt_keys_refine(keys); |
800 | 199 |
801 if (mouse_enabled && detect_mouse_action(keys)) | 200 if (mouse_enabled && detect_mouse_action(keys)) |
802 return TRUE; | 201 return TRUE; |
803 | 202 |
804 if (wm.key_pressed) { | 203 gnt_wm_process_input(wm, keys); |
805 buffer = wm.key_pressed(keys); | 204 |
806 if (buffer == NULL) { | |
807 event_stack = FALSE; | |
808 return TRUE; | |
809 } | |
810 } else | |
811 buffer = keys; | |
812 | |
813 if (mode == GNT_KP_MODE_NORMAL) | |
814 { | |
815 if (menu) { | |
816 ret = gnt_widget_key_pressed(GNT_WIDGET(menu), buffer); | |
817 } else if (ordered) { | |
818 ret = gnt_widget_key_pressed(ordered->data, buffer); | |
819 } | |
820 | |
821 if (!ret) | |
822 { | |
823 if (buffer[0] == 27) | |
824 { | |
825 /* Some special key has been pressed */ | |
826 if (strcmp(buffer, GNT_KEY_POPUP) == 0) | |
827 {} | |
828 else if (strcmp(buffer + 1, "c") == 0) | |
829 { | |
830 /* Alt + c was pressed. I am going to use it to close a window. */ | |
831 if (ordered) | |
832 { | |
833 gnt_widget_destroy(ordered->data); | |
834 } | |
835 } | |
836 else if (strcmp(buffer + 1, "q") == 0) | |
837 { | |
838 /* I am going to use Alt + q to quit. */ | |
839 g_main_loop_quit(loop); | |
840 } | |
841 else if (strcmp(buffer + 1, "n") == 0) | |
842 { | |
843 /* Alt + n to go to the next window */ | |
844 switch_window(1); | |
845 } | |
846 else if (strcmp(buffer + 1, "p") == 0) | |
847 { | |
848 /* Alt + p to go to the previous window */ | |
849 switch_window(-1); | |
850 } | |
851 else if (strcmp(buffer + 1, "m") == 0 && focus_list) | |
852 { | |
853 /* Move a window */ | |
854 mode = GNT_KP_MODE_MOVE; | |
855 window_reverse(ordered->data, TRUE); | |
856 } | |
857 else if (strcmp(buffer + 1, "w") == 0 && focus_list) | |
858 { | |
859 /* Window list */ | |
860 mode = GNT_KP_MODE_WINDOW_LIST; | |
861 show_window_list(); | |
862 } | |
863 else if (strcmp(buffer + 1, "a") == 0) | |
864 { | |
865 mode = GNT_KP_MODE_WINDOW_LIST; | |
866 show_actions_list(); | |
867 } | |
868 else if (strcmp(buffer + 1, "r") == 0 && focus_list) | |
869 { | |
870 /* Resize window */ | |
871 mode = GNT_KP_MODE_RESIZE; | |
872 window_reverse(ordered->data, TRUE); | |
873 } | |
874 else if (strcmp(buffer + 1, ",") == 0 && focus_list) | |
875 { | |
876 /* Re-order the list of windows */ | |
877 shift_window(ordered->data, -1); | |
878 } | |
879 else if (strcmp(buffer + 1, ".") == 0 && focus_list) | |
880 { | |
881 shift_window(ordered->data, 1); | |
882 } | |
883 else if (strcmp(buffer + 1, "l") == 0) | |
884 { | |
885 refresh_screen(); | |
886 } | |
887 else if (strlen(buffer) == 2 && isdigit(*(buffer + 1))) | |
888 { | |
889 int n = *(buffer + 1) - '0'; | |
890 | |
891 if (n == 0) | |
892 n = 10; | |
893 | |
894 switch_window_n(n - 1); | |
895 } | |
896 } | |
897 } | |
898 } | |
899 else if (mode == GNT_KP_MODE_MOVE && focus_list) | |
900 { | |
901 if (buffer[0] == 27) | |
902 { | |
903 gboolean changed = FALSE; | |
904 int x, y, w, h; | |
905 GntWidget *widget = GNT_WIDGET(ordered->data); | |
906 | |
907 gnt_widget_get_position(widget, &x, &y); | |
908 gnt_widget_get_size(widget, &w, &h); | |
909 | |
910 if (strcmp(buffer, GNT_KEY_LEFT) == 0) | |
911 { | |
912 if (x > X_MIN) | |
913 { | |
914 x--; | |
915 changed = TRUE; | |
916 } | |
917 } | |
918 else if (strcmp(buffer, GNT_KEY_RIGHT) == 0) | |
919 { | |
920 if (x + w < X_MAX) | |
921 { | |
922 x++; | |
923 changed = TRUE; | |
924 } | |
925 } | |
926 else if (strcmp(buffer, GNT_KEY_UP) == 0) | |
927 { | |
928 if (y > Y_MIN) | |
929 { | |
930 y--; | |
931 changed = TRUE; | |
932 } | |
933 } | |
934 else if (strcmp(buffer, GNT_KEY_DOWN) == 0) | |
935 { | |
936 if (y + h < Y_MAX) | |
937 { | |
938 y++; | |
939 changed = TRUE; | |
940 } | |
941 } | |
942 else if (buffer[1] == 0) | |
943 { | |
944 mode = GNT_KP_MODE_NORMAL; | |
945 window_reverse(widget, FALSE); | |
946 } | |
947 | |
948 if (changed) | |
949 { | |
950 gnt_screen_move_widget(widget, x, y); | |
951 } | |
952 } | |
953 else if (*buffer == '\r') | |
954 { | |
955 mode = GNT_KP_MODE_NORMAL; | |
956 window_reverse(ordered->data, FALSE); | |
957 } | |
958 } | |
959 else if (mode == GNT_KP_MODE_WINDOW_LIST && _list.window) | |
960 { | |
961 gnt_widget_key_pressed(_list.window, buffer); | |
962 | |
963 if (buffer[0] == '\r' || (buffer[0] == 27 && buffer[1] == 0)) | |
964 { | |
965 mode = GNT_KP_MODE_NORMAL; | |
966 lock_focus_list = 1; | |
967 gnt_widget_destroy(_list.window); | |
968 _list.window = NULL; | |
969 _list.tree = NULL; | |
970 lock_focus_list = 0; | |
971 window_list = NULL; | |
972 action_list = NULL; | |
973 } | |
974 } | |
975 else if (mode == GNT_KP_MODE_RESIZE) | |
976 { | |
977 if (buffer[0] == '\r' || (buffer[0] == 27 && buffer[1] == 0)) { | |
978 mode = GNT_KP_MODE_NORMAL; | |
979 window_reverse(ordered->data, FALSE); | |
980 } else if (buffer[0] == 27) { | |
981 GntWidget *widget = ordered->data; | |
982 gboolean changed = FALSE; | |
983 int width, height; | |
984 | |
985 gnt_widget_get_size(widget, &width, &height); | |
986 | |
987 if (strcmp(buffer, GNT_KEY_DOWN) == 0) | |
988 { | |
989 if (widget->priv.y + height < Y_MAX) | |
990 { | |
991 height++; | |
992 changed = TRUE; | |
993 } | |
994 } | |
995 else if (strcmp(buffer, GNT_KEY_UP) == 0) | |
996 { | |
997 height--; | |
998 changed = TRUE; | |
999 } | |
1000 else if (strcmp(buffer, GNT_KEY_LEFT) == 0) | |
1001 { | |
1002 width--; | |
1003 changed = TRUE; | |
1004 } | |
1005 else if (strcmp(buffer, GNT_KEY_RIGHT) == 0) | |
1006 { | |
1007 if (widget->priv.x + width < X_MAX) | |
1008 { | |
1009 width++; | |
1010 changed = TRUE; | |
1011 } | |
1012 } | |
1013 | |
1014 if (changed) | |
1015 { | |
1016 gnt_screen_resize_widget(widget, width, height); | |
1017 window_reverse(widget, TRUE); | |
1018 } | |
1019 } | |
1020 } | |
1021 | |
1022 event_stack = FALSE; | |
1023 return TRUE; | 205 return TRUE; |
206 } | |
207 | |
208 static void | |
209 setup_io() | |
210 { | |
211 int result; | |
212 channel = g_io_channel_unix_new(STDIN_FILENO); | |
213 | |
214 g_io_channel_set_encoding(channel, NULL, NULL); | |
215 g_io_channel_set_buffered(channel, FALSE); | |
216 #if 0 | |
217 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL ); | |
218 #endif | |
219 | |
220 result = g_io_add_watch_full(channel, G_PRIORITY_HIGH, | |
221 (G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI), | |
222 io_invoke, NULL, NULL); | |
223 | |
224 g_io_add_watch_full(channel, G_PRIORITY_HIGH, | |
225 (G_IO_NVAL), | |
226 io_invoke_error, GINT_TO_POINTER(result), NULL); | |
227 | |
228 g_io_channel_unref(channel); /* Apparently this caused crashes for some people. | |
229 But irssi does this, so I am going to assume the | |
230 crashes were caused by some other stuff. */ | |
231 | |
232 g_printerr("gntmain: setting up IO\n"); | |
1024 } | 233 } |
1025 | 234 |
1026 static gboolean | 235 static gboolean |
1027 refresh_screen() | 236 refresh_screen() |
1028 { | 237 { |
1029 endwin(); | 238 gnt_bindable_perform_action_named(GNT_BINDABLE(wm), "refresh-screen", NULL); |
1030 refresh(); | |
1031 | |
1032 X_MAX = getmaxx(stdscr); | |
1033 Y_MAX = getmaxy(stdscr) - 1; | |
1034 | |
1035 g_hash_table_foreach(nodes, (GHFunc)refresh_node, NULL); | |
1036 update_screen(NULL); | |
1037 draw_taskbar(TRUE); | |
1038 | |
1039 return FALSE; | 239 return FALSE; |
1040 } | 240 } |
1041 | 241 |
1042 /* Xerox */ | 242 /* Xerox */ |
1043 static void | 243 static void |
1080 init_wm() | 280 init_wm() |
1081 { | 281 { |
1082 const char *name = gnt_style_get(GNT_STYLE_WM); | 282 const char *name = gnt_style_get(GNT_STYLE_WM); |
1083 gpointer handle; | 283 gpointer handle; |
1084 | 284 |
1085 if (!name || !*name) | 285 if (name && *name) { |
1086 return; | 286 handle = g_module_open(name, G_MODULE_BIND_LAZY); |
1087 | 287 if (handle) { |
1088 handle = g_module_open(name, G_MODULE_BIND_LAZY); | 288 gboolean (*init)(GntWM **); |
1089 if (handle) { | 289 if (g_module_symbol(handle, "gntwm_init", (gpointer)&init)) { |
1090 gboolean (*init)(GntWM *); | 290 init(&wm); |
1091 if (g_module_symbol(handle, "gntwm_init", (gpointer)&init)) { | 291 } |
1092 init(&wm); | |
1093 } | 292 } |
1094 } | 293 } |
294 if (wm == NULL) | |
295 wm = g_object_new(GNT_TYPE_WM, NULL); | |
1095 } | 296 } |
1096 | 297 |
1097 void gnt_init() | 298 void gnt_init() |
1098 { | 299 { |
1099 static GIOChannel *channel = NULL; | |
1100 char *filename; | 300 char *filename; |
1101 int result; | |
1102 const char *locale; | 301 const char *locale; |
1103 | 302 |
1104 if (channel) | 303 if (channel) |
1105 return; | 304 return; |
1106 | 305 |
1107 channel = g_io_channel_unix_new(STDIN_FILENO); | 306 setup_io(); |
1108 | |
1109 g_io_channel_set_encoding(channel, NULL, NULL); | |
1110 g_io_channel_set_buffered(channel, FALSE); | |
1111 #if 0 | |
1112 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL ); | |
1113 #endif | |
1114 | |
1115 result = g_io_add_watch_full(channel, G_PRIORITY_HIGH, | |
1116 (G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI | G_IO_NVAL), | |
1117 io_invoke, NULL, NULL); | |
1118 | |
1119 g_io_channel_unref(channel); /* Apparently this caused crashes for some people. | |
1120 But irssi does this, so I am going to assume the | |
1121 crashes were caused by some other stuff. */ | |
1122 | 307 |
1123 locale = setlocale(LC_ALL, ""); | 308 locale = setlocale(LC_ALL, ""); |
1124 | 309 |
1125 if (locale && (strstr(locale, "UTF") || strstr(locale, "utf"))) | 310 if (locale && (strstr(locale, "UTF") || strstr(locale, "utf"))) |
1126 ascii_only = FALSE; | 311 ascii_only = FALSE; |
1137 filename = g_build_filename(g_get_home_dir(), ".gntrc", NULL); | 322 filename = g_build_filename(g_get_home_dir(), ".gntrc", NULL); |
1138 gnt_style_read_configure_file(filename); | 323 gnt_style_read_configure_file(filename); |
1139 g_free(filename); | 324 g_free(filename); |
1140 | 325 |
1141 gnt_init_colors(); | 326 gnt_init_colors(); |
1142 X_MIN = 0; | |
1143 Y_MIN = 0; | |
1144 X_MAX = getmaxx(stdscr); | |
1145 Y_MAX = getmaxy(stdscr) - 1; | |
1146 | |
1147 nodes = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_node); | |
1148 | 327 |
1149 wbkgdset(stdscr, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL)); | 328 wbkgdset(stdscr, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL)); |
1150 refresh(); | 329 refresh(); |
1151 | 330 |
1152 #ifdef ALL_MOUSE_EVENTS | 331 #ifdef ALL_MOUSE_EVENTS |
1169 init_wm(); | 348 init_wm(); |
1170 } | 349 } |
1171 | 350 |
1172 void gnt_main() | 351 void gnt_main() |
1173 { | 352 { |
1174 loop = g_main_loop_new(NULL, FALSE); | 353 wm->loop = g_main_loop_new(NULL, FALSE); |
1175 g_main_loop_run(loop); | 354 g_main_loop_run(wm->loop); |
1176 } | 355 } |
1177 | 356 |
1178 /********************************* | 357 /********************************* |
1179 * Stuff for 'window management' * | 358 * Stuff for 'window management' * |
1180 *********************************/ | 359 *********************************/ |
1181 | 360 |
1182 static void | |
1183 free_node(gpointer data) | |
1184 { | |
1185 GntNode *node = data; | |
1186 hide_panel(node->panel); | |
1187 del_panel(node->panel); | |
1188 g_free(node); | |
1189 } | |
1190 | |
1191 void gnt_screen_occupy(GntWidget *widget) | 361 void gnt_screen_occupy(GntWidget *widget) |
1192 { | 362 { |
1193 GntNode *node; | 363 gnt_wm_new_window(wm, widget); |
1194 | |
1195 while (widget->parent) | |
1196 widget = widget->parent; | |
1197 | |
1198 if (g_hash_table_lookup(nodes, widget)) | |
1199 return; /* XXX: perhaps _update instead? */ | |
1200 | |
1201 node = g_new0(GntNode, 1); | |
1202 node->me = widget; | |
1203 | |
1204 g_hash_table_replace(nodes, widget, node); | |
1205 | |
1206 refresh_node(widget, node, NULL); | |
1207 | |
1208 if (window_list) | |
1209 { | |
1210 if ((GNT_IS_BOX(widget) && GNT_BOX(widget)->title) && window_list->window != widget | |
1211 && GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_CAN_TAKE_FOCUS)) | |
1212 { | |
1213 gnt_tree_add_row_last(GNT_TREE(window_list->tree), widget, | |
1214 gnt_tree_create_row(GNT_TREE(window_list->tree), GNT_BOX(widget)->title), | |
1215 NULL); | |
1216 update_window_in_list(widget); | |
1217 } | |
1218 } | |
1219 | |
1220 update_screen(NULL); | |
1221 } | 364 } |
1222 | 365 |
1223 void gnt_screen_release(GntWidget *widget) | 366 void gnt_screen_release(GntWidget *widget) |
1224 { | 367 { |
1225 GntNode *node; | 368 gnt_wm_window_close(wm, widget); |
1226 | |
1227 gnt_screen_remove_widget(widget); | |
1228 node = g_hash_table_lookup(nodes, widget); | |
1229 | |
1230 if (node == NULL) /* Yay! Nothing to do. */ | |
1231 return; | |
1232 | |
1233 if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_DESTROYING) && wm.close_window) | |
1234 wm.close_window(widget); | |
1235 | |
1236 g_hash_table_remove(nodes, widget); | |
1237 | |
1238 if (window_list) | |
1239 { | |
1240 gnt_tree_remove(GNT_TREE(window_list->tree), widget); | |
1241 } | |
1242 | |
1243 update_screen(NULL); | |
1244 } | 369 } |
1245 | 370 |
1246 void gnt_screen_update(GntWidget *widget) | 371 void gnt_screen_update(GntWidget *widget) |
1247 { | 372 { |
1248 GntNode *node; | 373 gnt_wm_update_window(wm, widget); |
1249 | |
1250 while (widget->parent) | |
1251 widget = widget->parent; | |
1252 if (!GNT_IS_MENU(widget)) | |
1253 gnt_box_sync_children(GNT_BOX(widget)); | |
1254 node = g_hash_table_lookup(nodes, widget); | |
1255 if (node && !node->panel) | |
1256 { | |
1257 if (wm.new_window && node->me != _list.window) | |
1258 node->panel = wm.new_window(node->me); | |
1259 else | |
1260 node->panel = new_panel(node->me->window); | |
1261 set_panel_userptr(node->panel, node); | |
1262 if (!GNT_WIDGET_IS_FLAG_SET(node->me, GNT_WIDGET_TRANSIENT)) { | |
1263 if (!g_object_get_data(G_OBJECT(node->me), "give_focus")) { | |
1264 bottom_panel(node->panel); /* New windows should not grab focus */ | |
1265 gnt_widget_set_urgent(node->me); | |
1266 } | |
1267 else { | |
1268 bring_on_top(node->me); | |
1269 } | |
1270 } | |
1271 } | |
1272 | |
1273 if (_list.window) | |
1274 { | |
1275 GntNode *nd = g_hash_table_lookup(nodes, _list.window); | |
1276 top_panel(nd->panel); | |
1277 } | |
1278 | |
1279 update_screen(NULL); | |
1280 } | 374 } |
1281 | 375 |
1282 gboolean gnt_widget_has_focus(GntWidget *widget) | 376 gboolean gnt_widget_has_focus(GntWidget *widget) |
1283 { | 377 { |
1284 GntWidget *w; | 378 GntWidget *w; |
1291 w = widget; | 385 w = widget; |
1292 | 386 |
1293 while (widget->parent) | 387 while (widget->parent) |
1294 widget = widget->parent; | 388 widget = widget->parent; |
1295 | 389 |
1296 if (widget == _list.window) | 390 if (widget == wm->_list.window) |
1297 return TRUE; | 391 return TRUE; |
1298 | 392 if (wm->ordered && wm->ordered->data == widget) { |
1299 if (ordered && ordered->data == widget) | |
1300 { | |
1301 if (GNT_IS_BOX(widget) && | 393 if (GNT_IS_BOX(widget) && |
1302 (GNT_BOX(widget)->active == w || widget == w)) | 394 (GNT_BOX(widget)->active == w || widget == w)) |
1303 return TRUE; | 395 return TRUE; |
1304 } | 396 } |
1305 | |
1306 return FALSE; | 397 return FALSE; |
1307 } | 398 } |
1308 | 399 |
1309 void gnt_widget_set_urgent(GntWidget *widget) | 400 void gnt_widget_set_urgent(GntWidget *widget) |
1310 { | 401 { |
1311 while (widget->parent) | 402 while (widget->parent) |
1312 widget = widget->parent; | 403 widget = widget->parent; |
1313 | 404 |
1314 if (ordered && ordered->data == widget) | 405 if (wm->ordered && wm->ordered->data == widget) |
1315 return; | 406 return; |
1316 | 407 |
1317 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_URGENT); | 408 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_URGENT); |
1318 | 409 |
1319 if (wm.window_update) { | 410 gnt_wm_update_window(wm, widget); |
1320 GntNode *node = g_hash_table_lookup(nodes, widget); | |
1321 wm.window_update(node ? node->panel : NULL, widget); | |
1322 } | |
1323 | |
1324 draw_taskbar(FALSE); | |
1325 } | 411 } |
1326 | 412 |
1327 void gnt_quit() | 413 void gnt_quit() |
1328 { | 414 { |
415 g_hash_table_destroy(wm->nodes); /* XXX: */ | |
416 update_panels(); | |
417 doupdate(); | |
1329 gnt_uninit_colors(); | 418 gnt_uninit_colors(); |
1330 gnt_uninit_styles(); | 419 gnt_uninit_styles(); |
1331 endwin(); | 420 endwin(); |
1332 } | 421 } |
1333 | 422 |
1336 return ascii_only; | 425 return ascii_only; |
1337 } | 426 } |
1338 | 427 |
1339 void gnt_screen_resize_widget(GntWidget *widget, int width, int height) | 428 void gnt_screen_resize_widget(GntWidget *widget, int width, int height) |
1340 { | 429 { |
1341 if (widget->parent == NULL) | 430 gnt_wm_resize_window(wm, widget, width, height); |
1342 { | |
1343 GntNode *node = g_hash_table_lookup(nodes, widget); | |
1344 if (!node) | |
1345 return; | |
1346 | |
1347 if (wm.window_resize_confirm && !wm.window_resize_confirm(widget, &width, &height)) | |
1348 return; | |
1349 | |
1350 hide_panel(node->panel); | |
1351 gnt_widget_set_size(widget, width, height); | |
1352 gnt_widget_draw(widget); | |
1353 if (wm.window_resized) | |
1354 node->panel = wm.window_resized(node->panel, widget); | |
1355 else | |
1356 replace_panel(node->panel, widget->window); | |
1357 show_panel(node->panel); | |
1358 update_screen(NULL); | |
1359 } | |
1360 } | 431 } |
1361 | 432 |
1362 void gnt_screen_move_widget(GntWidget *widget, int x, int y) | 433 void gnt_screen_move_widget(GntWidget *widget, int x, int y) |
1363 { | 434 { |
1364 GntNode *node = g_hash_table_lookup(nodes, widget); | 435 gnt_wm_move_window(wm, widget, x, y); |
1365 | |
1366 if (wm.window_move_confirm && !wm.window_move_confirm(widget, &x, &y)) | |
1367 return; | |
1368 | |
1369 gnt_widget_set_position(widget, x, y); | |
1370 move_panel(node->panel, y, x); | |
1371 | |
1372 if (wm.window_moved) | |
1373 wm.window_moved(node->panel, widget); | |
1374 | |
1375 update_screen(NULL); | |
1376 } | 436 } |
1377 | 437 |
1378 void gnt_screen_rename_widget(GntWidget *widget, const char *text) | 438 void gnt_screen_rename_widget(GntWidget *widget, const char *text) |
1379 { | 439 { |
1380 gnt_box_set_title(GNT_BOX(widget), text); | 440 gnt_box_set_title(GNT_BOX(widget), text); |
1381 gnt_widget_draw(widget); | 441 gnt_widget_draw(widget); |
1382 | 442 gnt_wm_update_window(wm, widget); |
1383 if (wm.window_update) { | 443 } |
1384 GntNode *node = g_hash_table_lookup(nodes, widget); | |
1385 wm.window_update(node ? node->panel : NULL, widget); | |
1386 } | |
1387 | |
1388 draw_taskbar(FALSE); | |
1389 } | |
1390 | |
1391 /** | |
1392 * An application can register actions which will show up in a 'start-menu' like popup | |
1393 */ | |
1394 typedef struct _GnAction | |
1395 { | |
1396 const char *label; | |
1397 void (*callback)(); | |
1398 } GntAction; | |
1399 | |
1400 static GList *actions; | |
1401 | 444 |
1402 void gnt_register_action(const char *label, void (*callback)()) | 445 void gnt_register_action(const char *label, void (*callback)()) |
1403 { | 446 { |
1404 GntAction *action = g_new0(GntAction, 1); | 447 GntAction *action = g_new0(GntAction, 1); |
1405 action->label = g_strdup(label); | 448 action->label = g_strdup(label); |
1406 action->callback = callback; | 449 action->callback = callback; |
1407 | 450 |
1408 actions = g_list_append(actions, action); | 451 wm->acts = g_list_append(wm->acts, action); |
1409 } | |
1410 | |
1411 static void | |
1412 action_list_activate(GntTree *tree, gpointer null) | |
1413 { | |
1414 GntAction *action = gnt_tree_get_selection_data(tree); | |
1415 action->callback(); | |
1416 } | |
1417 | |
1418 static int | |
1419 compare_action(gconstpointer p1, gconstpointer p2) | |
1420 { | |
1421 const GntAction *a1 = p1; | |
1422 const GntAction *a2 = p2; | |
1423 | |
1424 return g_utf8_collate(a1->label, a2->label); | |
1425 } | |
1426 | |
1427 static void | |
1428 show_actions_list() | |
1429 { | |
1430 GntWidget *tree, *win; | |
1431 GList *iter; | |
1432 int h; | |
1433 | |
1434 if (action_list) | |
1435 return; | |
1436 | |
1437 setup__list(); | |
1438 action_list = &_list; | |
1439 win = action_list->window; | |
1440 tree = action_list->tree; | |
1441 | |
1442 gnt_box_set_title(GNT_BOX(win), "Actions"); | |
1443 GNT_WIDGET_SET_FLAGS(tree, GNT_WIDGET_NO_BORDER); | |
1444 /* XXX: Do we really want this? */ | |
1445 gnt_tree_set_compare_func(GNT_TREE(tree), compare_action); | |
1446 | |
1447 for (iter = actions; iter; iter = iter->next) { | |
1448 GntAction *action = iter->data; | |
1449 gnt_tree_add_row_last(GNT_TREE(tree), action, | |
1450 gnt_tree_create_row(GNT_TREE(tree), action->label), NULL); | |
1451 } | |
1452 g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(action_list_activate), NULL); | |
1453 gnt_widget_set_size(tree, 0, g_list_length(actions)); | |
1454 gnt_widget_get_size(win, NULL, &h); | |
1455 gnt_widget_set_position(win, 0, getmaxy(stdscr) - 1 - h); | |
1456 | |
1457 lock_focus_list = 1; | |
1458 gnt_widget_show(win); | |
1459 lock_focus_list = 0; | |
1460 } | 452 } |
1461 | 453 |
1462 static void | 454 static void |
1463 reset_menu(GntWidget *widget, gpointer null) | 455 reset_menu(GntWidget *widget, gpointer null) |
1464 { | 456 { |
1465 menu = NULL; | 457 wm->menu = NULL; |
1466 } | 458 } |
1467 | 459 |
1468 gboolean gnt_screen_menu_show(gpointer newmenu) | 460 gboolean gnt_screen_menu_show(gpointer newmenu) |
1469 { | 461 { |
1470 if (menu) { | 462 if (wm->menu) { |
1471 /* For now, if a menu is being displayed, then another menu | 463 /* For now, if a menu is being displayed, then another menu |
1472 * can NOT take over. */ | 464 * can NOT take over. */ |
1473 return FALSE; | 465 return FALSE; |
1474 } | 466 } |
1475 | 467 |
1476 menu = newmenu; | 468 wm->menu = newmenu; |
1477 gnt_widget_draw(GNT_WIDGET(menu)); | 469 gnt_widget_draw(GNT_WIDGET(wm->menu)); |
1478 | 470 |
1479 g_signal_connect(G_OBJECT(menu), "hide", G_CALLBACK(reset_menu), NULL); | 471 g_signal_connect(G_OBJECT(wm->menu), "hide", G_CALLBACK(reset_menu), NULL); |
1480 | 472 |
1481 return TRUE; | 473 return TRUE; |
1482 } | 474 } |
1483 | 475 |