1 /*
2 * GNT - The GLib Ncurses Toolkit
3 *
4 * GNT is the legal property of its developers, whose names are too numerous
5 * to list here. Please refer to the COPYRIGHT file distributed with this
6 * source distribution.
7 *
8 * This library is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
21 */
22
23 /* Stuff brutally ripped from Gflib */
24
25 #include "gntinternal.h"
26 #include "gntwidget.h"
27 #include "gntstyle.h"
28 #include "gntmarshal.h"
29 #include "gntutils.h"
30 #include "gnt.h"
31
32 enum
33 {
34 SIG_DESTROY,
35 SIG_DRAW,
36 SIG_HIDE,
37 SIG_GIVE_FOCUS,
38 SIG_LOST_FOCUS,
39 SIG_KEY_PRESSED,
40 SIG_MAP,
41 SIG_ACTIVATE,
42 SIG_EXPOSE,
43 SIG_SIZE_REQUEST,
44 SIG_CONFIRM_SIZE,
45 SIG_SIZE_CHANGED,
46 SIG_POSITION,
47 SIG_CLICKED,
48 SIG_CONTEXT_MENU,
49 SIGS
50 };
51
52 static GObjectClass *parent_class = NULL;
53 static guint signals[SIGS] = { 0 };
54
55 static void init_widget(GntWidget *widget);
56
57 static void
gnt_widget_init(GTypeInstance * instance,gpointer class)58 gnt_widget_init(GTypeInstance *instance, gpointer class)
59 {
60 GntWidget *widget = GNT_WIDGET(instance);
61 widget->priv.name = NULL;
62 GNTDEBUG;
63 }
64
65 static void
gnt_widget_map(GntWidget * widget)66 gnt_widget_map(GntWidget *widget)
67 {
68 /* Get some default size for the widget */
69 GNTDEBUG;
70 g_signal_emit(widget, signals[SIG_MAP], 0);
71 gnt_widget_set_mapped(widget, TRUE);
72 }
73
74 static void
gnt_widget_dispose(GObject * obj)75 gnt_widget_dispose(GObject *obj)
76 {
77 GntWidget *self = GNT_WIDGET(obj);
78 g_signal_emit(self, signals[SIG_DESTROY], 0);
79 parent_class->dispose(obj);
80 GNTDEBUG;
81 }
82
83 static void
gnt_widget_focus_change(GntWidget * widget)84 gnt_widget_focus_change(GntWidget *widget)
85 {
86 if (gnt_widget_get_mapped(widget)) {
87 gnt_widget_draw(widget);
88 }
89 }
90
91 static gboolean
gnt_widget_dummy_confirm_size(GntWidget * widget,int width,int height)92 gnt_widget_dummy_confirm_size(GntWidget *widget, int width, int height)
93 {
94 gboolean shadow;
95 if (width < widget->priv.minw || height < widget->priv.minh) {
96 return FALSE;
97 }
98
99 shadow = gnt_widget_has_shadow(widget);
100 if (widget->priv.width + shadow != width &&
101 !gnt_widget_get_grow_x(widget)) {
102 return FALSE;
103 }
104 if (widget->priv.height + shadow != height &&
105 !gnt_widget_get_grow_y(widget)) {
106 return FALSE;
107 }
108
109 return TRUE;
110 }
111
112 static gboolean
context_menu(GntBindable * bind,GList * null)113 context_menu(GntBindable *bind, GList *null)
114 {
115 gboolean ret = FALSE;
116 g_signal_emit(bind, signals[SIG_CONTEXT_MENU], 0, &ret);
117 return ret;
118 }
119
120 static void
gnt_widget_class_init(GntWidgetClass * klass)121 gnt_widget_class_init(GntWidgetClass *klass)
122 {
123 GObjectClass *obj_class = G_OBJECT_CLASS(klass);
124
125 parent_class = g_type_class_peek_parent(klass);
126
127 obj_class->dispose = gnt_widget_dispose;
128
129 klass->destroy = gnt_widget_destroy;
130 klass->show = gnt_widget_show;
131 klass->draw = gnt_widget_draw;
132 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
133 klass->expose = gnt_widget_expose;
134 G_GNUC_END_IGNORE_DEPRECATIONS
135 klass->map = gnt_widget_map;
136 klass->lost_focus = gnt_widget_focus_change;
137 klass->gained_focus = gnt_widget_focus_change;
138 klass->confirm_size = gnt_widget_dummy_confirm_size;
139
140 klass->key_pressed = NULL;
141 klass->activate = NULL;
142 klass->clicked = NULL;
143
144 signals[SIG_DESTROY] =
145 g_signal_new("destroy",
146 G_TYPE_FROM_CLASS(klass),
147 G_SIGNAL_RUN_LAST,
148 G_STRUCT_OFFSET(GntWidgetClass, destroy),
149 NULL, NULL,
150 g_cclosure_marshal_VOID__VOID,
151 G_TYPE_NONE, 0);
152 signals[SIG_GIVE_FOCUS] =
153 g_signal_new("gained-focus",
154 G_TYPE_FROM_CLASS(klass),
155 G_SIGNAL_RUN_LAST,
156 G_STRUCT_OFFSET(GntWidgetClass, gained_focus),
157 NULL, NULL,
158 g_cclosure_marshal_VOID__VOID,
159 G_TYPE_NONE, 0);
160 signals[SIG_LOST_FOCUS] =
161 g_signal_new("lost-focus",
162 G_TYPE_FROM_CLASS(klass),
163 G_SIGNAL_RUN_LAST,
164 G_STRUCT_OFFSET(GntWidgetClass, lost_focus),
165 NULL, NULL,
166 g_cclosure_marshal_VOID__VOID,
167 G_TYPE_NONE, 0);
168 signals[SIG_ACTIVATE] =
169 g_signal_new("activate",
170 G_TYPE_FROM_CLASS(klass),
171 G_SIGNAL_RUN_LAST,
172 G_STRUCT_OFFSET(GntWidgetClass, activate),
173 NULL, NULL,
174 g_cclosure_marshal_VOID__VOID,
175 G_TYPE_NONE, 0);
176 signals[SIG_MAP] =
177 g_signal_new("map",
178 G_TYPE_FROM_CLASS(klass),
179 G_SIGNAL_RUN_LAST,
180 G_STRUCT_OFFSET(GntWidgetClass, map),
181 NULL, NULL,
182 g_cclosure_marshal_VOID__VOID,
183 G_TYPE_NONE, 0);
184 signals[SIG_DRAW] =
185 g_signal_new("draw",
186 G_TYPE_FROM_CLASS(klass),
187 G_SIGNAL_RUN_LAST,
188 G_STRUCT_OFFSET(GntWidgetClass, draw),
189 NULL, NULL,
190 g_cclosure_marshal_VOID__VOID,
191 G_TYPE_NONE, 0);
192 signals[SIG_HIDE] =
193 g_signal_new("hide",
194 G_TYPE_FROM_CLASS(klass),
195 G_SIGNAL_RUN_LAST,
196 G_STRUCT_OFFSET(GntWidgetClass, hide),
197 NULL, NULL,
198 g_cclosure_marshal_VOID__VOID,
199 G_TYPE_NONE, 0);
200 signals[SIG_EXPOSE] =
201 g_signal_new("expose",
202 G_TYPE_FROM_CLASS(klass),
203 G_SIGNAL_RUN_LAST,
204 G_STRUCT_OFFSET(GntWidgetClass, expose),
205 NULL, NULL,
206 gnt_closure_marshal_VOID__INT_INT_INT_INT,
207 G_TYPE_NONE, 4, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
208 signals[SIG_POSITION] =
209 g_signal_new("position-set",
210 G_TYPE_FROM_CLASS(klass),
211 G_SIGNAL_RUN_LAST,
212 G_STRUCT_OFFSET(GntWidgetClass, set_position),
213 NULL, NULL,
214 gnt_closure_marshal_VOID__INT_INT,
215 G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
216 signals[SIG_SIZE_REQUEST] =
217 g_signal_new("size_request",
218 G_TYPE_FROM_CLASS(klass),
219 G_SIGNAL_RUN_LAST,
220 G_STRUCT_OFFSET(GntWidgetClass, size_request),
221 NULL, NULL,
222 g_cclosure_marshal_VOID__VOID,
223 G_TYPE_NONE, 0);
224 signals[SIG_SIZE_CHANGED] =
225 g_signal_new("size_changed",
226 G_TYPE_FROM_CLASS(klass),
227 G_SIGNAL_RUN_LAST,
228 G_STRUCT_OFFSET(GntWidgetClass, size_changed),
229 NULL, NULL,
230 gnt_closure_marshal_VOID__INT_INT,
231 G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
232 signals[SIG_CONFIRM_SIZE] =
233 g_signal_new("confirm_size",
234 G_TYPE_FROM_CLASS(klass),
235 G_SIGNAL_RUN_LAST,
236 G_STRUCT_OFFSET(GntWidgetClass, confirm_size),
237 NULL, NULL,
238 gnt_closure_marshal_BOOLEAN__INT_INT,
239 G_TYPE_BOOLEAN, 2, G_TYPE_INT, G_TYPE_INT);
240 signals[SIG_KEY_PRESSED] =
241 g_signal_new("key_pressed",
242 G_TYPE_FROM_CLASS(klass),
243 G_SIGNAL_RUN_LAST,
244 G_STRUCT_OFFSET(GntWidgetClass, key_pressed),
245 g_signal_accumulator_true_handled, NULL,
246 gnt_closure_marshal_BOOLEAN__STRING,
247 G_TYPE_BOOLEAN, 1, G_TYPE_STRING);
248
249 signals[SIG_CLICKED] =
250 g_signal_new("clicked",
251 G_TYPE_FROM_CLASS(klass),
252 G_SIGNAL_RUN_LAST,
253 G_STRUCT_OFFSET(GntWidgetClass, clicked),
254 g_signal_accumulator_true_handled, NULL,
255 gnt_closure_marshal_BOOLEAN__INT_INT_INT,
256 G_TYPE_BOOLEAN, 3, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
257
258 signals[SIG_CONTEXT_MENU] =
259 g_signal_new("context-menu",
260 G_TYPE_FROM_CLASS(klass),
261 G_SIGNAL_RUN_LAST,
262 0,
263 g_signal_accumulator_true_handled, NULL,
264 gnt_closure_marshal_BOOLEAN__VOID,
265 G_TYPE_BOOLEAN, 0);
266
267 /* This is relevant for all widgets */
268 gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "context-menu", context_menu,
269 GNT_KEY_POPUP, NULL);
270 gnt_bindable_register_binding(GNT_BINDABLE_CLASS(klass), "context-menu", GNT_KEY_F11, NULL);
271 gnt_bindable_register_binding(GNT_BINDABLE_CLASS(klass), "context-menu", GNT_KEY_CTRL_X, NULL);
272
273 gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
274 GNTDEBUG;
275 }
276
277 /******************************************************************************
278 * GntWidget API
279 *****************************************************************************/
280 GType
gnt_widget_get_gtype(void)281 gnt_widget_get_gtype(void)
282 {
283 static GType type = 0;
284
285 if(type == 0) {
286 static const GTypeInfo info = {
287 sizeof(GntWidgetClass),
288 NULL, /* base_init */
289 NULL, /* base_finalize */
290 (GClassInitFunc)gnt_widget_class_init,
291 NULL,
292 NULL, /* class_data */
293 sizeof(GntWidget),
294 0, /* n_preallocs */
295 gnt_widget_init, /* instance_init */
296 NULL /* value_table */
297 };
298
299 type = g_type_register_static(GNT_TYPE_BINDABLE,
300 "GntWidget",
301 &info, G_TYPE_FLAG_ABSTRACT);
302 }
303
304 return type;
305 }
306
gnt_widget_set_take_focus(GntWidget * widget,gboolean can)307 void gnt_widget_set_take_focus(GntWidget *widget, gboolean can)
308 {
309 if (can)
310 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS);
311 else
312 GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS);
313 }
314
315 gboolean
gnt_widget_get_take_focus(GntWidget * widget)316 gnt_widget_get_take_focus(GntWidget *widget)
317 {
318 g_return_val_if_fail(GNT_IS_WIDGET(widget), FALSE);
319
320 return GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_CAN_TAKE_FOCUS);
321 }
322
323 void
gnt_widget_destroy(GntWidget * obj)324 gnt_widget_destroy(GntWidget *obj)
325 {
326 g_return_if_fail(GNT_IS_WIDGET(obj));
327
328 if (!gnt_widget_in_destruction(obj)) {
329 GNT_WIDGET_SET_FLAGS(obj, GNT_WIDGET_DESTROYING);
330 gnt_widget_hide(obj);
331 g_clear_pointer(&obj->window, delwin);
332 g_object_run_dispose(G_OBJECT(obj));
333 }
334 GNTDEBUG;
335 }
336
337 void
gnt_widget_show(GntWidget * widget)338 gnt_widget_show(GntWidget *widget)
339 {
340 g_return_if_fail(widget != NULL);
341
342 gnt_widget_draw(widget);
343 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
344 gnt_screen_occupy(widget);
345 G_GNUC_END_IGNORE_DEPRECATIONS
346 }
347
348 void
gnt_widget_draw(GntWidget * widget)349 gnt_widget_draw(GntWidget *widget)
350 {
351 /* Draw the widget */
352 if (gnt_widget_get_drawing(widget))
353 return;
354
355 gnt_widget_set_drawing(widget, TRUE);
356 if (!gnt_widget_get_mapped(widget)) {
357 gnt_widget_map(widget);
358 }
359
360 if (widget->window == NULL)
361 {
362 #if 0
363 int x, y, maxx, maxy, w, h;
364 int oldw, oldh;
365 gboolean shadow = TRUE;
366
367 if (!gnt_widget_has_shadow(widget))
368 shadow = FALSE;
369
370 x = widget->priv.x;
371 y = widget->priv.y;
372 w = oldw = widget->priv.width + shadow;
373 h = oldh = widget->priv.height + shadow;
374
375 getmaxyx(stdscr, maxy, maxx);
376 maxy -= 1; /* room for the taskbar */
377
378 x = MAX(0, x);
379 y = MAX(0, y);
380 if (x + w >= maxx)
381 x = MAX(0, maxx - w);
382 if (y + h >= maxy)
383 y = MAX(0, maxy - h);
384
385 w = MIN(w, maxx);
386 h = MIN(h, maxy);
387
388 widget->priv.x = x;
389 widget->priv.y = y;
390 if (w != oldw || h != oldh) {
391 widget->priv.width = w - shadow;
392 widget->priv.height = h - shadow;
393 g_signal_emit(widget, signals[SIG_SIZE_CHANGED], 0, oldw, oldh);
394 }
395 #else
396 widget->window = newpad(widget->priv.height + 20, widget->priv.width + 20); /* XXX: */
397 #endif
398 init_widget(widget);
399 }
400
401 g_signal_emit(widget, signals[SIG_DRAW], 0);
402 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
403 gnt_widget_queue_update(widget);
404 G_GNUC_END_IGNORE_DEPRECATIONS
405 gnt_widget_set_drawing(widget, FALSE);
406 }
407
408 gboolean
gnt_widget_key_pressed(GntWidget * widget,const char * keys)409 gnt_widget_key_pressed(GntWidget *widget, const char *keys)
410 {
411 gboolean ret;
412 if (!gnt_widget_get_take_focus(widget))
413 return FALSE;
414
415 if (!gnt_widget_get_disable_actions(widget) &&
416 gnt_bindable_perform_action_key(GNT_BINDABLE(widget), keys)) {
417 return TRUE;
418 }
419
420 keys = gnt_bindable_remap_keys(GNT_BINDABLE(widget), keys);
421 g_signal_emit(widget, signals[SIG_KEY_PRESSED], 0, keys, &ret);
422 return ret;
423 }
424
425 gboolean
gnt_widget_clicked(GntWidget * widget,GntMouseEvent event,int x,int y)426 gnt_widget_clicked(GntWidget *widget, GntMouseEvent event, int x, int y)
427 {
428 gboolean ret;
429 g_signal_emit(widget, signals[SIG_CLICKED], 0, event, x, y, &ret);
430 if (!ret && event == GNT_RIGHT_MOUSE_DOWN)
431 ret = gnt_bindable_perform_action_named(GNT_BINDABLE(widget), "context-menu", NULL);
432 return ret;
433 }
434
435 void
gnt_widget_expose(GntWidget * widget,int x,int y,int width,int height)436 gnt_widget_expose(GntWidget *widget, int x, int y, int width, int height)
437 {
438 g_signal_emit(widget, signals[SIG_EXPOSE], 0, x, y, width, height);
439 }
440
441 void
gnt_widget_hide(GntWidget * widget)442 gnt_widget_hide(GntWidget *widget)
443 {
444 g_signal_emit(widget, signals[SIG_HIDE], 0);
445 if (widget->window) {
446 wbkgdset(widget->window, '\0' | gnt_color_pair(GNT_COLOR_NORMAL));
447 }
448 #if 0
449 /* XXX: I have no clue why, but this seemed to be necessary. */
450 if (gnt_widget_has_shadow(widget))
451 mvwvline(widget->window, 1, widget->priv.width, ' ', widget->priv.height);
452 #endif
453 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
454 gnt_screen_release(widget);
455 G_GNUC_END_IGNORE_DEPRECATIONS
456 gnt_widget_set_visible(widget, FALSE);
457 gnt_widget_set_mapped(widget, FALSE);
458 }
459
460 GntWidget *
gnt_widget_get_parent(GntWidget * widget)461 gnt_widget_get_parent(GntWidget *widget)
462 {
463 g_return_val_if_fail(GNT_IS_WIDGET(widget), NULL);
464
465 return widget->parent;
466 }
467
468 GntWidget *
gnt_widget_get_toplevel(GntWidget * widget)469 gnt_widget_get_toplevel(GntWidget *widget)
470 {
471 g_return_val_if_fail(GNT_IS_WIDGET(widget), NULL);
472
473 while (widget->parent) {
474 widget = widget->parent;
475 }
476
477 return widget;
478 }
479
480 void
gnt_widget_set_position(GntWidget * wid,int x,int y)481 gnt_widget_set_position(GntWidget *wid, int x, int y)
482 {
483 g_signal_emit(wid, signals[SIG_POSITION], 0, x, y);
484 /* XXX: Need to install properties for these and g_object_notify */
485 wid->priv.x = x;
486 wid->priv.y = y;
487 }
488
489 void
gnt_widget_get_position(GntWidget * wid,int * x,int * y)490 gnt_widget_get_position(GntWidget *wid, int *x, int *y)
491 {
492 if (x)
493 *x = wid->priv.x;
494 if (y)
495 *y = wid->priv.y;
496 }
497
498 void
gnt_widget_size_request(GntWidget * widget)499 gnt_widget_size_request(GntWidget *widget)
500 {
501 g_signal_emit(widget, signals[SIG_SIZE_REQUEST], 0);
502 }
503
504 void
gnt_widget_get_size(GntWidget * wid,int * width,int * height)505 gnt_widget_get_size(GntWidget *wid, int *width, int *height)
506 {
507 gboolean shadow = TRUE;
508 if (!gnt_widget_has_shadow(wid))
509 shadow = FALSE;
510
511 if (width)
512 *width = wid->priv.width + shadow;
513 if (height)
514 *height = wid->priv.height + shadow;
515 }
516
517 static void
init_widget(GntWidget * widget)518 init_widget(GntWidget *widget)
519 {
520 gboolean shadow = TRUE;
521
522 if (!gnt_widget_has_shadow(widget))
523 shadow = FALSE;
524
525 wbkgd(widget->window, gnt_color_pair(GNT_COLOR_NORMAL));
526 werase(widget->window);
527
528 if (gnt_widget_get_has_border(widget)) {
529 /* - This is ugly. */
530 /* - What's your point? */
531 mvwvline(widget->window, 0, 0, ACS_VLINE | gnt_color_pair(GNT_COLOR_NORMAL), widget->priv.height);
532 mvwvline(widget->window, 0, widget->priv.width - 1,
533 ACS_VLINE | gnt_color_pair(GNT_COLOR_NORMAL), widget->priv.height);
534 mvwhline(widget->window, widget->priv.height - 1, 0,
535 ACS_HLINE | gnt_color_pair(GNT_COLOR_NORMAL), widget->priv.width);
536 mvwhline(widget->window, 0, 0, ACS_HLINE | gnt_color_pair(GNT_COLOR_NORMAL), widget->priv.width);
537 mvwaddch(widget->window, 0, 0, ACS_ULCORNER | gnt_color_pair(GNT_COLOR_NORMAL));
538 mvwaddch(widget->window, 0, widget->priv.width - 1,
539 ACS_URCORNER | gnt_color_pair(GNT_COLOR_NORMAL));
540 mvwaddch(widget->window, widget->priv.height - 1, 0,
541 ACS_LLCORNER | gnt_color_pair(GNT_COLOR_NORMAL));
542 mvwaddch(widget->window, widget->priv.height - 1, widget->priv.width - 1,
543 ACS_LRCORNER | gnt_color_pair(GNT_COLOR_NORMAL));
544 }
545
546 if (shadow)
547 {
548 wbkgdset(widget->window, '\0' | gnt_color_pair(GNT_COLOR_SHADOW));
549 mvwvline(widget->window, 1, widget->priv.width, ' ', widget->priv.height);
550 mvwhline(widget->window, widget->priv.height, 1, ' ', widget->priv.width);
551 }
552 }
553
554 gboolean
gnt_widget_set_size(GntWidget * widget,int width,int height)555 gnt_widget_set_size(GntWidget *widget, int width, int height)
556 {
557 gboolean ret = TRUE;
558
559 if (gnt_widget_has_shadow(widget))
560 {
561 width--;
562 height--;
563 }
564 if (width <= 0)
565 width = widget->priv.width;
566 if (height <= 0)
567 height = widget->priv.height;
568
569 if (gnt_widget_get_mapped(widget)) {
570 ret = gnt_widget_confirm_size(widget, width, height);
571 }
572
573 if (ret)
574 {
575 gboolean shadow = TRUE;
576 int oldw, oldh;
577
578 if (!gnt_widget_has_shadow(widget))
579 shadow = FALSE;
580
581 oldw = widget->priv.width;
582 oldh = widget->priv.height;
583
584 widget->priv.width = width;
585 widget->priv.height = height;
586 if (width + shadow >= getmaxx(widget->window) || height + shadow >= getmaxy(widget->window)) {
587 delwin(widget->window);
588 widget->window = newpad(height + 20, width + 20);
589 }
590
591 g_signal_emit(widget, signals[SIG_SIZE_CHANGED], 0, oldw, oldh);
592
593 if (widget->window)
594 {
595 init_widget(widget);
596 }
597 if (gnt_widget_get_mapped(widget)) {
598 init_widget(widget);
599 } else {
600 gnt_widget_set_mapped(widget, TRUE);
601 }
602 }
603
604 return ret;
605 }
606
607 gboolean
gnt_widget_set_focus(GntWidget * widget,gboolean set)608 gnt_widget_set_focus(GntWidget *widget, gboolean set)
609 {
610 if (!gnt_widget_get_take_focus(widget))
611 return FALSE;
612
613 if (set && !gnt_widget_get_has_focus(widget)) {
614 gnt_widget_set_has_focus(widget, TRUE);
615 g_signal_emit(widget, signals[SIG_GIVE_FOCUS], 0);
616 } else if (!set && gnt_widget_get_has_focus(widget)) {
617 gnt_widget_set_has_focus(widget, FALSE);
618 g_signal_emit(widget, signals[SIG_LOST_FOCUS], 0);
619 } else {
620 return FALSE;
621 }
622
623 return TRUE;
624 }
625
gnt_widget_set_name(GntWidget * widget,const char * name)626 void gnt_widget_set_name(GntWidget *widget, const char *name)
627 {
628 g_free(widget->priv.name);
629 widget->priv.name = g_strdup(name);
630 }
631
gnt_widget_get_name(GntWidget * widget)632 const char *gnt_widget_get_name(GntWidget *widget)
633 {
634 return widget->priv.name;
635 }
636
gnt_widget_activate(GntWidget * widget)637 void gnt_widget_activate(GntWidget *widget)
638 {
639 g_signal_emit(widget, signals[SIG_ACTIVATE], 0);
640 }
641
642 static gboolean
update_queue_callback(gpointer data)643 update_queue_callback(gpointer data)
644 {
645 GntWidget *widget = GNT_WIDGET(data);
646
647 if (!g_object_get_data(G_OBJECT(widget), "gnt:queue_update"))
648 return FALSE;
649 if (gnt_widget_get_mapped(widget)) {
650 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
651 gnt_screen_update(widget);
652 G_GNUC_END_IGNORE_DEPRECATIONS
653 }
654 g_object_set_data(G_OBJECT(widget), "gnt:queue_update", NULL);
655 return FALSE;
656 }
657
gnt_widget_queue_update(GntWidget * widget)658 void gnt_widget_queue_update(GntWidget *widget)
659 {
660 if (widget->window == NULL)
661 return;
662 while (widget->parent)
663 widget = widget->parent;
664
665 if (!g_object_get_data(G_OBJECT(widget), "gnt:queue_update"))
666 {
667 int id = g_timeout_add(0, update_queue_callback, widget);
668 g_object_set_data_full(G_OBJECT(widget), "gnt:queue_update", GINT_TO_POINTER(id),
669 (GDestroyNotify)g_source_remove);
670 }
671 }
672
gnt_widget_confirm_size(GntWidget * widget,int width,int height)673 gboolean gnt_widget_confirm_size(GntWidget *widget, int width, int height)
674 {
675 gboolean ret = FALSE;
676 g_signal_emit(widget, signals[SIG_CONFIRM_SIZE], 0, width, height, &ret);
677 return ret;
678 }
679
gnt_widget_set_visible(GntWidget * widget,gboolean set)680 void gnt_widget_set_visible(GntWidget *widget, gboolean set)
681 {
682 if (set)
683 GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_INVISIBLE);
684 else
685 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_INVISIBLE);
686 }
687
688 gboolean
gnt_widget_get_visible(GntWidget * widget)689 gnt_widget_get_visible(GntWidget *widget)
690 {
691 g_return_val_if_fail(GNT_IS_WIDGET(widget), FALSE);
692
693 return !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_INVISIBLE);
694 }
695
gnt_widget_has_shadow(GntWidget * widget)696 gboolean gnt_widget_has_shadow(GntWidget *widget)
697 {
698 return (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_SHADOW) &&
699 gnt_style_get_bool(GNT_STYLE_SHADOW, FALSE));
700 }
701
702 gboolean
gnt_widget_in_destruction(GntWidget * widget)703 gnt_widget_in_destruction(GntWidget *widget)
704 {
705 g_return_val_if_fail(GNT_IS_WIDGET(widget), FALSE);
706
707 return GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_DESTROYING);
708 }
709
710 void
gnt_widget_set_drawing(GntWidget * widget,gboolean drawing)711 gnt_widget_set_drawing(GntWidget *widget, gboolean drawing)
712 {
713 g_return_if_fail(GNT_IS_WIDGET(widget));
714
715 if (drawing) {
716 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_DRAWING);
717 } else {
718 GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_DRAWING);
719 }
720 }
721
722 gboolean
gnt_widget_get_drawing(GntWidget * widget)723 gnt_widget_get_drawing(GntWidget *widget)
724 {
725 g_return_val_if_fail(GNT_IS_WIDGET(widget), FALSE);
726
727 return GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_DRAWING);
728 }
729
730 void
gnt_widget_set_mapped(GntWidget * widget,gboolean mapped)731 gnt_widget_set_mapped(GntWidget *widget, gboolean mapped)
732 {
733 g_return_if_fail(GNT_IS_WIDGET(widget));
734
735 if (mapped) {
736 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_MAPPED);
737 } else {
738 GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_MAPPED);
739 }
740 }
741
742 gboolean
gnt_widget_get_mapped(GntWidget * widget)743 gnt_widget_get_mapped(GntWidget *widget)
744 {
745 g_return_val_if_fail(GNT_IS_WIDGET(widget), FALSE);
746
747 return GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_MAPPED);
748 }
749
750 void
gnt_widget_set_has_border(GntWidget * widget,gboolean has_border)751 gnt_widget_set_has_border(GntWidget *widget, gboolean has_border)
752 {
753 g_return_if_fail(GNT_IS_WIDGET(widget));
754
755 if (has_border) {
756 GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_NO_BORDER);
757 } else {
758 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER);
759 }
760 }
761
762 gboolean
gnt_widget_get_has_border(GntWidget * widget)763 gnt_widget_get_has_border(GntWidget *widget)
764 {
765 g_return_val_if_fail(GNT_IS_WIDGET(widget), FALSE);
766
767 return !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER);
768 }
769
770 void
gnt_widget_set_has_shadow(GntWidget * widget,gboolean has_shadow)771 gnt_widget_set_has_shadow(GntWidget *widget, gboolean has_shadow)
772 {
773 g_return_if_fail(GNT_IS_WIDGET(widget));
774
775 if (has_shadow) {
776 GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_NO_SHADOW);
777 } else {
778 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_SHADOW);
779 }
780 }
781
782 gboolean
gnt_widget_get_has_shadow(GntWidget * widget)783 gnt_widget_get_has_shadow(GntWidget *widget)
784 {
785 g_return_val_if_fail(GNT_IS_WIDGET(widget), FALSE);
786
787 return !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_SHADOW);
788 }
789
790 void
gnt_widget_set_has_focus(GntWidget * widget,gboolean has_focus)791 gnt_widget_set_has_focus(GntWidget *widget, gboolean has_focus)
792 {
793 g_return_if_fail(GNT_IS_WIDGET(widget));
794
795 if (has_focus) {
796 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_HAS_FOCUS);
797 } else {
798 GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_HAS_FOCUS);
799 }
800 }
801
802 gboolean
gnt_widget_get_has_focus(GntWidget * widget)803 gnt_widget_get_has_focus(GntWidget *widget)
804 {
805 g_return_val_if_fail(GNT_IS_WIDGET(widget), FALSE);
806
807 return GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_HAS_FOCUS);
808 }
809
810 void
gnt_widget_set_is_urgent(GntWidget * widget,gboolean urgent)811 gnt_widget_set_is_urgent(GntWidget *widget, gboolean urgent)
812 {
813 g_return_if_fail(GNT_IS_WIDGET(widget));
814
815 if (urgent) {
816 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_URGENT);
817 } else {
818 GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_URGENT);
819 }
820 }
821
822 gboolean
gnt_widget_get_is_urgent(GntWidget * widget)823 gnt_widget_get_is_urgent(GntWidget *widget)
824 {
825 g_return_val_if_fail(GNT_IS_WIDGET(widget), FALSE);
826
827 return GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_URGENT);
828 }
829
830 void
gnt_widget_set_grow_x(GntWidget * widget,gboolean grow_x)831 gnt_widget_set_grow_x(GntWidget *widget, gboolean grow_x)
832 {
833 g_return_if_fail(GNT_IS_WIDGET(widget));
834
835 if (grow_x) {
836 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X);
837 } else {
838 GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_GROW_X);
839 }
840 }
841
842 gboolean
gnt_widget_get_grow_x(GntWidget * widget)843 gnt_widget_get_grow_x(GntWidget *widget)
844 {
845 g_return_val_if_fail(GNT_IS_WIDGET(widget), FALSE);
846
847 return GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_GROW_X);
848 }
849
850 void
gnt_widget_set_grow_y(GntWidget * widget,gboolean grow_y)851 gnt_widget_set_grow_y(GntWidget *widget, gboolean grow_y)
852 {
853 g_return_if_fail(GNT_IS_WIDGET(widget));
854
855 if (grow_y) {
856 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_Y);
857 } else {
858 GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_GROW_Y);
859 }
860 }
861
862 gboolean
gnt_widget_get_grow_y(GntWidget * widget)863 gnt_widget_get_grow_y(GntWidget *widget)
864 {
865 g_return_val_if_fail(GNT_IS_WIDGET(widget), FALSE);
866
867 return GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_GROW_Y);
868 }
869
870 void
gnt_widget_set_transient(GntWidget * widget,gboolean transient)871 gnt_widget_set_transient(GntWidget *widget, gboolean transient)
872 {
873 g_return_if_fail(GNT_IS_WIDGET(widget));
874
875 if (transient) {
876 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_TRANSIENT);
877 } else {
878 GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_TRANSIENT);
879 }
880 }
881
882 gboolean
gnt_widget_get_transient(GntWidget * widget)883 gnt_widget_get_transient(GntWidget *widget)
884 {
885 g_return_val_if_fail(GNT_IS_WIDGET(widget), FALSE);
886
887 return GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_TRANSIENT);
888 }
889
890 void
gnt_widget_set_disable_actions(GntWidget * widget,gboolean disable_actions)891 gnt_widget_set_disable_actions(GntWidget *widget, gboolean disable_actions)
892 {
893 g_return_if_fail(GNT_IS_WIDGET(widget));
894
895 if (disable_actions) {
896 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_DISABLE_ACTIONS);
897 } else {
898 GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_DISABLE_ACTIONS);
899 }
900 }
901
902 gboolean
gnt_widget_get_disable_actions(GntWidget * widget)903 gnt_widget_get_disable_actions(GntWidget *widget)
904 {
905 g_return_val_if_fail(GNT_IS_WIDGET(widget), FALSE);
906
907 return GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_DISABLE_ACTIONS);
908 }
909