naev 0.10.4
toolkit.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include <stdarg.h>
11
12#include "naev.h"
15#include "toolkit.h"
16
17#include "conf.h"
18#include "dialogue.h"
19#include "input.h"
20#include "log.h"
21#include "opengl.h"
22#include "pause.h"
23#include "nmath.h"
24#include "tk/toolkit_priv.h"
25
26#define INPUT_DELAY conf.repeat_delay
27#define INPUT_FREQ conf.repeat_freq
29static unsigned int genwid = 0;
31static int toolkit_delayCounter = 0;
33static const double WINDOW_FADEIN_TIME = 0.05;
34static const double WINDOW_FADEOUT_TIME = 0.05;
36/*
37 * window stuff
38 */
39#define MIN_WINDOWS 3
40static Window *windows = NULL;
42/*
43 * simulate keypresses when holding
44 */
45static SDL_Keycode input_key = 0;
46static SDL_Keymod input_mod = 0;
48/*
49 * default outline colours
50 */
51const glColour* toolkit_colLight = &cGrey50;
52const glColour* toolkit_col = &cGrey20;
53const glColour* toolkit_colDark = &cGrey5;
55/*
56 * Tab colors
57 */
58const glColour* tab_active = &cGrey20;
59const glColour* tab_activeB = &cGrey10;
60const glColour* tab_inactive = &cGrey15;
61const glColour* tab_inactiveB = &cGrey10;
62const glColour* tab_background= &cBlack;
64/*
65 * VBO
66 */
67static gl_vbo *toolkit_vbo;
70/*
71 * static prototypes
72 */
73/* input */
74static int toolkit_mouseEvent( Window *w, SDL_Event* event );
75static int toolkit_mouseEventWidget( Window *w, Widget *wgt,
76 SDL_Event *event, int x, int y, int rx, int ry );
77static int toolkit_keyEvent( Window *wdw, SDL_Event* event );
78static int toolkit_textEvent( Window *wdw, SDL_Event* event );
79/* Focus */
80static int toolkit_isFocusable( Widget *wgt );
81static Widget* toolkit_getFocus( Window *wdw );
82static void toolkit_expose( Window *wdw, int expose );
83/* render */
84static void window_renderBorder( Window* w );
85/* Death. */
86static void widget_kill( Widget *wgt );
87static void window_remove( Window *wdw );
88static void toolkit_purgeDead (void);
89
96{
97 /* Check to see if there is any active window. */
98 for (Window *wdw = windows; wdw != NULL; wdw = wdw->next)
99 if (!window_isFlag( wdw, WINDOW_FADEOUT | WINDOW_KILL | WINDOW_NORENDER ))
100 return 1;
101 return 0;
102}
103
107void toolkit_delay (void)
108{
110}
111
120void toolkit_setPos( Window *wdw, Widget *wgt, int x, int y )
121{
122 /* X position. */
123 if (x < 0)
124 wgt->x = wdw->w - wgt->w + x;
125 else
126 wgt->x = (double) x;
127
128 /* Y position. */
129 if (y < 0)
130 wgt->y = wdw->h - wgt->h + y;
131 else
132 wgt->y = (double) y;
133}
134
142void toolkit_setWindowPos( Window *wdw, int x, int y )
143{
144 wdw->xrel = -1.;
145 wdw->yrel = -1.;
146
147 window_rmFlag( wdw, WINDOW_CENTERX );
148 window_rmFlag( wdw, WINDOW_CENTERY );
149
150 /* x pos */
151 if (x == -1) { /* Center */
152 wdw->x = (gl_screen.nw - wdw->w)/2.;
153 wdw->xrel = .5;
154 window_setFlag( wdw, WINDOW_CENTERX );
155 }
156 else if (x < 0)
157 wdw->x = gl_screen.nw - wdw->w + (double) x;
158 else
159 wdw->x = (double) x;
160
161 /* y pos */
162 if (y == -1) { /* Center */
163 wdw->y = (gl_screen.nh - wdw->h)/2.;
164 wdw->yrel = .5;
165 window_setFlag( wdw, WINDOW_CENTERY );
166 }
167 else if (y < 0)
168 wdw->y = gl_screen.nh - wdw->h + (double) y;
169 else
170 wdw->y = (double) y;
171}
172
180void window_move( unsigned int wid, int x, int y )
181{
182 /* Get the window. */
183 Window *wdw = window_wget(wid);
184 if (wdw == NULL)
185 return;
186
187 toolkit_setWindowPos( wdw, x, y );
188}
189
197void window_resize( unsigned int wid, int w, int h )
198{
199 /* Get the window. */
200 Window *wdw = window_wget(wid);
201 if (wdw == NULL)
202 return;
203
204 wdw->w = (w == -1) ? gl_screen.nw : (double) w;
205 wdw->h = (h == -1) ? gl_screen.nh : (double) h;
206 if ((w == -1) && (h == -1)) {
207 window_setFlag( wdw, WINDOW_FULLSCREEN );
208 wdw->x = 0.;
209 wdw->y = 0.;
210 window_setFlag( wdw, WINDOW_CENTERX );
211 window_setFlag( wdw, WINDOW_CENTERY );
212 }
213 else {
214 window_rmFlag( wdw, WINDOW_FULLSCREEN );
215 if (window_isFlag( wdw, WINDOW_CENTERX ) && window_isFlag( wdw, WINDOW_CENTERY ))
216 toolkit_setWindowPos( wdw, -1, -1 );
217 }
218}
219
227Widget* window_newWidget( Window* w, const char *name )
228{
229 Widget *wgt, *wlast, *wtmp;
230 char *saved_name = NULL;
231
232 /* NULL protection. */
233 if (w==NULL)
234 return NULL;
235
236 /* Try to find one with the same name first. */
237 wlast = NULL;
238 for (wgt=w->widgets; wgt!=NULL; wgt=wgt->next) {
239
240 /* Must match name. */
241 if (strcmp(name, wgt->name)!=0) {
242 wlast = wgt;
243 continue;
244 }
245
246 /* Should be destroyed. */
247 if (!wgt_isFlag( wgt, WGT_FLAG_KILL )) {
248 WARN(_("Trying to create widget '%s' over existing one that hasn't been destroyed"),
249 name );
250 return NULL;
251 }
252
253 /* Relink. */
254 if (wlast==NULL)
255 w->widgets = wgt->next;
256 else
257 wlast->next = wgt->next;
258
259 /* Prepare and return this widget. */
260 saved_name = wgt->name;
261 wgt->name = NULL;
262 widget_cleanup(wgt);
263 break;
264 }
265
266 /* Must grow widgets. */
267 if (wgt == NULL)
268 wgt = malloc( sizeof(Widget) );
269
270 /* Safe defaults. */
271 memset( wgt, 0, sizeof(Widget) );
272 wgt->type = WIDGET_NULL;
273 wgt->status = WIDGET_STATUS_NORMAL;
274 wgt->wdw = w->id;
275 if (saved_name != NULL) /* Hack to avoid frees so _getFocus works in the same frame. */
276 wgt->name = saved_name;
277 else
278 wgt->name = strdup(name);
279 wgt->id = ++w->idgen;
280
281 /* Set up. */
282 wlast = NULL;
283 for (wtmp=w->widgets; wtmp!=NULL; wtmp=wtmp->next)
284 wlast = wtmp;
285 if (wlast == NULL)
286 w->widgets = wgt;
287 else
288 wlast->next = wgt;
289
290 return wgt;
291}
292
299Window* window_wget( unsigned int wid )
300{
301 if (windows == NULL) {
302 WARN(_("Window '%u' not found in list!"), wid );
303 return NULL;
304 }
305 Window *w = window_wgetW( wid );
306 if (w==NULL)
307 WARN(_("Window '%u' not found in list!"), wid );
308 return w;
309}
310
317Window* window_wgetW( unsigned int wid )
318{
319 for (Window *w = windows; w != NULL; w = w->next)
320 if (w->id == wid)
321 return w;
322 return NULL;
323}
324
331Window* window_wgetNameW( const char *name )
332{
333 for (Window *w = windows; w != NULL; w = w->next)
334 if (strcmp( w->name, name )==0)
335 return w;
336 return NULL;
337}
338
346Widget* window_getwgt( unsigned int wid, const char* name )
347{
348 /* Get the window. */
349 Window *wdw = window_wget(wid);
350 if (wdw == NULL) {
351 WARN(_("Widget '%s' not found in window '%u'!"), name, wid );
352 return NULL;
353 }
354
355 /* Find the widget. */
356 for (Widget *wgt=wdw->widgets; wgt!=NULL; wgt=wgt->next)
357 if (strcmp(wgt->name, name)==0)
358 return wgt;
359
360 WARN(_("Widget '%s' not found in window '%u'!"), name, wid );
361 return NULL;
362}
363
371void window_dimWindow( unsigned int wid, int *w, int *h )
372{
373 /* Get the window. */
374 Window *wdw = window_wget(wid);
375 if (wdw == NULL) {
376 *w = -1;
377 *h = -1;
378 return;
379 }
380
381 /* Set dimensions. */
382 *w = wdw->w;
383 *h = wdw->h;
384}
385
393void window_posWindow( unsigned int wid, int *x, int *y )
394{
395 /* Get the window. */
396 Window *wdw = window_wget(wid);
397 if (wdw == NULL) {
398 *x = -1;
399 *y = -1;
400 return;
401 }
402
403 /* Set dimensions. */
404 *x = wdw->x;
405 *y = wdw->y;
406}
407
416void window_dimWidget( unsigned int wid, const char *name, int *w, int *h )
417{
418 /* Get widget. */
419 Widget *wgt = window_getwgt(wid, name);
420 if (wgt == NULL) {
421 if (w!=NULL)
422 *w = -1;
423 if (h!=NULL)
424 *h = -1;
425 return;
426 }
427
428 if (w!=NULL)
429 *w = wgt->w;
430 if (h!=NULL)
431 *h = wgt->h;
432}
433
442void window_posWidget( unsigned int wid,
443 const char* name, int *x, int *y )
444{
445 Widget *wgt;
446
447 /* Get widget. */
448 wgt = window_getwgt(wid,name);
449 if (wgt == NULL)
450 return;
451
452 /* Return position. */
453 if (x != NULL)
454 (*x) = wgt->x;
455 if (y != NULL)
456 (*y) = wgt->y;
457}
458
467void window_moveWidget( unsigned int wid,
468 const char* name, int x, int y )
469{
470 Window *wdw;
471 Widget *wgt;
472
473 /* Get window. */
474 wdw = window_wget(wid);
475 if (wdw == NULL)
476 return;
477
478 /* Get widget. */
479 wgt = window_getwgt(wid,name);
480 if (wgt == NULL)
481 return;
482
483 /* Set position. */
484 toolkit_setPos( wdw, wgt, x, y );
485}
486
495void window_resizeWidget( unsigned int wid,
496 const char* name, int w, int h )
497{
498 Window *wdw;
499 Widget *wgt;
500
501 /* Get window. */
502 wdw = window_wget(wid);
503 if (wdw == NULL)
504 return;
505
506 /* Get widget. */
507 wgt = window_getwgt(wid,name);
508 if (wgt == NULL)
509 return;
510
511 /* Set position. */
512 wgt->w = w;
513 wgt->h = h;
514}
515
523void window_canFocusWidget( unsigned int wid,
524 const char* name, int canfocus )
525{
526 Window *wdw;
527 Widget *wgt;
528
529 /* Get window. */
530 wdw = window_wget(wid);
531 if (wdw == NULL)
532 return;
533
534 /* Get widget. */
535 wgt = window_getwgt(wid,name);
536 if (wgt == NULL)
537 return;
538
539 /* Set position. */
540 if (canfocus)
541 wgt_setFlag( wgt, WGT_FLAG_CANFOCUS );
542 else
543 wgt_rmFlag( wgt, WGT_FLAG_CANFOCUS );
544}
545
551int window_isTop( unsigned int wid )
552{
553 Window *n, *w = window_wget(wid);
554 if (w==NULL)
555 return 0;
556 n = w->next;
557 while (n != NULL) {
558 if (!window_isFlag(n,WINDOW_KILL | WINDOW_FADEOUT | WINDOW_NORENDER))
559 return 0;
560 n = n->next;
561 }
562 return 1;
563}
564
568int widget_isCovered( unsigned int wid, const char *name, int x, int y )
569{
570 int bx, by, rx, ry;
571 Widget *wgt = window_getwgt( wid, name );
572 if (wgt==NULL)
573 return 0;
574
575 /* Undo transform. */
576 bx = x + wgt->x;
577 by = y + wgt->y;
578
579 /* Find if the point is covered. */
580 for (Widget *w=wgt->next; w!=NULL; w=w->next) {
581 if ((wgt->render==NULL) || wgt_isFlag(w, WGT_FLAG_KILL))
582 continue;
583
584 rx = bx-w->x;
585 ry = by-w->y;
586 if (!((rx < 0) || (rx >= w->w) || (ry < 0) || (ry >= w->h)))
587 return 1;
588 }
589 return 0;
590}
591
598int window_exists( const char* wdwname )
599{
600 if (windows == NULL)
601 return 0;
602 for (Window *w = windows; w != NULL; w = w->next)
603 if ((strcmp(w->name,wdwname)==0) && !window_isFlag(w, WINDOW_KILL | WINDOW_FADEOUT))
604 return 1;
605 return 0; /* doesn't exist */
606}
607
614int window_existsID( unsigned int wid )
615{
616 if (windows == NULL)
617 return 0;
618 for (Window *w = windows; w != NULL; w = w->next)
619 if ((w->id==wid) && !window_isFlag(w, WINDOW_KILL | WINDOW_FADEOUT))
620 return 1;
621 return 0; /* doesn't exist */
622}
623
631int window_setDisplayname( unsigned int wid, const char *displayname )
632{
633 Window *wdw = window_wget(wid);
634 if (wdw == NULL)
635 return -1;
636 free(wdw->displayname);
637 wdw->displayname = NULL;
638 if (displayname != NULL)
639 wdw->displayname = strdup(displayname);
640 return 0;
641}
642
646void window_setFade( unsigned int wid, const SimpleShader *shd, double length )
647{
648 (void) shd;
649
650 Window *wdw = window_wget(wid);
651 if (wdw == NULL)
652 return;
653
654 wdw->timer_max = wdw->timer = length;
655
656 if (wdw->timer <= 0.) {
657 if (window_isFlag(wdw, WINDOW_FADEOUT))
658 window_kill( wdw );
659 window_rmFlag(wdw, WINDOW_FADEIN | WINDOW_FADEOUT);
660 }
661}
662
671unsigned int window_get( const char* wdwname )
672{
673 Window *last;
674 if (windows == NULL)
675 return 0;
676 last = NULL;
677 for (Window *w = windows; w != NULL; w = w->next)
678 if ((strcmp(w->name,wdwname)==0) && !window_isFlag(w, WINDOW_KILL | WINDOW_FADEOUT))
679 last = w;
680 if (last==NULL)
681 return 0;
682 return last->id;
683}
684
696unsigned int window_create( const char* name, const char *displayname,
697 const int x, const int y, const int w, const int h )
698{
699 return window_createFlags( name, displayname, x, y, w, h, 0 );
700}
701
714unsigned int window_createFlags( const char* name, const char *displayname,
715 const int x, const int y, const int w, const int h, unsigned int flags )
716{
717 Window *old = window_wgetNameW( name );
718 Window *wdw = calloc( 1, sizeof(Window) );
719
720 const int wid = (++genwid); /* unique id */
721
722 /* Create the window. */
723 wdw->id = wid;
724 wdw->name = strdup(name);
725 wdw->displayname = strdup(displayname);
726
727 /* Safe defaults. */
728 wdw->idgen = -1;
729 wdw->focus = -1;
730 wdw->xrel = -1.;
731 wdw->yrel = -1.;
732 wdw->flags = flags | WINDOW_FADEIN | WINDOW_FADEDELAY;
733 wdw->exposed = !window_isFlag(wdw, WINDOW_NOFOCUS);
734 wdw->timer_max = wdw->timer = WINDOW_FADEIN_TIME;
735
736 /* In the case a window is getting recreated over an old one, we can skip
737 * the fade on both of them, and just replace it. */
738 if ((old != NULL) && window_isFlag( old, WINDOW_KILL | WINDOW_FADEOUT )) {
739 old->timer = 0.;
740 window_rmFlag( wdw, WINDOW_FADEIN | WINDOW_FADEDELAY );
741 wdw->timer = 0.;
742 }
743
744 /* Dimensions. */
745 wdw->w = (w == -1) ? gl_screen.nw : (double) w;
746 wdw->h = (h == -1) ? gl_screen.nh : (double) h;
747 if ((w == -1) && (h == -1)) {
748 window_setFlag( wdw, WINDOW_FULLSCREEN );
749 wdw->x = 0.;
750 wdw->y = 0.;
751 }
752 else
753 toolkit_setWindowPos( wdw, x, y );
754
755 if (!toolkit_isOpen()) {
757 pause_game();
758 gl_defViewport(); /* Reset the default viewport */
759 }
760
761 /* Clear key repeat. */
763
764 /* Add to list. */
765 wdw->next = NULL;
766 if (windows == NULL)
767 windows = wdw;
768 else {
769 Window *wlast;
770 /* Take focus from the old window. */
771 if (wdw->exposed) {
772 Window *wcur = toolkit_getActiveWindow();
773 if (wcur != NULL)
774 toolkit_expose( wcur, 0 ); /* wcur is hidden */
775 }
776
777 wlast = windows;
778 while (1) {
779 if ((strcmp( wlast->name, name )==0) && !window_isFlag( wlast, WINDOW_KILL | WINDOW_FADEOUT )
780 && !window_isFlag( wlast, WINDOW_NOFOCUS ))
781 WARN( _( "Window with name '%s' already exists!" ), wlast->name );
782
783 if (wlast->next == NULL)
784 break;
785
786 wlast = wlast->next;
787 }
788
789 wlast->next = wdw;
790 }
791
792 return wid;
793}
794
803void window_setParent( unsigned int wid, unsigned int parent )
804{
805 /* Get the window. */
806 Window *wdw = window_wget( wid );
807 if (wdw == NULL)
808 return;
809
810 /* Set the parent. */
811 wdw->parent = parent;
812}
813
820unsigned int window_getParent( unsigned int wid )
821{
822 /* Get the window. */
823 Window *wdw = window_wget( wid );
824 if (wdw == NULL)
825 return 0;
826
827 /* Get the parent. */
828 return wdw->parent;
829}
830
840void window_onClose( unsigned int wid, void (*fptr)(unsigned int,const char*) )
841{
842 /* Get the window. */
843 Window *wdw = window_wget( wid );
844 if (wdw == NULL)
845 return;
846
847 /* Set the close function. */
848 wdw->close_fptr = fptr;
849}
850
858void window_onCleanup( unsigned int wid, void (*fptr)(unsigned int,const char*) )
859{
860 /* Get the window. */
861 Window *wdw = window_wget( wid );
862 if (wdw == NULL)
863 return;
864
865 /* Set the close function. */
866 wdw->cleanup_fptr = fptr;
867}
868
879void window_setAccept( unsigned int wid, void (*accept)(unsigned int,const char*) )
880{
881 /* Get the window. */
882 Window *wdw = window_wget( wid );
883 if (wdw == NULL)
884 return;
885
886 /* Set the accept function. */
887 wdw->accept_fptr = accept;
888}
889
900void window_setCancel( unsigned int wid, void (*cancel)(unsigned int,const char*) )
901{
902 /* Get the window. */
903 Window *wdw = window_wget( wid );
904 if (wdw == NULL)
905 return;
906
907 /* Set the cancel function. */
908 wdw->cancel_fptr = cancel;
909}
910
917void window_setData( unsigned int wid, void *data )
918{
919 /* Get the window. */
920 Window *wdw = window_wget( wid );
921 if (wdw == NULL)
922 return;
923
924 /* Set data. */
925 wdw->udata = data;
926}
927
934void* window_getData( unsigned int wid )
935{
936 /* Get the window. */
937 Window *wdw = window_wget( wid );
938 if (wdw == NULL)
939 return NULL;
940
941 /* Get data. */
942 return wdw->udata;
943}
944
953void window_setBorder( unsigned int wid, int enable )
954{
955 /* Get the window. */
956 Window *wdw = window_wget( wid );
957 if (wdw == NULL)
958 return;
959
960 if (enable)
961 window_rmFlag( wdw, WINDOW_NOBORDER );
962 else
963 window_setFlag( wdw, WINDOW_NOBORDER );
964}
965
972void window_handleKeys( unsigned int wid,
973 int (*keyhandler)(unsigned int,SDL_Keycode,SDL_Keymod) )
974{
975 /* Get the window. */
976 Window *wdw = window_wget( wid );
977 if (wdw == NULL)
978 return;
979
980 /* Set key event handler function. */
981 wdw->keyevent = keyhandler;
982}
983
989void window_handleEvents( unsigned int wid,
990 int (*eventhandler)(unsigned int,SDL_Event*) )
991{
992 /* Get the window. */
993 Window *wdw = window_wget( wid );
994 if (wdw == NULL)
995 return;
996
997 /* Set key event handler function. */
998 wdw->eventevent = eventhandler;
999}
1000
1006void widget_cleanup( Widget *widget )
1007{
1008 /* Type specific clean up. */
1009 if (widget->cleanup != NULL)
1010 widget->cleanup(widget);
1011
1012 /* General freeing. */
1013 free(widget->name);
1014}
1015
1020{
1021 for (Window *w = windows; w != NULL; w = w->next)
1022 window_destroy( w->id );
1023}
1024
1031void window_close( unsigned int wid, const char *str )
1032{
1033 (void) str;
1034 window_destroy( wid );
1035}
1036
1042void window_destroy( unsigned int wid )
1043{
1044 if (windows == NULL)
1045 return;
1046 /* Destroy the window */
1047 for (Window *wdw = windows; wdw != NULL; wdw = wdw->next) {
1048 Window *wactive;
1049
1050 /* Not the window we're looking for. */
1051 if (wdw->id != wid)
1052 continue;
1053
1054 /* Already being killed, skip. */
1055 if (window_isFlag( wdw, WINDOW_KILL | WINDOW_FADEOUT ))
1056 continue;
1057
1058 /* Mark children for death. */
1059 for (Window *w = windows; w != NULL; w = w->next)
1060 if (w->parent == wid)
1061 window_destroy( w->id );
1062
1063 /* Start the fade out. */
1064 window_rmFlag( wdw, WINDOW_FADEIN );
1065 window_setFlag( wdw, WINDOW_FADEOUT | WINDOW_FADEDELAY );
1066 wdw->timer_max = wdw->timer = WINDOW_FADEOUT_TIME;
1067
1068 /* Run the close function first. */
1069 if (wdw->close_fptr != NULL)
1070 wdw->close_fptr( wdw->id, wdw->name );
1071 wdw->close_fptr = NULL;
1072
1073 /* Disable text input, etc. */
1074 toolkit_focusClear( wdw );
1075
1076 wactive = toolkit_getActiveWindow();
1077 if (wactive == NULL)
1078 break;
1079
1080 toolkit_expose( wactive, 1 );
1081 break;
1082 }
1083}
1084
1090void window_kill( Window *wdw )
1091{
1092 for (Window *w = windows; w != NULL; w = w->next)
1093 if (w->parent == wdw->id)
1094 window_kill( w );
1095 window_setFlag( wdw, WINDOW_KILL );
1096}
1097
1103static void window_remove( Window *wdw )
1104{
1105 Widget *wgt;
1106
1107 /* Run the close function first. */
1108 if (wdw->close_fptr != NULL)
1109 wdw->close_fptr( wdw->id, wdw->name );
1110 wdw->close_fptr = NULL;
1111
1112 /* Run the cleanup function. */
1113 if (wdw->cleanup_fptr != NULL)
1114 wdw->cleanup_fptr( wdw->id, wdw->name );
1115 wdw->cleanup_fptr = NULL;
1116
1117 /* Destroy the window. */
1118 free(wdw->name);
1119 free(wdw->displayname);
1120 wgt = wdw->widgets;
1121 while (wgt != NULL) {
1122 Widget *wgtkill = wgt;
1123 wgt = wgtkill->next;
1124 widget_kill(wgtkill);
1125 }
1126 free(wdw);
1127
1128 /* Clear key repeat, since toolkit could miss the keyup event. */
1130}
1131
1139int widget_exists( unsigned int wid, const char* wgtname )
1140{
1141 /* Get window. */
1142 Window *w = window_wget(wid);
1143 if (w==NULL) {
1144 WARN(_("window '%d' does not exist"), wid);
1145 return 0;
1146 }
1147
1148 /* Check for widget. */
1149 for (Widget *wgt=w->widgets; wgt!=NULL; wgt=wgt->next)
1150 if (strcmp(wgtname, wgt->name)==0)
1151 return !wgt_isFlag(wgt, WGT_FLAG_KILL);
1152
1153 return 0;
1154}
1155
1162void window_destroyWidget( unsigned int wid, const char* wgtname )
1163{
1164 Window *wdw;
1165 Widget *wgt;
1166
1167 /* Get the window. */
1168 wdw = window_wget( wid );
1169 if (wdw == NULL)
1170 return;
1171
1172 /* Get the widget. */
1173 for (wgt=wdw->widgets; wgt!=NULL; wgt=wgt->next)
1174 if (strcmp(wgt->name, wgtname)==0)
1175 break;
1176
1177 if (wgt == NULL) {
1178 WARN(_("Widget '%s' not found in window '%s'"), wgtname, wdw->displayname );
1179 return;
1180 }
1181
1182 toolkit_defocusWidget( wdw, wgt );
1183
1184 /* There's dead stuff now. */
1185 wgt_rmFlag( wgt, WGT_FLAG_FOCUSED );
1186 wgt_setFlag( wgt, WGT_FLAG_KILL );
1187}
1188
1192static void widget_kill( Widget *wgt )
1193{
1194 /* Clean up. */
1195 widget_cleanup(wgt);
1196 free(wgt);
1197}
1198
1213void toolkit_drawOutlineThick( int x, int y, int w, int h, int b,
1214 int thick, const glColour* c, const glColour* lc )
1215{
1216 GLshort tri[5][4];
1217 glColour colours[10];
1218
1219 x -= (b - thick);
1220 w += 2 * (b - thick);
1221 y -= (b - thick);
1222 h += 2 * (b - thick);
1223 lc = lc ? lc : c;
1224
1225 /* Left-up. */
1226 tri[0][0] = x; /* Inner */
1227 tri[0][1] = y;
1228 tri[0][2] = x-thick; /* Outer */
1229 tri[0][3] = y-thick;
1230 colours[0] = *lc;
1231 colours[1] = *lc;
1232
1233 /* Left-down. */
1234 tri[1][0] = x; /* Inner. */
1235 tri[1][1] = y + h;
1236 tri[1][2] = x-thick; /* Outer. */
1237 tri[1][3] = y + h+thick;
1238 colours[2] = *c;
1239 colours[3] = *c;
1240
1241 /* Right-down. */
1242 tri[2][0] = x + w; /* Inner. */
1243 tri[2][1] = y + h;
1244 tri[2][2] = x + w+thick; /* Outer. */
1245 tri[2][3] = y + h+thick;
1246 colours[4] = *c;
1247 colours[5] = *c;
1248
1249 /* Right-up. */
1250 tri[3][0] = x + w; /* Inner. */
1251 tri[3][1] = y;
1252 tri[3][2] = x + w+thick; /* Outer. */
1253 tri[3][3] = y-thick;
1254 colours[6] = *lc;
1255 colours[7] = *lc;
1256
1257 /* Left-up. */
1258 tri[4][0] = x; /* Inner */
1259 tri[4][1] = y;
1260 tri[4][2] = x-thick; /* Outer */
1261 tri[4][3] = y-thick;
1262 colours[8] = *lc;
1263 colours[9] = *lc;
1264
1265 /* Upload to the VBO. */
1266 gl_vboSubData( toolkit_vbo, 0, sizeof(tri), tri );
1267 gl_vboSubData( toolkit_vbo, toolkit_vboColourOffset, sizeof(colours), colours );
1268
1269 gl_beginSmoothProgram(gl_view_matrix);
1270 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex, 0, 2, GL_SHORT, 0 );
1271 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex_color,
1272 toolkit_vboColourOffset, 4, GL_FLOAT, 0 );
1273 glDrawArrays( GL_TRIANGLE_STRIP, 0, 10 );
1274 gl_endSmoothProgram();
1275}
1276
1290void toolkit_drawOutline( int x, int y, int w, int h, int b,
1291 const glColour* c, const glColour* lc )
1292{
1293 GLshort lines[4][2];
1294 glColour colours[4];
1295
1296 x -= b, w += 2 * b;
1297 y -= b, h += 2 * b;
1298 lc = lc ? lc : c;
1299
1300 /* Lines. */
1301 lines[0][0] = x; /* left-up */
1302 lines[0][1] = y;
1303 colours[0] = *lc;
1304
1305 lines[1][0] = x; /* left-down */
1306 lines[1][1] = y + h;
1307 colours[1] = *c;
1308
1309 lines[2][0] = x + w; /* right-down */
1310 lines[2][1] = y + h;
1311 colours[2] = *c;
1312
1313 lines[3][0] = x + w; /* right-up */
1314 lines[3][1] = y;
1315 colours[3] = *lc;
1316
1317 /* Upload to the VBO. */
1318 gl_vboSubData( toolkit_vbo, 0, sizeof(lines), lines );
1319 gl_vboSubData( toolkit_vbo, toolkit_vboColourOffset, sizeof(colours), colours );
1320
1321 gl_beginSmoothProgram(gl_view_matrix);
1322 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex, 0, 2, GL_SHORT, 0 );
1323 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex_color,
1324 toolkit_vboColourOffset, 4, GL_FLOAT, 0 );
1325 glDrawArrays( GL_LINE_LOOP, 0, 4 );
1326 gl_endSmoothProgram();
1327}
1340void toolkit_drawRect( int x, int y, int w, int h,
1341 const glColour* c, const glColour* lc )
1342{
1343 GLshort vertex[4][2];
1344 glColour colours[4];
1345
1346 lc = lc == NULL ? c : lc;
1347
1348 /* Set up vertices and colours. */
1349 vertex[0][0] = x; /* left-up */
1350 vertex[0][1] = y;
1351 colours[0] = *c;
1352
1353 vertex[1][0] = x; /* left-down */
1354 vertex[1][1] = y + h;
1355 colours[1] = *lc;
1356
1357 vertex[2][0] = x + w; /* right-up */
1358 vertex[2][1] = y;
1359 colours[2] = *c;
1360
1361 vertex[3][0] = x + w; /* right-down */
1362 vertex[3][1] = y + h;
1363 colours[3] = *lc;
1364
1365 /* Upload to the VBO. */
1366 gl_vboSubData( toolkit_vbo, 0, sizeof(vertex), vertex );
1367 gl_vboSubData( toolkit_vbo, toolkit_vboColourOffset, sizeof(colours), colours );
1368
1369 gl_beginSmoothProgram(gl_view_matrix);
1370 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex, 0, 2, GL_SHORT, 0 );
1371 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex_color,
1372 toolkit_vboColourOffset, 4, GL_FLOAT, 0 );
1373 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
1374 gl_endSmoothProgram();
1375}
1376
1388void toolkit_drawTriangle( int x1, int y1, int x2, int y2, int x3, int y3,
1389 const glColour* c )
1390{
1391 GLshort vertex[3][2];
1392 glColour colours[3];
1393
1394 /* Set up vertices and colours. */
1395 vertex[0][0] = x1; /* left-up */
1396 vertex[0][1] = y1;
1397 colours[0] = *c;
1398
1399 vertex[1][0] = x2; /* left-down */
1400 vertex[1][1] = y2;
1401 colours[1] = *c;
1402
1403 vertex[2][0] = x3; /* right-up */
1404 vertex[2][1] = y3;
1405 colours[2] = *c;
1406
1407 /* Upload to the VBO. */
1408 gl_vboSubData( toolkit_vbo, 0, sizeof(vertex), vertex );
1409 gl_vboSubData( toolkit_vbo, toolkit_vboColourOffset, sizeof(colours), colours );
1410
1411 gl_beginSmoothProgram(gl_view_matrix);
1412 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex, 0, 2, GL_SHORT, 0 );
1413 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex_color,
1414 toolkit_vboColourOffset, 4, GL_FLOAT, 0 );
1415 glDrawArrays( GL_TRIANGLE_STRIP, 0, 3 );
1416 gl_endSmoothProgram();
1417}
1418
1426void toolkit_drawAltText( int bx, int by, const char *alt )
1427{
1428 double w, h;
1429 double x, y;
1430 glColour c;
1431 glColour c2;
1432
1433 /* We're on top of anything previously drawn. */
1434 glClear( GL_DEPTH_BUFFER_BIT );
1435
1436 /* Get dimensions. */
1437 w = MIN( gl_printWidthRaw( &gl_smallFont, alt ), 400 );
1438 h = gl_printHeightRaw( &gl_smallFont, w, alt );
1439
1440 /* Choose position. */
1441 x = bx + 10.;
1442 y = by - h - gl_smallFont.h - 10.;
1443 if (y < 10.)
1444 y = 10.;
1445 if (x+w+10. > gl_screen.nw)
1446 x -= w;
1447
1448 /* Set colours. */
1449 c.r = cGrey20.r;
1450 c.g = cGrey20.g;
1451 c.b = cGrey20.b;
1452 c.a = 0.9;
1453 c2.r = cGrey10.r;
1454 c2.g = cGrey10.g;
1455 c2.b = cGrey10.b;
1456 c2.a = 0.7;
1457 toolkit_drawRect( x+1, y+1, w+18, h+18, &c2, NULL );
1458 toolkit_drawRect( x, y, w+18, h+18, &c, NULL );
1459 gl_printTextRaw( &gl_smallFont, w, h, x + 9, y + 9, 0, &cFontWhite, -1., alt );
1460}
1461
1467static void window_renderBorder( Window* w )
1468{
1469 /* Position */
1470 double x = w->x;
1471 double y = w->y;
1472
1473 /*
1474 * Case fullscreen.
1475 */
1476 if (window_isFlag( w, WINDOW_FULLSCREEN )) {
1477 /* Background. */
1478 toolkit_drawRect( x, y, w->w, w->h, toolkit_col, NULL );
1479 /* Name. */
1480 gl_printMidRaw( &gl_defFont, w->w,
1481 x,
1482 y + w->h - 20.,
1483 &cFontWhite, -1., w->displayname );
1484 return;
1485 }
1486
1487 toolkit_drawRect( x, y, w->w, w->h, toolkit_col, NULL );
1488 toolkit_drawOutlineThick( x, y, w->w, w->h, 1, 2, toolkit_colDark, NULL );
1489 toolkit_drawOutline( x + 3, y + 2, w->w - 5, w->h - 5, 1, toolkit_colLight, NULL );
1490
1491 /*
1492 * render window name
1493 */
1494 gl_printMidRaw( &gl_defFont, w->w,
1495 x,
1496 y + w->h - 20.,
1497 &cFontWhite, -1., w->displayname );
1498}
1499
1505void window_render( Window *w )
1506{
1507 double x, y;
1508
1509 /* Do not render dead windows. */
1510 if (window_isFlag( w, WINDOW_KILL ))
1511 return;
1512
1513 /* position */
1514 x = w->x;
1515 y = w->y;
1516
1517 /* We're on top of anything previously drawn. */
1518 glClear( GL_DEPTH_BUFFER_BIT );
1519
1520 /* See if needs border. */
1521 if (!window_isFlag( w, WINDOW_NOBORDER ))
1523
1524 /*
1525 * widgets
1526 */
1527 for (Widget *wgt=w->widgets; wgt!=NULL; wgt=wgt->next) {
1528 if ((wgt->render != NULL) && !wgt_isFlag(wgt, WGT_FLAG_KILL)) {
1529 wgt->render( wgt, x, y );
1530
1531 if (wgt->id == w->focus) {
1532 double wx = x + wgt->x - 2;
1533 double wy = y + wgt->y - 2;
1534 toolkit_drawOutlineThick( wx, wy, wgt->w+4, wgt->h+4, 0, 2, (wgt->type == WIDGET_BUTTON ? &cGrey70 : &cGrey30), NULL );
1535 }
1536 }
1537 }
1538}
1539
1545void window_renderOverlay( Window *w )
1546{
1547 double x, y;
1548
1549 /* Do not render dead windows. */
1550 if (window_isFlag( w, WINDOW_KILL ))
1551 return;
1552
1553 /* position */
1554 x = w->x;
1555 y = w->y;
1556
1557 /*
1558 * overlays
1559 */
1560 for (Widget *wgt=w->widgets; wgt!=NULL; wgt=wgt->next)
1561 if ((wgt->renderOverlay != NULL) && !wgt_isFlag(wgt, WGT_FLAG_KILL))
1562 wgt->renderOverlay( wgt, x, y );
1563}
1564
1574void toolkit_drawScrollbar( int x, int y, int w, int h, double pos )
1575{
1576 double sy;
1577
1578 /* scrollbar background */
1579 toolkit_drawRect( x, y, w, h, &cGrey10, NULL );
1580
1581 /* Bar itself. */
1582 sy = y + (h - 30.) * (1.-pos);
1583 toolkit_drawRect( x, sy, w, 30., toolkit_colLight, NULL );
1584 toolkit_drawOutline( x+1, sy, w-2, 30., 0., toolkit_colDark, NULL );
1585}
1586
1590void toolkit_render( double dt )
1591{
1592 /* Render base. */
1593 for (Window *w = windows; w!=NULL; w = w->next) {
1594 if (window_isFlag(w, WINDOW_NORENDER | WINDOW_KILL))
1595 continue;
1596
1597 int use_fb = 0;
1598 double alpha = 1.;
1599 if (window_isFlag(w, WINDOW_FADEIN | WINDOW_FADEOUT)) {
1600 if (!window_isFlag(w, WINDOW_FADEDELAY) || (dt < fps_min))
1601 w->timer -= dt;
1602 window_rmFlag( w, WINDOW_FADEDELAY );
1603 if (w->timer > 0.) {
1604 alpha = ease_QuadraticInOut( w->timer / w->timer_max );
1605 if (window_isFlag(w, WINDOW_FADEIN))
1606 alpha = 1. - alpha;
1607
1608 if (alpha < 1.) {
1609 use_fb = 1;
1610 glBindFramebuffer( GL_FRAMEBUFFER, gl_screen.fbo[2] );
1611 glClearColor( 0., 0., 0., 0. );
1612 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1613 }
1614 }
1615 else {
1616 if (window_isFlag(w, WINDOW_FADEOUT)) {
1617 /* Mark for death. */
1618 window_kill( w );
1619 continue; /* No need to draw this iteration. */
1620 }
1621 window_rmFlag(w, WINDOW_FADEIN | WINDOW_FADEOUT);
1622 }
1623 }
1624
1625 /* The actual rendering. */
1626 window_render(w);
1628
1629 /* Drawing directly to the main framebuffer. */
1630 if (!use_fb)
1631 continue;
1632
1633 /* Must draw onto the main screen. */
1634 glColour col = { 1., 1., 1., alpha };
1635
1636 glBindFramebuffer(GL_FRAMEBUFFER, gl_screen.current_fbo);
1637 glClearColor( 0., 0., 0., 1. );
1638
1639 glUseProgram(shaders.texture.program);
1640
1641 /* Set texture. */
1642 glActiveTexture( GL_TEXTURE0 );
1643 glBindTexture( GL_TEXTURE_2D, gl_screen.fbo_tex[2] );
1644 glUniform1i(shaders.texture.sampler, 0);
1645
1646 /* Set vertex data. */
1647 glEnableVertexAttribArray( shaders.texture.vertex );
1648 gl_vboActivateAttribOffset( gl_squareVBO, shaders.texture.vertex,
1649 0, 2, GL_FLOAT, 0 );
1650
1651 /* Set shader uniforms. */
1652 gl_uniformColor(shaders.texture.color, &col);
1653 const mat4 ortho = mat4_ortho(0., 1., 0., 1., 1., -1.);
1654 const mat4 I = mat4_identity();
1655 gl_uniformMat4(shaders.texture.projection, &ortho);
1656 gl_uniformMat4(shaders.texture.tex_mat, &I);
1657
1658 /* Draw. */
1659 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
1660
1661 /* Clean up. */
1662 glDisableVertexAttribArray( shaders.texture.vertex );
1663 gl_checkErr();
1664 glUseProgram(0);
1665 }
1666}
1667
1674int toolkit_input( SDL_Event* event )
1675{
1676 /* Get window that can be focused. */
1677 Window *wdw = toolkit_getActiveWindow();
1678 if (wdw == NULL)
1679 return 0;
1680
1681 /* Pass event to window. */
1682 return toolkit_inputWindow( wdw, event, 1 );
1683}
1684
1688int toolkit_inputWindow( Window *wdw, SDL_Event *event, int purge )
1689{
1690 int ret;
1691
1692 /* See if widget needs event. */
1693 for (Widget *wgt=wdw->widgets; wgt!=NULL; wgt=wgt->next) {
1694 if (wgt_isFlag( wgt, WGT_FLAG_RAWINPUT )) {
1695 if (wgt->rawevent != NULL) {
1696 ret = wgt->rawevent( wgt, event );
1697 if (ret != 0)
1698 return ret;
1699 }
1700 }
1701 }
1702
1703 /* Event handler. */
1704 if (wdw->eventevent != NULL) {
1705 ret = wdw->eventevent( wdw->id, event );
1706 if (ret != 0)
1707 return ret;
1708 }
1709
1710 /* Hack in case window got destroyed in eventevent. */
1711 ret = 0;
1712 if (!window_isFlag(wdw, WINDOW_KILL | WINDOW_FADEOUT)) {
1713 /* Pass it on. */
1714 switch (event->type) {
1715 case SDL_MOUSEMOTION:
1716 case SDL_MOUSEBUTTONDOWN:
1717 case SDL_MOUSEBUTTONUP:
1718 case SDL_MOUSEWHEEL:
1719 ret |= toolkit_mouseEvent(wdw, event);
1720 break;
1721
1722 case SDL_KEYDOWN:
1723 case SDL_KEYUP:
1724 ret |= toolkit_keyEvent(wdw, event);
1725 break;
1726
1727 case SDL_TEXTINPUT:
1728 ret |= toolkit_textEvent(wdw, event);
1729 break;
1730 case SDL_TEXTEDITING:
1731 break;
1732 }
1733 }
1734
1735 /* Clean up the dead if needed. */
1736 if (purge && !dialogue_isOpen()) { /* Hack, since dialogues use secondary loop. */
1737 if (toolkit_delayCounter > 0)
1739 else
1741 }
1742
1743 return ret; /* don't block input */
1744}
1745
1757Uint32 toolkit_inputTranslateCoords( Window *w, SDL_Event *event,
1758 int *x, int *y, int *rx, int *ry )
1759{
1760 /* Extract the position as event. */
1761 if (event->type==SDL_MOUSEMOTION) {
1762 *x = event->motion.x;
1763 *y = event->motion.y;
1764 }
1765 else if ((event->type==SDL_MOUSEBUTTONDOWN) || (event->type==SDL_MOUSEBUTTONUP)) {
1766 *x = event->button.x;
1767 *y = event->button.y;
1768 }
1769 else if (event->type == SDL_MOUSEWHEEL)
1770 SDL_GetMouseState( x, y );
1771
1772 /* Translate offset. */
1773 gl_windowToScreenPos( x, y, *x, *y );
1774
1775 /* Transform to relative to window. */
1776 *x -= w->x;
1777 *y -= w->y;
1778
1779 /* Relative only matter if mouse motion. */
1780 if (event->type==SDL_MOUSEMOTION) {
1781 *ry = (double)event->motion.yrel * gl_screen.mxscale;
1782 *rx = (double)event->motion.xrel * gl_screen.myscale;
1783 }
1784 else {
1785 *ry = 0;
1786 *rx = 0;
1787 }
1788
1789 return event->type;
1790}
1791
1792static int toolkit_mouseEventSingle( Window *w, SDL_Event* event,
1793 Widget *wgt, int x, int y, int rx, int ry )
1794{
1795 int ret = 0;
1796 /* Custom widgets take it from here */
1797 if (wgt->type==WIDGET_CUST) {
1798 if (wgt->dat.cst.mouse)
1799 ret = wgt->dat.cst.mouse( w->id, event, x-wgt->x, y-wgt->y, wgt->w, wgt->h, rx, ry,
1800 wgt->dat.cst.userdata );
1801 }
1802 else
1803 ret = toolkit_mouseEventWidget( w, wgt, event, x, y, rx, ry );
1804 return ret;
1805}
1806static int toolkit_mouseEventReverse( Window *w, SDL_Event* event,
1807 Widget *wgt, int x, int y, int rx, int ry )
1808{
1809 if (wgt->next!=NULL) {
1810 int ret = toolkit_mouseEventReverse( w, event, wgt->next, x, y, rx, ry );
1811 if (ret)
1812 return ret;
1813 }
1814
1815 return toolkit_mouseEventSingle( w, event, wgt, x, y, rx, ry );
1816}
1823static int toolkit_mouseEvent( Window *w, SDL_Event* event )
1824{
1825 int x, y, rx, ry;
1826
1827 /* Translate mouse coords. */
1828 toolkit_inputTranslateCoords( w, event, &x, &y, &rx, &ry );
1829
1830 /* Check each widget. */
1831 if (w->widgets != NULL)
1832 return toolkit_mouseEventReverse( w, event, w->widgets, x, y, rx, ry );
1833 return 0;
1834}
1835
1847static int toolkit_mouseEventWidget( Window *w, Widget *wgt,
1848 SDL_Event *event, int x, int y, int rx, int ry )
1849{
1850 int ret, inbounds;
1851 Uint8 button;
1852
1853 /* Widget translations. */
1854 x -= wgt->x;
1855 y -= wgt->y;
1856
1857 /* Handle mouse event. */
1858 if (event->type == SDL_MOUSEMOTION)
1859 button = event->motion.state;
1860 else
1861 button = event->button.button;
1862
1863 /* Check inbounds. */
1864 inbounds = !((x < 0) || (x >= wgt->w) || (y < 0) || (y >= wgt->h));
1865
1866 /* Regular widgets. */
1867 ret = 0;
1868 switch (event->type) {
1869 case SDL_MOUSEMOTION:
1870 /* Change the status of the widget if mouse isn't down. */
1871
1872 /* Not scrolling. */
1873 if (wgt->status != WIDGET_STATUS_SCROLLING) {
1874 if (inbounds) {
1875 if (wgt->status != WIDGET_STATUS_MOUSEDOWN)
1876 wgt->status = WIDGET_STATUS_MOUSEOVER;
1877 }
1878 else
1879 wgt->status = WIDGET_STATUS_NORMAL;
1880 }
1881 else
1882 inbounds = 1; /* Scrolling is always inbounds. */
1883
1884 /* If always gets the event. */
1885 if (wgt_isFlag( wgt, WGT_FLAG_ALWAYSMMOVE ))
1886 inbounds = 1;
1887
1888 /* Try to give the event to the widget. */
1889 if (inbounds && (wgt->mmoveevent != NULL))
1890 ret |= (*wgt->mmoveevent)( wgt, x, y, rx, ry );
1891
1892 break;
1893
1894 case SDL_MOUSEWHEEL:
1895 if (!inbounds)
1896 break;
1897
1898 /* Try to give the event to the widget. */
1899 if (wgt->mwheelevent != NULL)
1900 ret |= (*wgt->mwheelevent)( wgt, event->wheel );
1901
1902 break;
1903
1904 case SDL_MOUSEBUTTONDOWN:
1905 if (!inbounds)
1906 break;
1907
1908 /* Update the status. */
1909 if (button == SDL_BUTTON_LEFT)
1910 wgt->status = WIDGET_STATUS_MOUSEDOWN;
1911
1912 if (toolkit_isFocusable(wgt)) {
1913 toolkit_focusClear( w );
1914 toolkit_focusWidget( w, wgt );
1915 }
1916
1917 /* Try to give the event to the widget. */
1918 if (wgt->mdoubleclickevent != NULL && input_isDoubleClick( (void*)wgt ))
1919 ret |= (*wgt->mdoubleclickevent)( wgt, button, x, y );
1920 else if (wgt->mclickevent != NULL)
1921 ret |= (*wgt->mclickevent)( wgt, button, x, y );
1922 if (ret)
1923 input_clicked( (void*)wgt );
1924 break;
1925
1926 case SDL_MOUSEBUTTONUP:
1927 /* Since basically only buttons are handled here, we ignore
1928 * it all except the left mouse button. */
1929 if (button != SDL_BUTTON_LEFT)
1930 break;
1931
1932 if (wgt->status==WIDGET_STATUS_MOUSEDOWN) {
1933 /* Soft-disabled buttons will run anyway. */
1934 if ((wgt->type==WIDGET_BUTTON) && ((wgt->dat.btn.disabled==0) ||
1935 (wgt->dat.btn.softdisable))) {
1936 if (wgt->dat.btn.fptr==NULL)
1937 DEBUG(_("Toolkit: Button '%s' of Window '%s' "
1938 "doesn't have a function trigger"),
1939 wgt->name, w->displayname );
1940 else {
1941 (*wgt->dat.btn.fptr)(w->id, wgt->name);
1942 ret = 1;
1943 }
1944 }
1945 }
1946
1947 /* Signal scroll done if necessary. */
1948 if ((wgt->status == WIDGET_STATUS_SCROLLING) && (wgt->scrolldone != NULL))
1949 wgt->scrolldone( wgt );
1950
1951 /* Always goes normal unless is below mouse. */
1952 if (inbounds)
1953 wgt->status = WIDGET_STATUS_MOUSEOVER;
1954 else
1955 wgt->status = WIDGET_STATUS_NORMAL;
1956
1957 break;
1958 }
1959
1960 return ret;
1961}
1962
1969static SDL_Keymod toolkit_mapMod( SDL_Keycode key )
1970{
1971 switch(key) {
1972 case SDLK_LCTRL:
1973 return KMOD_LCTRL;
1974 case SDLK_RCTRL:
1975 return KMOD_RCTRL;
1976 case SDLK_LALT:
1977 return KMOD_LALT;
1978 case SDLK_RALT:
1979 return KMOD_RALT;
1980 case SDLK_LSHIFT:
1981 return KMOD_LSHIFT;
1982 case SDLK_RSHIFT:
1983 return KMOD_RSHIFT;
1984 default:
1985 return 0;
1986 }
1987}
1988
1994static void toolkit_regKey( SDL_Keycode key )
1995{
1996 SDL_Keymod mod;
1997
1998 /* See if our key is in fact a modifier key, and if it is, convert it to a mod.
1999 * If it is indeed a mod, do not register a new key but add the modifier to the mod mask instead.
2000 */
2001 mod = toolkit_mapMod(key);
2002 if (mod)
2003 input_mod |= mod;
2004 /* Don't reset values on repeat keydowns. */
2005 else if (input_key != key) {
2006 input_key = key;
2007 }
2008}
2009
2015static void toolkit_unregKey( SDL_Keycode key )
2016{
2017 SDL_Keymod mod;
2018
2019 /* See if our key is in fact a modifier key, and if it is, convert it to a mod.
2020 * If it is indeed a mod, do not unregister the key but subtract the modifier from the mod mask instead.
2021 */
2022 mod = toolkit_mapMod(key);
2023 if (mod)
2024 input_mod &= ~mod;
2025 else
2027}
2028
2033{
2034 input_key = 0;
2035}
2043static int toolkit_keyEvent( Window *wdw, SDL_Event* event )
2044{
2045 Widget *wgt;
2046 SDL_Keycode key;
2047 SDL_Keymod mod;
2048 int ret;
2049
2050 /* Event info. */
2051 key = event->key.keysym.sym;
2052 mod = event->key.keysym.mod;
2053
2054 /* Hack to simulate key repetition */
2055 if (event->type == SDL_KEYDOWN)
2056 toolkit_regKey(key);
2057 else if (event->type == SDL_KEYUP)
2058 toolkit_unregKey(key);
2059
2060 /* See if window is valid. */
2061 if (wdw == NULL)
2062 return 0;
2063
2064 /* Get widget. */
2065 wgt = toolkit_getFocus( wdw );
2066
2067 /* We only want keydown from now on. */
2068 if (event->type != SDL_KEYDOWN)
2069 return 0;
2070
2071 /* Trigger event function if exists. */
2072 if (wgt != NULL) {
2073 if (wgt->keyevent != NULL) {
2074 ret = wgt->keyevent( wgt, input_key, input_mod );
2075 if (ret!=0)
2076 return ret;
2077 }
2078 }
2079
2080 if (input_key != 0 && !event->key.repeat) {
2081 /* Handle button hotkeys. We don't want a held-down key to keep activating buttons, so forbid "repeat". */
2082 for ( wgt = wdw->widgets; wgt != NULL; wgt = wgt->next ) {
2083 if ( ( wgt->type == WIDGET_BUTTON ) && ( wgt->dat.btn.key == input_key )
2084 && wgt->keyevent != NULL ) {
2085 ret = wgt->keyevent( wgt, SDLK_RETURN, input_mod );
2086 if (ret!=0)
2087 return ret;
2088 }
2089 }
2090
2091 /* Handle other cases where event might be used by the window... and we don't want key-repeat. */
2092 switch (key) {
2093 case SDLK_RETURN:
2094 case SDLK_KP_ENTER:
2095 if (wdw->accept_fptr != NULL) {
2096 wdw->accept_fptr( wdw->id, wdw->name );
2097 return 1;
2098 }
2099 break;
2100
2101 case SDLK_ESCAPE:
2102 if (wdw->cancel_fptr != NULL) {
2103 wdw->cancel_fptr( wdw->id, wdw->name );
2104 return 1;
2105 }
2106 break;
2107
2108 default:
2109 break;
2110 }
2111 }
2112
2113 /* Finally the stuff gets passed to the custom key handler if it's defined. */
2114 if (wdw->keyevent != NULL) {
2115 ret = (*wdw->keyevent)( wdw->id, input_key, input_mod );
2116 if (ret!=0)
2117 return ret;
2118 }
2119
2120 /* Placed here so it can be overriden in console for tab completion. */
2121 if (key == SDLK_TAB) {
2122 if (mod & (KMOD_LSHIFT | KMOD_RSHIFT))
2123 toolkit_prevFocus( wdw );
2124 else
2125 toolkit_nextFocus( wdw );
2126 return 1;
2127 }
2128
2129 return 0;
2130}
2131static int toolkit_textEvent( Window *wdw, SDL_Event* event )
2132{
2133 Widget *wgt;
2134 int ret;
2135
2136 /* See if window is valid. */
2137 if (wdw == NULL)
2138 return 0;
2139
2140 /* Get widget. */
2141 wgt = toolkit_getFocus( wdw );
2142
2143 /* Trigger event function if exists. */
2144 if ((wgt != NULL) && (wgt->textevent != NULL)) {
2145 ret = (*wgt->textevent)( wgt, event->text.text );
2146 if (ret!=0)
2147 return ret;
2148 }
2149
2150 return 0;
2151}
2152
2156static void toolkit_purgeDead (void)
2157{
2158 Window *wdw, *wlast;
2159
2160 /* Must be windows. */
2161 if (windows == NULL)
2162 return;
2163
2164 /* Destroy what is needed. */
2165 wlast = NULL;
2166 wdw = windows;
2167 while (wdw != NULL) {
2168 if (window_isFlag( wdw, WINDOW_KILL )) {
2169 /* Save target. */
2170 Window *wkill = wdw;
2171 /* Reattach linked list. */
2172 if (wlast == NULL)
2173 windows = wdw->next;
2174 else
2175 wlast->next = wdw->next;
2176 wdw = wlast;
2177 /* Kill target. */
2178 wkill->next = NULL;
2179 window_remove( wkill );
2180 }
2181 else {
2182 Widget *wgtlast = NULL;
2183 Widget *wgt = wdw->widgets;
2184 while (wgt != NULL) {
2185 if (wgt_isFlag( wgt, WGT_FLAG_KILL )) {
2186 /* Save target. */
2187 Widget *wgtkill = wgt;
2188 /* Reattach linked list. */
2189 if (wgtlast == NULL)
2190 wdw->widgets = wgt->next;
2191 else
2192 wgtlast->next = wgt->next;
2193 wgt = wgtlast;
2194 /* Kill target. */
2195 wgtkill->next = NULL;
2196 widget_kill( wgtkill );
2197 }
2198 /* Save position. */
2199 wgtlast = wgt;
2200 if (wgt == NULL)
2201 wgt = wdw->widgets;
2202 else
2203 wgt = wgt->next;
2204 }
2205 }
2206 /* Save position. */
2207 wlast = wdw;
2208 if (wdw == NULL)
2209 wdw = windows;
2210 else
2211 wdw = wdw->next;
2212 }
2213}
2214
2219{
2220 /* Clean up the dead if needed. */
2221 if (!dialogue_isOpen()) { /* Hack, since dialogues use secondary loop. */
2222 if (toolkit_delayCounter > 0)
2224 else
2226 }
2227
2228 /* Killed all the windows. */
2229 if (!toolkit_isOpen()) {
2230
2232 if (paused && !player_paused)
2233 unpause_game();
2234 }
2235}
2236
2243static void toolkit_expose( Window *wdw, int expose )
2244{
2245 if (expose == wdw->exposed)
2246 return;
2247 else
2248 wdw->exposed = expose;
2249
2250 if (expose)
2251 toolkit_focusSanitize( wdw );
2252 else
2253 toolkit_focusClear( wdw );
2254
2255 if (wdw->focus != -1)
2256 return;
2257
2258 /* Notify widgets (for tabbed children, etc.) */
2259 for (Widget *wgt = wdw->widgets; wgt != NULL; wgt = wgt->next)
2260 if (wgt->exposeevent != NULL)
2261 wgt->exposeevent( wgt, expose );
2262}
2263
2267void toolkit_focusClear( Window *wdw )
2268{
2269 if (wdw->focus == -1)
2270 return;
2271
2272 for (Widget *wgt=wdw->widgets; wgt!=NULL; wgt=wgt->next)
2273 toolkit_defocusWidget( wdw, wgt );
2274}
2275
2281void toolkit_focusSanitize( Window *wdw )
2282{
2283 int focus = wdw->focus;
2284
2285 /* Clear focus. */
2286 toolkit_focusClear( wdw );
2287
2288 /* No focus is always safe. */
2289 if (focus == -1)
2290 return;
2291
2292 /* Check focused widget. */
2293 for (Widget *wgt=wdw->widgets; wgt!=NULL; wgt=wgt->next) {
2294 if (focus == wgt->id) {
2295 /* Not focusable. */
2296 if (!toolkit_isFocusable(wgt))
2297 toolkit_nextFocus( wdw ); /* Get first focus. */
2298 else
2299 toolkit_focusWidget( wdw, wgt );
2300
2301 return;
2302 }
2303 }
2304}
2305
2309void toolkit_nextFocus( Window *wdw )
2310{
2311 int next;
2312
2313 /* Clear focus. */
2314 toolkit_focusClear( wdw );
2315
2316 /* See what to focus. */
2317 next = (wdw->focus == -1);
2318 for (Widget *wgt=wdw->widgets; wgt!=NULL; wgt=wgt->next) {
2319 if (!toolkit_isFocusable(wgt))
2320 continue;
2321
2322 if (next) {
2323 toolkit_focusWidget( wdw, wgt );
2324 return;
2325 }
2326 else if (wdw->focus == wgt->id) {
2327 next = 1;
2328 }
2329 }
2330
2331 /* Focus nothing. */
2332 wdw->focus = -1;
2333 return;
2334}
2335
2339void toolkit_prevFocus( Window *wdw )
2340{
2341 Widget *prev;
2342 int focus = wdw->focus;
2343
2344 /* Clear focus. */
2345 toolkit_focusClear( wdw );
2346
2347 /* See what to focus. */
2348 prev = NULL;
2349 for (Widget *wgt=wdw->widgets; wgt!=NULL; wgt=wgt->next) {
2350 if (!toolkit_isFocusable(wgt))
2351 continue;
2352
2353 /* See if we found the current one. */
2354 if (focus == wgt->id) {
2355 if (prev != NULL)
2356 toolkit_focusWidget( wdw, prev );
2357 return;
2358 }
2359
2360 /* Store last focusable widget. */
2361 prev = wgt;
2362 }
2363
2364 /* Focus nothing. */
2365 if (prev != NULL)
2366 toolkit_focusWidget( wdw, prev );
2367
2368 return;
2369}
2370
2374void toolkit_focusWidget( Window *wdw, Widget *wgt )
2375{
2376 if (!toolkit_isFocusable(wgt) || wgt_isFlag( wgt, WGT_FLAG_FOCUSED ))
2377 return;
2378
2379 wdw->focus = wgt->id;
2380 wgt_setFlag( wgt, WGT_FLAG_FOCUSED );
2381 if (wgt->focusGain != NULL)
2382 wgt->focusGain( wgt );
2383}
2384
2389void toolkit_defocusWidget( Window *wdw, Widget *wgt )
2390{
2391 if (wdw->focus != wgt->id || !wgt_isFlag( wgt, WGT_FLAG_FOCUSED ))
2392 return;
2393
2394 wdw->focus = -1;
2395 wgt_rmFlag( wgt, WGT_FLAG_FOCUSED );
2396 if (wgt->focusLose != NULL)
2397 wgt->focusLose( wgt );
2398}
2399
2406static int toolkit_isFocusable( Widget *wgt )
2407{
2408 if (wgt==NULL)
2409 return 0;
2410
2411 return wgt_isFlag(wgt, WGT_FLAG_CANFOCUS);
2412}
2413
2420{
2421 /* Get window that can be focused. */
2422 Window *wlast = NULL;
2423 for (Window *wdw = windows; wdw!=NULL; wdw = wdw->next)
2424 if (!window_isFlag(wdw, WINDOW_NOFOCUS) &&
2425 !window_isFlag(wdw, WINDOW_KILL | WINDOW_FADEOUT))
2426 wlast = wdw;
2427 return wlast;
2428}
2429
2436static Widget* toolkit_getFocus( Window *wdw )
2437{
2438 /* No focus. */
2439 if (wdw->focus == -1)
2440 return NULL;
2441
2442 /* Find focus. */
2443 for (Widget *wgt=wdw->widgets; wgt!=NULL; wgt=wgt->next)
2444 if (wdw->focus == wgt->id)
2445 return wgt;
2446
2447 /* Not found. */
2448 toolkit_focusClear( wdw );
2449 wdw->focus = -1;
2450 return NULL;
2451}
2452
2460void window_setFocus( unsigned int wid, const char* wgtname )
2461{
2462 Window *wdw;
2463 Widget *wgt;
2464
2465 /* Get window. */
2466 wdw = window_wget(wid);
2467 if (wdw == NULL)
2468 return;
2469
2470 toolkit_focusClear( wdw );
2471
2472 /* Get widget. */
2473 wgt = wgtname==NULL ? NULL : window_getwgt( wid, wgtname );
2474 if (wgt == NULL)
2475 return;
2476
2477 toolkit_focusWidget( wdw, wgt );
2478}
2479
2486char* window_getFocus( unsigned int wid )
2487{
2488 /* Get window. */
2489 Window *wdw = window_wget(wid);
2490 if (wdw == NULL)
2491 return NULL;
2492
2493 /* Find focused widget. */
2494 for (Widget *wgt=wdw->widgets; wgt!=NULL; wgt=wgt->next)
2495 if (wgt->id == wdw->focus)
2496 return strdup( wgt->name );
2497
2498 return NULL;
2499}
2500
2506void window_raise( unsigned int wid )
2507{
2508 Window *wdw, *wtmp, *wprev, *wlast;
2509
2510 wdw = window_wget(wid);
2511
2512 /* Not found, or already top of the stack. */
2513 if (wdw == NULL || wdw->next == NULL)
2514 return;
2515
2516 wprev = NULL;
2517 wlast = NULL;
2518
2519 for (wtmp = windows; wtmp != NULL; wtmp = wtmp->next)
2520 if (wtmp->next == wdw)
2521 wprev = wtmp;
2522 else if (wtmp->next == NULL)
2523 wlast = wtmp;
2524
2525 if (wprev != NULL)
2526 wprev->next = wdw->next; /* wdw-1 links to wdw+1 */
2527
2528 if (wlast != NULL)
2529 wlast->next = wdw; /* last links to wdw */
2530
2531 wdw->next = NULL; /* wdw becomes new last window */
2532
2533 wtmp = toolkit_getActiveWindow();
2534
2535 /* No active window, or window is the same. */
2536 if (wtmp == NULL || wtmp == wdw)
2537 return;
2538
2539 toolkit_expose( wtmp, 0 ); /* wtmp is hidden */
2540 toolkit_expose( wdw, 1 ); /* wdw is visible */
2541}
2542
2548void window_lower( unsigned int wid )
2549{
2550 Window *wdw, *wtmp, *wprev;
2551
2552 wdw = window_wget(wid);
2553
2554 /* Not found, or already bottom of the stack. */
2555 if (wdw == NULL || wdw == windows)
2556 return;
2557
2558 wprev = NULL;
2559 for (wtmp = windows; wtmp != NULL; wtmp = wtmp->next)
2560 if (wtmp->next == wdw)
2561 wprev = wtmp;
2562
2563 if (wprev != NULL)
2564 wprev->next = wdw->next; /* wdw-1 links to wdw+1 */
2565
2566 wdw->next = windows; /* wdw links to first window */
2567 windows = wdw; /* wdw becomes new first window */
2568
2569 wtmp = toolkit_getActiveWindow();
2570
2571 /* No active window, or window is the same. */
2572 if (wtmp == NULL || wtmp == wdw)
2573 return;
2574
2575 toolkit_expose( wtmp, 1 ); /* wtmp is visible */
2576 toolkit_expose( wdw, 0 ); /* wdw is hidden */
2577}
2578
2583{
2584 for (Window *w = windows; w != NULL; w = w->next) {
2585 int xorig, yorig, xdiff, ydiff;
2586
2587 /* Fullscreen windows must always be full size, though their widgets
2588 * don't auto-scale. */
2589 if (window_isFlag( w, WINDOW_FULLSCREEN )) {
2590 w->w = gl_screen.nw;
2591 w->h = gl_screen.nh;
2592 continue;
2593 }
2594
2595 /* Skip if position is fixed. */
2596 if (w->xrel == -1. && w->yrel == -1.)
2597 continue;
2598
2599 xdiff = 0.;
2600 ydiff = 0.;
2601
2602 if (w->xrel != -1.) {
2603 xorig = w->x;
2604 w->x = (gl_screen.nw - w->w) * w->xrel;
2605 xdiff = w->x - xorig;
2606 }
2607
2608 if (w->yrel != -1.) {
2609 yorig = w->y;
2610 w->y = (gl_screen.nh - w->h) * w->yrel;
2611 ydiff = w->y - yorig;
2612 }
2613
2614 /* Tabwin children aren't in the stack and must be manually updated. */
2615 for (Widget *wgt=w->widgets; wgt!=NULL; wgt=wgt->next) {
2616 if (wgt->type != WIDGET_TABBEDWINDOW)
2617 continue;
2618
2619 for (int i=0; i<wgt->dat.tab.ntabs; i++) {
2620 Window *wtmp = window_wget( wgt->dat.tab.windows[i] );
2621 wtmp->x += xdiff;
2622 wtmp->y += ydiff;
2623 }
2624 }
2625 }
2626}
2627
2634{
2635 GLsizei size;
2636
2637 /* Create the VBO. */
2638 toolkit_vboColourOffset = sizeof(GLshort) * 2 * 31;
2639 size = (sizeof(GLshort)*2 + sizeof(GLfloat)*4) * 31;
2640 toolkit_vbo = gl_vboCreateStream( size, NULL );
2641
2642 /* Disable the cursor. */
2644
2645 return 0;
2646}
2647
2651void toolkit_exit (void)
2652{
2653 Window *wdw;
2654
2655 /* Destroy the windows. */
2656 while (windows!=NULL) {
2657 wdw = windows;
2658 windows = windows->next;
2659 window_remove(wdw);
2660 }
2661
2662 /* Free the VBO. */
2664 toolkit_vbo = NULL;
2665}
int dialogue_isOpen(void)
Checks to see if a dialogue is open.
Definition: dialogue.c:98
int gl_printHeightRaw(const glFont *ft_font, const int width, const char *text)
Gets the height of a non-formatted string.
Definition: font.c:1026
glFont gl_smallFont
Definition: font.c:154
int gl_printWidthRaw(const glFont *ft_font, const char *text)
Gets the width that it would take to print some text.
Definition: font.c:960
glFont gl_defFont
Definition: font.c:153
int gl_printMidRaw(const glFont *ft_font, int width, double x, double y, const glColour *c, double outlineR, const char *text)
Displays text centered in position and width.
Definition: font.c:787
int gl_printTextRaw(const glFont *ft_font, const int width, const int height, double bx, double by, int line_height, const glColour *c, double outlineR, const char *text)
Prints a block of text that fits in the dimensions given.
Definition: font.c:869
void input_clicked(void *clicked)
Sets the last-clicked item, for double-click detection.
Definition: input.c:1453
void input_mouseShow(void)
Shows the mouse.
Definition: input.c:373
int input_isDoubleClick(void *clicked)
Checks whether a clicked item is the same as the last-clicked.
Definition: input.c:1466
void input_mouseHide(void)
Hides the mouse.
Definition: input.c:382
mat4 mat4_identity(void)
Creates an identity matrix.
Definition: mat4.c:195
mat4 mat4_ortho(double left, double right, double bottom, double top, double nearVal, double farVal)
Creates an orthographic projection matrix.
Definition: mat4.c:209
const double fps_min
Definition: naev.c:118
Header file with generic functions and naev-specifics.
#define MIN(x, y)
Definition: naev.h:40
double ease_QuadraticInOut(double x)
Simple symmetric quadratic easing.
Definition: nmath.c:114
void gl_defViewport(void)
Resets viewport to default.
Definition: opengl.c:608
void gl_windowToScreenPos(int *sx, int *sy, int wx, int wy)
Translates the window position to screen position.
Definition: opengl.c:616
glInfo gl_screen
Definition: opengl.c:51
void gl_vboDestroy(gl_vbo *vbo)
Destroys a VBO.
Definition: opengl_vbo.c:248
gl_vbo * gl_vboCreateStream(GLsizei size, const void *data)
Creates a stream vbo.
Definition: opengl_vbo.c:147
void gl_vboActivateAttribOffset(gl_vbo *vbo, GLuint index, GLuint offset, GLint size, GLenum type, GLsizei stride)
Activates a VBO's offset.
Definition: opengl_vbo.c:228
void gl_vboSubData(gl_vbo *vbo, GLint offset, GLsizei size, const void *data)
Loads some data into the VBO.
Definition: opengl_vbo.c:132
void pause_game(void)
Pauses the game.
Definition: pause.c:28
int player_paused
Definition: pause.c:22
int paused
Definition: pause.c:21
void unpause_game(void)
Unpauses the game.
Definition: pause.c:46
static const double c[]
Definition: rng.c:264
static const double b[]
Definition: rng.c:256
int h
Definition: font.h:18
double myscale
Definition: opengl.h:54
GLuint fbo_tex[OPENGL_NUM_FBOS]
Definition: opengl.h:68
double mxscale
Definition: opengl.h:53
GLuint fbo[OPENGL_NUM_FBOS]
Definition: opengl.h:67
int nw
Definition: opengl.h:43
int nh
Definition: opengl.h:44
GLuint current_fbo
Definition: opengl.h:66
Definition: mat4.h:10
unsigned int window_createFlags(const char *name, const char *displayname, const int x, const int y, const int w, const int h, unsigned int flags)
Creates a window.
Definition: toolkit.c:714
unsigned int window_create(const char *name, const char *displayname, const int x, const int y, const int w, const int h)
Creates a window.
Definition: toolkit.c:696
void toolkit_defocusWidget(Window *wdw, Widget *wgt)
Defocuses the focused widget in a window. No-op if it's not (de)focusable or already defocused,...
Definition: toolkit.c:2389
static GLsizei toolkit_vboColourOffset
Definition: toolkit.c:68
void toolkit_update(void)
Updates the toolkit input for repeating keys.
Definition: toolkit.c:2218
void window_dimWidget(unsigned int wid, const char *name, int *w, int *h)
Gets the dimensions of a widget.
Definition: toolkit.c:416
static void window_renderBorder(Window *w)
Renders a window border.
Definition: toolkit.c:1467
void toolkit_exit(void)
Exits the toolkit.
Definition: toolkit.c:2651
static Widget * toolkit_getFocus(Window *wdw)
Gets the focused widget in a window.
Definition: toolkit.c:2436
void window_setFade(unsigned int wid, const SimpleShader *shd, double length)
Sets the fade-in behaviour of a window.
Definition: toolkit.c:646
unsigned int window_getParent(unsigned int wid)
Gets the window's parent.
Definition: toolkit.c:820
void toolkit_drawScrollbar(int x, int y, int w, int h, double pos)
Draws a scrollbar.
Definition: toolkit.c:1574
static SDL_Keymod toolkit_mapMod(SDL_Keycode key)
Maps modifier keysyms (ctrl, alt, shift) to SDL_Keymods.
Definition: toolkit.c:1969
void window_setFocus(unsigned int wid, const char *wgtname)
Sets the focused widget in a window.
Definition: toolkit.c:2460
static unsigned int genwid
Definition: toolkit.c:29
const glColour * toolkit_col
Definition: toolkit.c:52
static void toolkit_purgeDead(void)
Purges the dead windows.
Definition: toolkit.c:2156
void window_setAccept(unsigned int wid, void(*accept)(unsigned int, const char *))
Sets the default accept function of the window.
Definition: toolkit.c:879
void window_dimWindow(unsigned int wid, int *w, int *h)
Gets the dimensions of a window.
Definition: toolkit.c:371
int toolkit_isOpen(void)
Checks to see if the toolkit is open.
Definition: toolkit.c:95
void window_move(unsigned int wid, int x, int y)
Moves a window to the specified coordinates.
Definition: toolkit.c:180
void window_setCancel(unsigned int wid, void(*cancel)(unsigned int, const char *))
Sets the default cancel function of the window.
Definition: toolkit.c:900
static int toolkit_mouseEvent(Window *w, SDL_Event *event)
Handles the mouse events.
Definition: toolkit.c:1823
Window * window_wgetW(unsigned int wid)
Gets a Window by ID, without warning.
Definition: toolkit.c:317
static const double WINDOW_FADEOUT_TIME
Definition: toolkit.c:34
int window_existsID(unsigned int wid)
Checks to see if a window with a certain ID exists.
Definition: toolkit.c:614
static const double WINDOW_FADEIN_TIME
Definition: toolkit.c:33
static void widget_kill(Widget *wgt)
Destroy a widget really.
Definition: toolkit.c:1192
static void toolkit_unregKey(SDL_Keycode key)
Unregisters a key.
Definition: toolkit.c:2015
void toolkit_drawAltText(int bx, int by, const char *alt)
Draws an alt text.
Definition: toolkit.c:1426
const glColour * tab_background
Definition: toolkit.c:62
const glColour * tab_inactiveB
Definition: toolkit.c:61
void toolkit_closeAll(void)
Closes all open toolkit windows.
Definition: toolkit.c:1019
Window * window_wget(unsigned int wid)
Gets a Window by ID.
Definition: toolkit.c:299
static int toolkit_mouseEventWidget(Window *w, Widget *wgt, SDL_Event *event, int x, int y, int rx, int ry)
Handle widget mouse input.
Definition: toolkit.c:1847
void window_onClose(unsigned int wid, void(*fptr)(unsigned int, const char *))
Sets the default close function of the window.
Definition: toolkit.c:840
const glColour * tab_inactive
Definition: toolkit.c:60
void window_canFocusWidget(unsigned int wid, const char *name, int canfocus)
Allows or disallows focusing a widget.
Definition: toolkit.c:523
void toolkit_clearKey(void)
Clears the registered keys.
Definition: toolkit.c:2032
void window_raise(unsigned int wid)
Raises a window (causes all other windows to appear below it).
Definition: toolkit.c:2506
void toolkit_drawRect(int x, int y, int w, int h, const glColour *c, const glColour *lc)
Draws a rectangle.
Definition: toolkit.c:1340
static void window_remove(Window *wdw)
Frees up a window.
Definition: toolkit.c:1103
static SDL_Keycode input_key
Definition: toolkit.c:45
static int toolkit_delayCounter
Definition: toolkit.c:31
void toolkit_focusSanitize(Window *wdw)
Sanitizes the focus of a window.
Definition: toolkit.c:2281
void window_moveWidget(unsigned int wid, const char *name, int x, int y)
Moves a widget.
Definition: toolkit.c:467
void window_handleKeys(unsigned int wid, int(*keyhandler)(unsigned int, SDL_Keycode, SDL_Keymod))
Sets the key handler for the window.
Definition: toolkit.c:972
const glColour * tab_activeB
Definition: toolkit.c:59
Widget * window_newWidget(Window *w, const char *name)
Allocates room for a new widget.
Definition: toolkit.c:227
Widget * window_getwgt(unsigned int wid, const char *name)
Gets a widget from window id and widgetname.
Definition: toolkit.c:346
void window_resize(unsigned int wid, int w, int h)
Resizes the window.
Definition: toolkit.c:197
void toolkit_drawTriangle(int x1, int y1, int x2, int y2, int x3, int y3, const glColour *c)
Draws a rectangle.
Definition: toolkit.c:1388
void toolkit_delay(void)
Delays the toolkit purge by an iteration, useful for dialogues.
Definition: toolkit.c:107
void toolkit_focusWidget(Window *wdw, Widget *wgt)
Focuses a widget in a window. No-op if it's not focusable or already focused.
Definition: toolkit.c:2374
void window_posWidget(unsigned int wid, const char *name, int *x, int *y)
Gets a widget's position.
Definition: toolkit.c:442
static void toolkit_expose(Window *wdw, int expose)
Exposes or hides a window and notifies its widgets.
Definition: toolkit.c:2243
int toolkit_init(void)
Initializes the toolkit.
Definition: toolkit.c:2633
Window * window_wgetNameW(const char *name)
Gets a Window by name, without warning.
Definition: toolkit.c:331
void toolkit_setPos(Window *wdw, Widget *wgt, int x, int y)
Sets the internal widget position.
Definition: toolkit.c:120
void window_destroyWidget(unsigned int wid, const char *wgtname)
Destroys a widget in a window.
Definition: toolkit.c:1162
int widget_isCovered(unsigned int wid, const char *name, int x, int y)
Checks to see if a widget is covered or not.
Definition: toolkit.c:568
static gl_vbo * toolkit_vbo
Definition: toolkit.c:67
void toolkit_setWindowPos(Window *wdw, int x, int y)
Moves a window to the specified coordinates.
Definition: toolkit.c:142
void toolkit_render(double dt)
Renders the windows.
Definition: toolkit.c:1590
void toolkit_drawOutlineThick(int x, int y, int w, int h, int b, int thick, const glColour *c, const glColour *lc)
Draws an outline.
Definition: toolkit.c:1213
void toolkit_prevFocus(Window *wdw)
Focus previous widget.
Definition: toolkit.c:2339
int window_isTop(unsigned int wid)
Checks to see if a window is at the top.
Definition: toolkit.c:551
static int toolkit_isFocusable(Widget *wgt)
Checks to see if a widget is focusable.
Definition: toolkit.c:2406
const glColour * toolkit_colDark
Definition: toolkit.c:53
void window_render(Window *w)
Renders a window.
Definition: toolkit.c:1505
Uint32 toolkit_inputTranslateCoords(Window *w, SDL_Event *event, int *x, int *y, int *rx, int *ry)
Translates the mouse coordinates.
Definition: toolkit.c:1757
unsigned int window_get(const char *wdwname)
Gets the ID of a window.
Definition: toolkit.c:671
void window_lower(unsigned int wid)
Lowers a window (causes all other windows to appear above it).
Definition: toolkit.c:2548
void window_setBorder(unsigned int wid, int enable)
Sets or removes the border of a window.
Definition: toolkit.c:953
void toolkit_drawOutline(int x, int y, int w, int h, int b, const glColour *c, const glColour *lc)
Draws an outline.
Definition: toolkit.c:1290
void toolkit_nextFocus(Window *wdw)
Focus next widget.
Definition: toolkit.c:2309
int toolkit_input(SDL_Event *event)
Toolkit input handled here.
Definition: toolkit.c:1674
void window_posWindow(unsigned int wid, int *x, int *y)
Gets the dimensions of a window.
Definition: toolkit.c:393
void * window_getData(unsigned int wid)
Gets the custom data of a window.
Definition: toolkit.c:934
void window_kill(Window *wdw)
Kills the window (and children).
Definition: toolkit.c:1090
void window_setParent(unsigned int wid, unsigned int parent)
Sets a window as a window's parent.
Definition: toolkit.c:803
void window_setData(unsigned int wid, void *data)
Sets custom data for a window.
Definition: toolkit.c:917
static SDL_Keymod input_mod
Definition: toolkit.c:46
void window_resizeWidget(unsigned int wid, const char *name, int w, int h)
Resizes a widget.
Definition: toolkit.c:495
int toolkit_inputWindow(Window *wdw, SDL_Event *event, int purge)
Toolkit window input is handled here.
Definition: toolkit.c:1688
void toolkit_focusClear(Window *wdw)
Clears the window focus.
Definition: toolkit.c:2267
void window_onCleanup(unsigned int wid, void(*fptr)(unsigned int, const char *))
Sets the cleanup function of the window.
Definition: toolkit.c:858
int window_exists(const char *wdwname)
Checks to see if a window exists.
Definition: toolkit.c:598
const glColour * toolkit_colLight
Definition: toolkit.c:51
int widget_exists(unsigned int wid, const char *wgtname)
Checks to see if a widget exists.
Definition: toolkit.c:1139
static Window * windows
Definition: toolkit.c:40
void widget_cleanup(Widget *widget)
Destroys a widget.
Definition: toolkit.c:1006
int window_setDisplayname(unsigned int wid, const char *displayname)
Sets the displayname of a window.
Definition: toolkit.c:631
static void toolkit_regKey(SDL_Keycode key)
Registers a key as down (for key repetition).
Definition: toolkit.c:1994
static int toolkit_keyEvent(Window *wdw, SDL_Event *event)
Handles keyboard events.
Definition: toolkit.c:2043
void window_close(unsigned int wid, const char *str)
Helper function to automatically close the window calling it.
Definition: toolkit.c:1031
void toolkit_reposition(void)
Repositions windows and their children if resolution changes.
Definition: toolkit.c:2582
Window * toolkit_getActiveWindow(void)
Gets the active window in the toolkit.
Definition: toolkit.c:2419
void window_destroy(unsigned int wid)
Kills the window.
Definition: toolkit.c:1042
char * window_getFocus(unsigned int wid)
Gets the focused widget in a window (does strdup!!).
Definition: toolkit.c:2486
void window_handleEvents(unsigned int wid, int(*eventhandler)(unsigned int, SDL_Event *))
Sets the event handler for the window.
Definition: toolkit.c:989
void window_renderOverlay(Window *w)
Renders the window overlays.
Definition: toolkit.c:1545
const glColour * tab_active
Definition: toolkit.c:58