naev 0.11.5
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_needsRender = 1;
32static int toolkit_delayCounter = 0;
34/*
35 * window stuff
36 */
37#define MIN_WINDOWS 4
38static Window *windows = NULL;
40/*
41 * simulate keypresses when holding
42 */
43static SDL_Keycode input_key = 0;
44static SDL_Keymod input_mod = 0;
46/*
47 * default outline colours
48 */
49const glColour* toolkit_colLight = &cGrey50;
50const glColour* toolkit_col = &cGrey20;
51const glColour* toolkit_colDark = &cGrey5;
53/*
54 * Tab colours
55 */
56const glColour* tab_active = &cGrey20;
57const glColour* tab_activeB = &cGrey10;
58const glColour* tab_inactive = &cGrey15;
59const glColour* tab_inactiveB = &cGrey10;
60const glColour* tab_background= &cBlack;
62/*
63 * VBO
64 */
65static gl_vbo *toolkit_vbo;
68/*
69 * static prototypes
70 */
71/* input */
72static int toolkit_mouseEvent( Window *w, SDL_Event* event );
73static int toolkit_mouseEventWidget( Window *w, Widget *wgt,
74 SDL_Event *event, int x, int y, int rx, int ry );
75static int toolkit_keyEvent( Window *wdw, SDL_Event* event );
76static int toolkit_textEvent( Window *wdw, SDL_Event* event );
77/* Focus */
78static int toolkit_isFocusable( const Widget *wgt );
79static Widget* toolkit_getFocus( Window *wdw );
80static void toolkit_expose( Window *wdw, int expose );
81/* render */
82static void window_renderBorder( const Window* w );
83/* Death. */
84static void widget_kill( Widget *wgt );
85static void window_cleanup( Window *wdw );
86static void window_remove( Window *wdw );
87static void toolkit_purgeDead (void);
88
95{
96 /* Check to see if there is any active window. */
97 for (Window *wdw = windows; wdw != NULL; wdw = wdw->next)
98 if (!window_isFlag( wdw, WINDOW_KILL | WINDOW_NORENDER ))
99 return 1;
100 return 0;
101}
102
106void toolkit_delay (void)
107{
109}
110
119void toolkit_setPos( const Window *wdw, Widget *wgt, int x, int y )
120{
121 /* X position. */
122 if (x < 0)
123 wgt->x = wdw->w - wgt->w + x;
124 else
125 wgt->x = (double) x;
126
127 /* Y position. */
128 if (y < 0)
129 wgt->y = wdw->h - wgt->h + y;
130 else
131 wgt->y = (double) y;
132}
133
141void toolkit_setWindowPos( Window *wdw, int x, int y )
142{
143 wdw->xrel = -1.;
144 wdw->yrel = -1.;
145
146 window_rmFlag( wdw, WINDOW_CENTERX );
147 window_rmFlag( wdw, WINDOW_CENTERY );
148
149 /* x pos */
150 if (x == -1) { /* Center */
151 wdw->x = (gl_screen.nw - wdw->w)/2.;
152 wdw->xrel = 0.5;
153 window_setFlag( wdw, WINDOW_CENTERX );
154 }
155 else if (x < 0)
156 wdw->x = gl_screen.nw - wdw->w + (double) x;
157 else
158 wdw->x = (double) x;
159
160 /* y pos */
161 if (y == -1) { /* Center */
162 wdw->y = (gl_screen.nh - wdw->h)/2.;
163 wdw->yrel = 0.5;
164 window_setFlag( wdw, WINDOW_CENTERY );
165 }
166 else if (y < 0)
167 wdw->y = gl_screen.nh - wdw->h + (double) y;
168 else
169 wdw->y = (double) y;
170}
171
179void window_move( unsigned int wid, int x, int y )
180{
181 /* Get the window. */
182 Window *wdw = window_wget(wid);
183 if (wdw == NULL)
184 return;
185
186 toolkit_setWindowPos( wdw, x, y );
187}
188
196void window_resize( unsigned int wid, int w, int h )
197{
198 /* Get the window. */
199 Window *wdw = window_wget(wid);
200 if (wdw == NULL)
201 return;
202
203 wdw->w = (w == -1) ? gl_screen.nw : (double) w;
204 wdw->h = (h == -1) ? gl_screen.nh : (double) h;
205 if ((w == -1) && (h == -1)) {
206 window_setFlag( wdw, WINDOW_FULLSCREEN );
207 wdw->x = 0.;
208 wdw->y = 0.;
209 window_setFlag( wdw, WINDOW_CENTERX );
210 window_setFlag( wdw, WINDOW_CENTERY );
211 }
212 else {
213 window_rmFlag( wdw, WINDOW_FULLSCREEN );
214 if (window_isFlag( wdw, WINDOW_CENTERX ) && window_isFlag( wdw, WINDOW_CENTERY ))
215 toolkit_setWindowPos( wdw, -1, -1 );
216 }
217}
218
226Widget* window_newWidget( Window* w, const char *name )
227{
228 Widget *wgt, *wlast, *wtmp;
229 char *saved_name = NULL;
230
231 /* NULL protection. */
232 if (w==NULL)
233 return NULL;
234
235 /* Try to find one with the same name first. */
236 wlast = NULL;
237 for (wgt=w->widgets; wgt!=NULL; wgt=wgt->next) {
238
239 /* Must match name. */
240 if (strcmp(name, wgt->name)!=0) {
241 wlast = wgt;
242 continue;
243 }
244
245 /* Should be destroyed. */
246 if (!wgt_isFlag( wgt, WGT_FLAG_KILL )) {
247 WARN(_("Trying to create widget '%s' over existing one that hasn't been destroyed"),
248 name );
249 return NULL;
250 }
251
252 /* Relink. */
253 if (wlast==NULL)
254 w->widgets = wgt->next;
255 else
256 wlast->next = wgt->next;
257
258 /* Prepare and return this widget. */
259 saved_name = wgt->name;
260 wgt->name = NULL;
261 widget_cleanup(wgt);
262 break;
263 }
264
265 /* Must grow widgets. */
266 if (wgt == NULL)
267 wgt = malloc( sizeof(Widget) );
268
269 /* Safe defaults. */
270 memset( wgt, 0, sizeof(Widget) );
271 wgt->type = WIDGET_NULL;
272 wgt->status = WIDGET_STATUS_NORMAL;
273 wgt->wdw = w->id;
274 if (saved_name != NULL) /* Hack to avoid frees so _getFocus works in the same frame. */
275 wgt->name = saved_name;
276 else
277 wgt->name = strdup(name);
278 wgt->id = ++w->idgen;
279
280 /* Set up. */
281 wlast = NULL;
282 for (wtmp=w->widgets; wtmp!=NULL; wtmp=wtmp->next)
283 wlast = wtmp;
284 if (wlast == NULL)
285 w->widgets = wgt;
286 else
287 wlast->next = wgt;
288
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 const 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 const 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 const 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 /* Get widget. */
446 const Widget *wgt = window_getwgt(wid,name);
447 if (wgt == NULL)
448 return;
449
450 /* Return position. */
451 if (x != NULL)
452 (*x) = wgt->x;
453 if (y != NULL)
454 (*y) = wgt->y;
455}
456
465void window_moveWidget( unsigned int wid,
466 const char* name, int x, int y )
467{
468 Window *wdw;
469 Widget *wgt;
470
471 /* Get window. */
472 wdw = window_wget(wid);
473 if (wdw == NULL)
474 return;
475
476 /* Get widget. */
477 wgt = window_getwgt(wid,name);
478 if (wgt == NULL)
479 return;
480
481 /* Set position. */
482 toolkit_setPos( wdw, wgt, x, y );
483}
484
493void window_resizeWidget( unsigned int wid,
494 const char* name, int w, int h )
495{
496 Window *wdw;
497 Widget *wgt;
498
499 /* Get window. */
500 wdw = window_wget(wid);
501 if (wdw == NULL)
502 return;
503
504 /* Get widget. */
505 wgt = window_getwgt(wid,name);
506 if (wgt == NULL)
507 return;
508
509 /* Set position. */
510 wgt->w = w;
511 wgt->h = h;
512}
513
521void window_canFocusWidget( unsigned int wid,
522 const char* name, int canfocus )
523{
524 Window *wdw;
525 Widget *wgt;
526
527 /* Get window. */
528 wdw = window_wget(wid);
529 if (wdw == NULL)
530 return;
531
532 /* Get widget. */
533 wgt = window_getwgt(wid,name);
534 if (wgt == NULL)
535 return;
536
537 /* Set position. */
538 if (canfocus)
539 wgt_setFlag( wgt, WGT_FLAG_CANFOCUS );
540 else
541 wgt_rmFlag( wgt, WGT_FLAG_CANFOCUS );
542}
543
549int window_isTop( unsigned int wid )
550{
551 Window *n, *w = window_wget(wid);
552 if (w==NULL)
553 return 0;
554 n = w->next;
555 while (n != NULL) {
556 if (!window_isFlag(n,WINDOW_KILL | WINDOW_NORENDER))
557 return 0;
558 n = n->next;
559 }
560 return 1;
561}
562
566int widget_isCovered( unsigned int wid, const char *name, int x, int y )
567{
568 int bx, by, rx, ry;
569 Widget *wgt = window_getwgt( wid, name );
570 if (wgt==NULL)
571 return 0;
572
573 /* Undo transform. */
574 bx = x + wgt->x;
575 by = y + wgt->y;
576
577 /* Find if the point is covered. */
578 for (Widget *w=wgt->next; w!=NULL; w=w->next) {
579 if ((wgt->render==NULL) || wgt_isFlag(w, WGT_FLAG_KILL))
580 continue;
581
582 rx = bx-w->x;
583 ry = by-w->y;
584 if (!((rx < 0) || (rx >= w->w) || (ry < 0) || (ry >= w->h)))
585 return 1;
586 }
587 return 0;
588}
589
596int window_exists( const char* wdwname )
597{
598 if (windows == NULL)
599 return 0;
600 for (Window *w = windows; w != NULL; w = w->next)
601 if ((strcmp(w->name,wdwname)==0) && !window_isFlag(w, WINDOW_KILL))
602 return 1;
603 return 0; /* doesn't exist */
604}
605
612int window_existsID( unsigned int wid )
613{
614 if (windows == NULL)
615 return 0;
616 for (Window *w = windows; w != NULL; w = w->next)
617 if ((w->id==wid) && !window_isFlag(w, WINDOW_KILL))
618 return 1;
619 return 0; /* doesn't exist */
620}
621
629int window_setDisplayname( unsigned int wid, const char *displayname )
630{
631 Window *wdw = window_wget(wid);
632 if (wdw == NULL)
633 return -1;
634 free(wdw->displayname);
635 wdw->displayname = NULL;
636 if (displayname != NULL)
637 wdw->displayname = strdup(displayname);
638 return 0;
639}
640
647void window_setDynamic( unsigned int wid, int dynamic )
648{
649 Window *wdw = window_wget(wid);
650 if (wdw == NULL)
651 return;
652 if (dynamic)
653 wdw->flags |= WINDOW_DYNAMIC;
654 else
655 wdw->flags &= ~WINDOW_DYNAMIC;
656}
657
666unsigned int window_get( const char* wdwname )
667{
668 Window *last;
669 if (windows == NULL)
670 return 0;
671 last = NULL;
672 for (Window *w = windows; w != NULL; w = w->next)
673 if ((strcmp(w->name,wdwname)==0) && !window_isFlag(w, WINDOW_KILL))
674 last = w;
675 if (last==NULL)
676 return 0;
677 return last->id;
678}
679
691unsigned int window_create( const char* name, const char *displayname,
692 const int x, const int y, const int w, const int h )
693{
694 return window_createFlags( name, displayname, x, y, w, h, 0 );
695}
696
709unsigned int window_createFlags( const char* name, const char *displayname,
710 const int x, const int y, const int w, const int h, unsigned int flags )
711{
712 Window *wdw = calloc( 1, sizeof(Window) );
713
714 const int wid = (++genwid); /* unique id */
715
716 /* Create the window. */
717 wdw->id = wid;
718 wdw->name = strdup(name);
719 wdw->displayname = strdup(displayname);
720
721 /* Safe defaults. */
722 wdw->idgen = -1;
723 wdw->focus = -1;
724 wdw->xrel = -1.;
725 wdw->yrel = -1.;
726 wdw->flags = flags;
727 wdw->exposed = !window_isFlag(wdw, WINDOW_NOFOCUS);
728
729 /* Dimensions. */
730 wdw->w = (w == -1) ? gl_screen.nw : (double) w;
731 wdw->h = (h == -1) ? gl_screen.nh : (double) h;
732 if ((w == -1) && (h == -1)) {
733 window_setFlag( wdw, WINDOW_FULLSCREEN );
734 wdw->x = 0.;
735 wdw->y = 0.;
736 }
737 else
738 toolkit_setWindowPos( wdw, x, y );
739
740 if (!toolkit_isOpen()) {
742 pause_game();
743 gl_defViewport(); /* Reset the default viewport */
744 }
745
746 /* Clear key repeat. */
748
749 /* Add to list. */
750 wdw->next = NULL;
751 if (windows == NULL)
752 windows = wdw;
753 else {
754 Window *wlast;
755 /* Take focus from the old window. */
756 if (wdw->exposed) {
757 Window *wcur = toolkit_getActiveWindow();
758 if (wcur != NULL)
759 toolkit_expose( wcur, 0 ); /* wcur is hidden */
760 }
761
762 wlast = windows;
763 while (1) {
764 if ((strcmp( wlast->name, name )==0) && !window_isFlag( wlast, WINDOW_KILL )
765 && !window_isFlag( wlast, WINDOW_NOFOCUS ))
766 WARN( _( "Window with name '%s' already exists!" ), wlast->name );
767
768 if (wlast->next == NULL)
769 break;
770
771 wlast = wlast->next;
772 }
773
774 wlast->next = wdw;
775 }
776
778 return wid;
779}
780
789void window_setParent( unsigned int wid, unsigned int parent )
790{
791 /* Get the window. */
792 Window *wdw = window_wget( wid );
793 if (wdw == NULL)
794 return;
795
796 /* Set the parent. */
797 wdw->parent = parent;
798}
799
806unsigned int window_getParent( unsigned int wid )
807{
808 /* Get the window. */
809 const Window *wdw = window_wget( wid );
810 if (wdw == NULL)
811 return 0;
812
813 /* Get the parent. */
814 return wdw->parent;
815}
816
826void window_onClose( unsigned int wid, void (*fptr)(unsigned int,const char*) )
827{
828 /* Get the window. */
829 Window *wdw = window_wget( wid );
830 if (wdw == NULL)
831 return;
832
833 /* Set the close function. */
834 wdw->close_fptr = fptr;
835}
836
847void window_setAccept( unsigned int wid, void (*accept)(unsigned int,const char*) )
848{
849 /* Get the window. */
850 Window *wdw = window_wget( wid );
851 if (wdw == NULL)
852 return;
853
854 /* Set the accept function. */
855 wdw->accept_fptr = accept;
856}
857
868void window_setCancel( unsigned int wid, void (*cancel)(unsigned int,const char*) )
869{
870 /* Get the window. */
871 Window *wdw = window_wget( wid );
872 if (wdw == NULL)
873 return;
874
875 /* Set the cancel function. */
876 wdw->cancel_fptr = cancel;
877}
878
888void window_setOnFocus( unsigned int wid, void (*focus)(unsigned int) )
889{
890 /* Get the window. */
891 Window *wdw = window_wget( wid );
892 if (wdw == NULL)
893 return;
894
895 /* Set the cancel function. */
896 wdw->focus_fptr = focus;
897}
898
905void window_setData( unsigned int wid, void *data )
906{
907 /* Get the window. */
908 Window *wdw = window_wget( wid );
909 if (wdw == NULL)
910 return;
911
912 /* Set data. */
913 wdw->udata = data;
914}
915
922void* window_getData( unsigned int wid )
923{
924 /* Get the window. */
925 const Window *wdw = window_wget( wid );
926 if (wdw == NULL)
927 return NULL;
928
929 /* Get data. */
930 return wdw->udata;
931}
932
941void window_setBorder( unsigned int wid, int enable )
942{
943 /* Get the window. */
944 Window *wdw = window_wget( wid );
945 if (wdw == NULL)
946 return;
947
948 if (enable)
949 window_rmFlag( wdw, WINDOW_NOBORDER );
950 else
951 window_setFlag( wdw, WINDOW_NOBORDER );
952}
953
960void window_handleKeys( unsigned int wid,
961 int (*keyhandler)(unsigned int,SDL_Keycode,SDL_Keymod,int) )
962{
963 /* Get the window. */
964 Window *wdw = window_wget( wid );
965 if (wdw == NULL)
966 return;
967
968 /* Set key event handler function. */
969 wdw->keyevent = keyhandler;
970}
971
977void window_handleEvents( unsigned int wid,
978 int (*eventhandler)(unsigned int,SDL_Event*) )
979{
980 /* Get the window. */
981 Window *wdw = window_wget( wid );
982 if (wdw == NULL)
983 return;
984
985 /* Set key event handler function. */
986 wdw->eventevent = eventhandler;
987}
988
994void widget_cleanup( Widget *widget )
995{
996 /* Type specific clean up. */
997 if (widget->cleanup != NULL)
998 widget->cleanup(widget);
999
1000 /* General freeing. */
1001 free(widget->name);
1002}
1003
1004void widget_setStatus( Widget *wgt, WidgetStatus sts )
1005{
1006 if (wgt->status != sts)
1008 wgt->status = sts;
1009}
1010
1015{
1016 for (Window *w = windows; w != NULL; w = w->next)
1017 window_destroy( w->id );
1018}
1019
1026void window_close( unsigned int wid, const char *str )
1027{
1028 (void) str;
1029 window_destroy( wid );
1030}
1031
1037void window_destroy( unsigned int wid )
1038{
1039 if (windows == NULL)
1040 return;
1041 /* Destroy the window */
1042 for (Window *wdw = windows; wdw != NULL; wdw = wdw->next) {
1043 Window *wactive;
1044
1045 /* Not the window we're looking for. */
1046 if (wdw->id != wid)
1047 continue;
1048
1049 /* Already being killed, skip. */
1050 if (window_isFlag( wdw, WINDOW_KILL ))
1051 continue;
1052
1053 /* Mark children for death. */
1054 for (Window *w = windows; w != NULL; w = w->next)
1055 if (w->parent == wid)
1056 window_destroy( w->id );
1057
1058 /* Clean up. */
1059 window_cleanup( wdw );
1060 window_setFlag( wdw, WINDOW_KILL );
1062
1063 /* Disable text input, etc. */
1064 toolkit_focusClear( wdw );
1065
1066 wactive = toolkit_getActiveWindow();
1067 if (wactive == NULL)
1068 break;
1069
1070 toolkit_expose( wactive, 1 );
1071 break;
1072 }
1073
1074 /* Do focus. */
1075 for (Window *w = windows; w != NULL; w = w->next) {
1076 if (!window_isFlag(w, WINDOW_KILL) && (w->focus_fptr!=NULL))
1077 w->focus_fptr( w->id );
1078 }
1079}
1080
1086void window_kill( Window *wdw )
1087{
1088 for (Window *w = windows; w != NULL; w = w->next)
1089 if (w->parent == wdw->id)
1090 window_kill( w );
1091 window_cleanup( wdw );
1092 window_setFlag( wdw, WINDOW_KILL );
1094}
1095
1102static void window_cleanup( Window *wdw )
1103{
1104 /* Run the close function first. */
1105 if (wdw->close_fptr != NULL)
1106 wdw->close_fptr( wdw->id, wdw->name );
1107 wdw->close_fptr = NULL;
1108}
1109
1116static void window_remove( Window *wdw )
1117{
1118 Widget *wgt;
1119
1120 /* Destroy the window. */
1121 free(wdw->name);
1122 free(wdw->displayname);
1123 wgt = wdw->widgets;
1124 while (wgt != NULL) {
1125 Widget *wgtkill = wgt;
1126 wgt = wgtkill->next;
1127 widget_kill(wgtkill);
1128 }
1129 free(wdw);
1130
1131 /* Clear key repeat, since toolkit could miss the keyup event. */
1133}
1134
1142int widget_exists( unsigned int wid, const char* wgtname )
1143{
1144 /* Get window. */
1145 Window *w = window_wget(wid);
1146 if (w==NULL) {
1147 WARN(_("window '%d' does not exist"), wid);
1148 return 0;
1149 }
1150
1151 /* Check for widget. */
1152 for (Widget *wgt=w->widgets; wgt!=NULL; wgt=wgt->next)
1153 if (strcmp(wgtname, wgt->name)==0)
1154 return !wgt_isFlag(wgt, WGT_FLAG_KILL);
1155
1156 return 0;
1157}
1158
1165void window_destroyWidget( unsigned int wid, const char* wgtname )
1166{
1167 Window *wdw;
1168 Widget *wgt;
1169
1170 /* Get the window. */
1171 wdw = window_wget( wid );
1172 if (wdw == NULL)
1173 return;
1174
1175 /* Get the widget. */
1176 for (wgt=wdw->widgets; wgt!=NULL; wgt=wgt->next)
1177 if (strcmp(wgt->name, wgtname)==0)
1178 break;
1179
1180 if (wgt == NULL) {
1181 WARN(_("Widget '%s' not found in window '%s'"), wgtname, wdw->displayname );
1182 return;
1183 }
1184
1185 toolkit_defocusWidget( wdw, wgt );
1186
1187 /* There's dead stuff now. */
1188 wgt_rmFlag( wgt, WGT_FLAG_FOCUSED );
1189 wgt_setFlag( wgt, WGT_FLAG_KILL );
1190}
1191
1195static void widget_kill( Widget *wgt )
1196{
1197 /* Clean up. */
1198 widget_cleanup(wgt);
1199 free(wgt);
1200}
1201
1216void toolkit_drawOutlineThick( int x, int y, int w, int h, int b,
1217 int thick, const glColour* c, const glColour* lc )
1218{
1219 GLshort tri[5][4];
1220 glColour colours[10];
1221
1222 x -= (b - thick);
1223 w += 2 * (b - thick);
1224 y -= (b - thick);
1225 h += 2 * (b - thick);
1226 lc = lc ? lc : c;
1227
1228 /* Left-up. */
1229 tri[0][0] = x; /* Inner */
1230 tri[0][1] = y;
1231 tri[0][2] = x-thick; /* Outer */
1232 tri[0][3] = y-thick;
1233 colours[0] = *lc;
1234 colours[1] = *lc;
1235
1236 /* Left-down. */
1237 tri[1][0] = x; /* Inner. */
1238 tri[1][1] = y + h;
1239 tri[1][2] = x-thick; /* Outer. */
1240 tri[1][3] = y + h+thick;
1241 colours[2] = *c;
1242 colours[3] = *c;
1243
1244 /* Right-down. */
1245 tri[2][0] = x + w; /* Inner. */
1246 tri[2][1] = y + h;
1247 tri[2][2] = x + w+thick; /* Outer. */
1248 tri[2][3] = y + h+thick;
1249 colours[4] = *c;
1250 colours[5] = *c;
1251
1252 /* Right-up. */
1253 tri[3][0] = x + w; /* Inner. */
1254 tri[3][1] = y;
1255 tri[3][2] = x + w+thick; /* Outer. */
1256 tri[3][3] = y-thick;
1257 colours[6] = *lc;
1258 colours[7] = *lc;
1259
1260 /* Left-up. */
1261 tri[4][0] = x; /* Inner */
1262 tri[4][1] = y;
1263 tri[4][2] = x-thick; /* Outer */
1264 tri[4][3] = y-thick;
1265 colours[8] = *lc;
1266 colours[9] = *lc;
1267
1268 /* Upload to the VBO. */
1269 gl_vboSubData( toolkit_vbo, 0, sizeof(tri), tri );
1270 gl_vboSubData( toolkit_vbo, toolkit_vboColourOffset, sizeof(colours), colours );
1271
1272 gl_beginSmoothProgram(gl_view_matrix);
1273 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex, 0, 2, GL_SHORT, 0 );
1274 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex_colour,
1275 toolkit_vboColourOffset, 4, GL_FLOAT, 0 );
1276 glDrawArrays( GL_TRIANGLE_STRIP, 0, 10 );
1277 gl_endSmoothProgram();
1278}
1279
1293void toolkit_drawOutline( int x, int y, int w, int h, int b,
1294 const glColour* c, const glColour* lc )
1295{
1296 GLshort lines[4][2];
1297 glColour colours[4];
1298
1299 x -= b, w += 2 * b;
1300 y -= b, h += 2 * b;
1301 lc = lc ? lc : c;
1302
1303 /* Lines. */
1304 lines[0][0] = x; /* left-up */
1305 lines[0][1] = y;
1306 colours[0] = *lc;
1307
1308 lines[1][0] = x; /* left-down */
1309 lines[1][1] = y + h;
1310 colours[1] = *c;
1311
1312 lines[2][0] = x + w; /* right-down */
1313 lines[2][1] = y + h;
1314 colours[2] = *c;
1315
1316 lines[3][0] = x + w; /* right-up */
1317 lines[3][1] = y;
1318 colours[3] = *lc;
1319
1320 /* Upload to the VBO. */
1321 gl_vboSubData( toolkit_vbo, 0, sizeof(lines), lines );
1322 gl_vboSubData( toolkit_vbo, toolkit_vboColourOffset, sizeof(colours), colours );
1323
1324 gl_beginSmoothProgram(gl_view_matrix);
1325 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex, 0, 2, GL_SHORT, 0 );
1326 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex_colour,
1327 toolkit_vboColourOffset, 4, GL_FLOAT, 0 );
1328 glDrawArrays( GL_LINE_LOOP, 0, 4 );
1329 gl_endSmoothProgram();
1330}
1343void toolkit_drawRect( int x, int y, int w, int h,
1344 const glColour* c, const glColour* lc )
1345{
1346 GLshort vertex[4][2];
1347 glColour colours[4];
1348
1349 lc = lc == NULL ? c : lc;
1350
1351 /* Set up vertices and colours. */
1352 vertex[0][0] = x; /* left-up */
1353 vertex[0][1] = y;
1354 colours[0] = *c;
1355
1356 vertex[1][0] = x; /* left-down */
1357 vertex[1][1] = y + h;
1358 colours[1] = *lc;
1359
1360 vertex[2][0] = x + w; /* right-up */
1361 vertex[2][1] = y;
1362 colours[2] = *c;
1363
1364 vertex[3][0] = x + w; /* right-down */
1365 vertex[3][1] = y + h;
1366 colours[3] = *lc;
1367
1368 /* Upload to the VBO. */
1369 gl_vboSubData( toolkit_vbo, 0, sizeof(vertex), vertex );
1370 gl_vboSubData( toolkit_vbo, toolkit_vboColourOffset, sizeof(colours), colours );
1371
1372 gl_beginSmoothProgram(gl_view_matrix);
1373 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex, 0, 2, GL_SHORT, 0 );
1374 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex_colour,
1375 toolkit_vboColourOffset, 4, GL_FLOAT, 0 );
1376 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
1377 gl_endSmoothProgram();
1378}
1379
1391void toolkit_drawTriangle( int x1, int y1, int x2, int y2, int x3, int y3,
1392 const glColour* c )
1393{
1394 GLshort vertex[3][2];
1395 glColour colours[3];
1396
1397 /* Set up vertices and colours. */
1398 vertex[0][0] = x1; /* left-up */
1399 vertex[0][1] = y1;
1400 colours[0] = *c;
1401
1402 vertex[1][0] = x2; /* left-down */
1403 vertex[1][1] = y2;
1404 colours[1] = *c;
1405
1406 vertex[2][0] = x3; /* right-up */
1407 vertex[2][1] = y3;
1408 colours[2] = *c;
1409
1410 /* Upload to the VBO. */
1411 gl_vboSubData( toolkit_vbo, 0, sizeof(vertex), vertex );
1412 gl_vboSubData( toolkit_vbo, toolkit_vboColourOffset, sizeof(colours), colours );
1413
1414 gl_beginSmoothProgram(gl_view_matrix);
1415 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex, 0, 2, GL_SHORT, 0 );
1416 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex_colour,
1417 toolkit_vboColourOffset, 4, GL_FLOAT, 0 );
1418 glDrawArrays( GL_TRIANGLE_STRIP, 0, 3 );
1419 gl_endSmoothProgram();
1420}
1421
1429void toolkit_drawAltText( int bx, int by, const char *alt )
1430{
1431 double w, h;
1432 double x, y;
1433 glColour c;
1434 glColour c2;
1435
1436 /* We're on top of anything previously drawn. */
1437 glClear( GL_DEPTH_BUFFER_BIT );
1438
1439 /* Get dimensions. */
1440 w = MIN( gl_printWidthRaw( &gl_smallFont, alt ), 400 );
1441 h = gl_printHeightRaw( &gl_smallFont, w, alt );
1442
1443 /* Choose position. */
1444 x = bx + 10.;
1445 y = by - h - gl_smallFont.h - 10.;
1446 if (y < 10.)
1447 y = 10.;
1448 if (x+w+10. > gl_screen.nw)
1449 x -= w;
1450
1451 /* Set colours. */
1452 c.r = cGrey20.r;
1453 c.g = cGrey20.g;
1454 c.b = cGrey20.b;
1455 c.a = 0.9;
1456 c2.r = cGrey10.r;
1457 c2.g = cGrey10.g;
1458 c2.b = cGrey10.b;
1459 c2.a = 0.7;
1460 toolkit_drawRect( x+1, y+1, w+18, h+18, &c2, NULL );
1461 toolkit_drawRect( x, y, w+18, h+18, &c, NULL );
1462 gl_printTextRaw( &gl_smallFont, w, h, x + 9, y + 9, 0, &cFontWhite, -1., alt );
1463}
1464
1470static void window_renderBorder( const Window* w )
1471{
1472 /* Position */
1473 double x = w->x;
1474 double y = w->y;
1475
1476 /*
1477 * Case fullscreen.
1478 */
1479 if (window_isFlag( w, WINDOW_FULLSCREEN )) {
1480 /* Background. */
1481 toolkit_drawRect( x, y, w->w, w->h, toolkit_col, NULL );
1482 /* Name. */
1483 gl_printMidRaw( &gl_defFont, w->w,
1484 x,
1485 y + w->h - 20.,
1486 &cFontWhite, -1., w->displayname );
1487 return;
1488 }
1489
1490 toolkit_drawRect( x, y, w->w, w->h, toolkit_col, NULL );
1491 toolkit_drawOutlineThick( x, y, w->w, w->h, 1, 2, toolkit_colDark, NULL );
1492 toolkit_drawOutline( x + 3, y + 2, w->w - 5, w->h - 5, 1, toolkit_colLight, NULL );
1493
1494 /*
1495 * render window name
1496 */
1497 gl_printMidRaw( &gl_defFont, w->w,
1498 x,
1499 y + w->h - 20.,
1500 &cFontWhite, -1., w->displayname );
1501}
1502
1509void window_render( Window *w, int top )
1510{
1511 /* We're on top of anything previously drawn. */
1512 glClear( GL_DEPTH_BUFFER_BIT );
1513
1514 /* See if needs border. */
1515 if (!window_isFlag( w, WINDOW_NOBORDER ))
1517
1518 /* Iterate over widgets. */
1519 for (Widget *wgt=w->widgets; wgt!=NULL; wgt=wgt->next) {
1520 if (wgt->render==NULL)
1521 continue;
1522 if (wgt_isFlag(wgt, WGT_FLAG_KILL))
1523 continue;
1524
1525 /* Only render non-dynamics. */
1526 if (!wgt_isFlag(wgt, WGT_FLAG_DYNAMIC) || !top)
1527 wgt->render( wgt, w->x, w->y );
1528
1529 if (wgt->id == w->focus) {
1530 double wx = w->x + wgt->x - 2;
1531 double wy = w->y + wgt->y - 2;
1532 toolkit_drawOutlineThick( wx, wy, wgt->w+4, wgt->h+4, 0, 2, (wgt->type == WIDGET_BUTTON ? &cGrey70 : &cGrey30), NULL );
1533 }
1534 }
1535}
1536
1540void window_renderDynamic( Window *w )
1541{
1542 /* Iterate over widgets. */
1543 for (Widget *wgt=w->widgets; wgt!=NULL; wgt=wgt->next) {
1544 if (wgt->render==NULL)
1545 continue;
1546 if (wgt_isFlag(wgt, WGT_FLAG_KILL))
1547 continue;
1548 if (wgt_isFlag(wgt, WGT_FLAG_DYNAMIC) || window_isFlag(w, WINDOW_DYNAMIC))
1549 wgt->render( wgt, w->x, w->y );
1550 if (wgt->renderDynamic != NULL)
1551 wgt->renderDynamic( wgt, w->x, w->y );
1552 }
1553}
1554
1560void window_renderOverlay( Window *w )
1561{
1562 /* Draw overlays. */
1563 for (Widget *wgt=w->widgets; wgt!=NULL; wgt=wgt->next)
1564 if ((wgt->renderOverlay != NULL) && !wgt_isFlag(wgt, WGT_FLAG_KILL))
1565 wgt->renderOverlay( wgt, w->x, w->y );
1566}
1567
1577void toolkit_drawScrollbar( int x, int y, int w, int h, double pos )
1578{
1579 double sy;
1580
1581 /* scrollbar background */
1582 toolkit_drawRect( x, y, w, h, &cGrey10, NULL );
1583
1584 /* Bar itself. */
1585 sy = y + (h - 30.) * (1.-pos);
1586 toolkit_drawRect( x, sy, w, 30., toolkit_colLight, NULL );
1587 toolkit_drawOutline( x+1, sy, w-2, 30., 0., toolkit_colDark, NULL );
1588}
1589
1593void toolkit_render( double dt )
1594{
1595 (void) dt;
1596 Window *top = toolkit_getActiveWindow();
1597
1598 if (toolkit_needsRender) {
1600
1601 glBindFramebuffer( GL_FRAMEBUFFER, gl_screen.fbo[3] );
1602 glClearColor( 0., 0., 0., 0. );
1603 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1604 glBlendFuncSeparate( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
1605
1606 /* Render base. */
1607 for (Window *w = windows; w!=NULL; w = w->next) {
1608 if (window_isFlag(w, WINDOW_NORENDER | WINDOW_KILL))
1609 continue;
1610 if ((w==top) && window_isFlag(w,WINDOW_DYNAMIC))
1611 continue;
1612
1613 /* The actual rendering. */
1614 window_render( w, w==top );
1615 }
1616
1617 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1618 glBindFramebuffer(GL_FRAMEBUFFER, gl_screen.current_fbo);
1619 glClearColor( 0., 0., 0., 1. );
1620 }
1621
1622 glUseProgram(shaders.texture.program);
1623
1624 /* Set texture. */
1625 glActiveTexture( GL_TEXTURE0 );
1626 glBindTexture( GL_TEXTURE_2D, gl_screen.fbo_tex[3] );
1627 glUniform1i(shaders.texture.sampler, 0);
1628
1629 /* Set vertex data. */
1630 glEnableVertexAttribArray( shaders.texture.vertex );
1631 gl_vboActivateAttribOffset( gl_squareVBO, shaders.texture.vertex,
1632 0, 2, GL_FLOAT, 0 );
1633
1634 /* Set shader uniforms. */
1635 gl_uniformColour(shaders.texture.colour, &cWhite);
1636 const mat4 ortho = mat4_ortho(0., 1., 0., 1., 1., -1.);
1637 const mat4 I = mat4_identity();
1638 gl_uniformMat4(shaders.texture.projection, &ortho);
1639 gl_uniformMat4(shaders.texture.tex_mat, &I);
1640
1641 /* Draw. */
1642 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
1643
1644 /* Clean up. */
1645 glDisableVertexAttribArray( shaders.texture.vertex );
1646 glBindTexture( GL_TEXTURE_2D, 0 );
1647 gl_checkErr();
1648 glUseProgram(0);
1649
1650 /* We render only the active window dynamically, otherwise we wouldn't be able to respect the order.
1651 * However, since the dynamic stuff is also rendered to the framebuffer below, it shouldn't be too bad. */
1652 if ((top != NULL) && !window_isFlag(top, WINDOW_NORENDER | WINDOW_KILL)) {
1653 window_renderDynamic( top );
1654 window_renderOverlay( top );
1655 }
1656}
1657
1662{
1664}
1665
1672int toolkit_input( SDL_Event* event )
1673{
1674 /* Get window that can be focused. */
1675 Window *wdw = toolkit_getActiveWindow();
1676 if (wdw == NULL)
1677 return 0;
1678
1679 /* Pass event to window. */
1680 return toolkit_inputWindow( wdw, event, 1 );
1681}
1682
1686int toolkit_inputWindow( Window *wdw, SDL_Event *event, int purge )
1687{
1688 int ret;
1689
1690 /* See if widget needs event. */
1691 for (Widget *wgt=wdw->widgets; wgt!=NULL; wgt=wgt->next) {
1692 if (!wgt_isFlag( wgt, WGT_FLAG_RAWINPUT ))
1693 continue;
1694 if (wgt->rawevent==NULL)
1695 continue;
1696 ret = wgt->rawevent( wgt, event );
1697 if (ret != 0) {
1699 return ret;
1700 }
1701 }
1702
1703 /* Event handler. */
1704 if (wdw->eventevent != NULL) {
1705 ret = wdw->eventevent( wdw->id, event );
1706 if (ret != 0) {
1708 return ret;
1709 }
1710 }
1711
1712 /* Hack in case window got destroyed in eventevent. */
1713 ret = 0;
1714 if (!window_isFlag(wdw, WINDOW_KILL)) {
1715 /* Pass it on. */
1716 switch (event->type) {
1717 case SDL_MOUSEMOTION:
1718 case SDL_MOUSEBUTTONDOWN:
1719 case SDL_MOUSEBUTTONUP:
1720 case SDL_MOUSEWHEEL:
1721 ret |= toolkit_mouseEvent(wdw, event);
1722 break;
1723
1724 case SDL_KEYDOWN:
1725 case SDL_KEYUP:
1726 ret |= toolkit_keyEvent(wdw, event);
1727 break;
1728
1729 case SDL_TEXTINPUT:
1730 ret |= toolkit_textEvent(wdw, event);
1731 break;
1732 case SDL_TEXTEDITING:
1733 break;
1734 }
1735 }
1736 if (ret)
1738
1739 /* Clean up the dead if needed. */
1740 if (purge && !dialogue_isOpen()) { /* Hack, since dialogues use secondary loop. */
1741 if (toolkit_delayCounter > 0)
1743 else
1745 }
1746
1747 return ret; /* don't block input */
1748}
1749
1761Uint32 toolkit_inputTranslateCoords( const Window *w, SDL_Event *event,
1762 int *x, int *y, int *rx, int *ry )
1763{
1764 /* Extract the position as event. */
1765 if (event->type==SDL_MOUSEMOTION) {
1766 *x = event->motion.x;
1767 *y = event->motion.y;
1768 }
1769 else if ((event->type==SDL_MOUSEBUTTONDOWN) || (event->type==SDL_MOUSEBUTTONUP)) {
1770 *x = event->button.x;
1771 *y = event->button.y;
1772 }
1773 else if (event->type == SDL_MOUSEWHEEL)
1774 SDL_GetMouseState( x, y );
1775
1776 /* Translate offset. */
1777 gl_windowToScreenPos( x, y, *x, *y );
1778
1779 /* Transform to relative to window. */
1780 *x -= w->x;
1781 *y -= w->y;
1782
1783 /* Relative only matter if mouse motion. */
1784 if (event->type==SDL_MOUSEMOTION) {
1785 *ry = (double)event->motion.yrel * gl_screen.mxscale;
1786 *rx = (double)event->motion.xrel * gl_screen.myscale;
1787 }
1788 else {
1789 *ry = 0;
1790 *rx = 0;
1791 }
1792
1793 return event->type;
1794}
1795
1796static int toolkit_mouseEventSingle( Window *w, SDL_Event* event,
1797 Widget *wgt, int x, int y, int rx, int ry )
1798{
1799 int ret = 0;
1800 /* Custom widgets take it from here */
1801 if (wgt->type==WIDGET_CUST) {
1802 if (wgt->dat.cst.mouse)
1803 ret = wgt->dat.cst.mouse( w->id, event, x-wgt->x, y-wgt->y, wgt->w, wgt->h, rx, ry,
1804 wgt->dat.cst.userdata );
1805 }
1806 else
1807 ret = toolkit_mouseEventWidget( w, wgt, event, x, y, rx, ry );
1808 return ret;
1809}
1810static int toolkit_mouseEventReverse( Window *w, SDL_Event* event,
1811 Widget *wgt, int x, int y, int rx, int ry )
1812{
1813 if (wgt->next!=NULL) {
1814 int ret = toolkit_mouseEventReverse( w, event, wgt->next, x, y, rx, ry );
1815 if (ret)
1816 return ret;
1817 }
1818
1819 return toolkit_mouseEventSingle( w, event, wgt, x, y, rx, ry );
1820}
1827static int toolkit_mouseEvent( Window *w, SDL_Event* event )
1828{
1829 int x, y, rx, ry;
1830
1831 /* Translate mouse coords. */
1832 toolkit_inputTranslateCoords( w, event, &x, &y, &rx, &ry );
1833
1834 /* Check each widget. */
1835 if (w->widgets != NULL)
1836 return toolkit_mouseEventReverse( w, event, w->widgets, x, y, rx, ry );
1837 return 0;
1838}
1839
1851static int toolkit_mouseEventWidget( Window *w, Widget *wgt,
1852 SDL_Event *event, int x, int y, int rx, int ry )
1853{
1854 int ret, inbounds;
1855 Uint8 button;
1856
1857 /* Widget translations. */
1858 x -= wgt->x;
1859 y -= wgt->y;
1860
1861 /* Handle mouse event. */
1862 if (event->type == SDL_MOUSEMOTION)
1863 button = event->motion.state;
1864 else
1865 button = event->button.button;
1866
1867 /* Check inbounds. */
1868 inbounds = !((x < 0) || (x >= wgt->w) || (y < 0) || (y >= wgt->h));
1869
1870 /* Regular widgets. */
1871 ret = 0;
1872 switch (event->type) {
1873 case SDL_MOUSEMOTION:
1874 /* Change the status of the widget if mouse isn't down. */
1875
1876 /* Not scrolling. */
1877 if (wgt->status != WIDGET_STATUS_SCROLLING) {
1878 if (inbounds) {
1879 if (wgt->status != WIDGET_STATUS_MOUSEDOWN)
1880 widget_setStatus( wgt, WIDGET_STATUS_MOUSEOVER );
1881 }
1882 else
1883 widget_setStatus( wgt, WIDGET_STATUS_NORMAL );
1884 }
1885 else
1886 inbounds = 1; /* Scrolling is always inbounds. */
1887
1888 /* If always gets the event. */
1889 if (wgt_isFlag( wgt, WGT_FLAG_ALWAYSMMOVE ))
1890 inbounds = 1;
1891
1892 /* Try to give the event to the widget. */
1893 if (inbounds && (wgt->mmoveevent != NULL))
1894 ret |= (*wgt->mmoveevent)( wgt, x, y, rx, ry );
1895
1896 break;
1897
1898 case SDL_MOUSEWHEEL:
1899 if (!inbounds)
1900 break;
1901
1902 /* Try to give the event to the widget. */
1903 if (wgt->mwheelevent != NULL)
1904 ret |= (*wgt->mwheelevent)( wgt, event->wheel );
1905 if (ret)
1907
1908 break;
1909
1910 case SDL_MOUSEBUTTONDOWN:
1911 if (!inbounds)
1912 break;
1913
1914 /* Update the status. */
1915 if (button == SDL_BUTTON_LEFT)
1916 widget_setStatus( wgt, WIDGET_STATUS_MOUSEDOWN );
1917
1918 if (toolkit_isFocusable(wgt)) {
1919 toolkit_focusClear( w );
1920 toolkit_focusWidget( w, wgt );
1921 }
1922
1923 /* Try to give the event to the widget. */
1924 if (wgt->mdoubleclickevent != NULL && input_isDoubleClick( (void*)wgt ))
1925 ret |= (*wgt->mdoubleclickevent)( wgt, button, x, y );
1926 else if (wgt->mclickevent != NULL)
1927 ret |= (*wgt->mclickevent)( wgt, button, x, y );
1928 if (ret) {
1929 input_clicked( (void*)wgt );
1931 }
1932 break;
1933
1934 case SDL_MOUSEBUTTONUP:
1935 /* Since basically only buttons are handled here, we ignore
1936 * it all except the left mouse button. */
1937 if (button != SDL_BUTTON_LEFT)
1938 break;
1939
1940 if (wgt->status==WIDGET_STATUS_MOUSEDOWN) {
1941 /* Soft-disabled buttons will run anyway. */
1942 if ((wgt->type==WIDGET_BUTTON) && ((wgt->dat.btn.disabled==0) ||
1943 (wgt->dat.btn.softdisable))) {
1944 if (wgt->dat.btn.fptr==NULL)
1945 DEBUG(_("Toolkit: Button '%s' of Window '%s' "
1946 "doesn't have a function trigger"),
1947 wgt->name, w->displayname );
1948 else {
1949 (*wgt->dat.btn.fptr)(w->id, wgt->name);
1950 ret = 1;
1952 }
1953 }
1954 }
1955
1956 /* Signal scroll done if necessary. */
1957 if ((wgt->status == WIDGET_STATUS_SCROLLING) && (wgt->scrolldone != NULL))
1958 wgt->scrolldone( wgt );
1959
1960 /* Always goes normal unless is below mouse. */
1961 if (inbounds)
1962 widget_setStatus( wgt, WIDGET_STATUS_MOUSEOVER );
1963 else
1964 widget_setStatus( wgt, WIDGET_STATUS_NORMAL );
1965
1966 break;
1967 }
1968
1969 return ret;
1970}
1971
1978static SDL_Keymod toolkit_mapMod( SDL_Keycode key )
1979{
1980 switch(key) {
1981 case SDLK_LCTRL:
1982 return KMOD_LCTRL;
1983 case SDLK_RCTRL:
1984 return KMOD_RCTRL;
1985 case SDLK_LALT:
1986 return KMOD_LALT;
1987 case SDLK_RALT:
1988 return KMOD_RALT;
1989 case SDLK_LSHIFT:
1990 return KMOD_LSHIFT;
1991 case SDLK_RSHIFT:
1992 return KMOD_RSHIFT;
1993 default:
1994 return 0;
1995 }
1996}
1997
2003static void toolkit_regKey( SDL_Keycode key )
2004{
2005 /* See if our key is in fact a modifier key, and if it is, convert it to a mod.
2006 * If it is indeed a mod, do not register a new key but add the modifier to the mod mask instead.
2007 */
2008 SDL_Keymod mod = toolkit_mapMod(key);
2009 if (mod)
2010 input_mod |= mod;
2011 /* Don't reset values on repeat keydowns. */
2012 else
2013 input_key = key;
2014}
2015
2021static void toolkit_unregKey( SDL_Keycode key )
2022{
2023 /* See if our key is in fact a modifier key, and if it is, convert it to a mod.
2024 * If it is indeed a mod, do not unregister the key but subtract the modifier from the mod mask instead.
2025 */
2026 SDL_Keymod mod = toolkit_mapMod(key);
2027 if (mod)
2028 input_mod &= ~mod;
2029 else
2031}
2032
2037{
2038 input_key = 0;
2039}
2047static int toolkit_keyEvent( Window *wdw, SDL_Event* event )
2048{
2049 Widget *wgt;
2050 SDL_Keycode key;
2051 SDL_Keymod mod;
2052 int rep, ret;
2053
2054 /* Event info. */
2055 key = event->key.keysym.sym;
2056 mod = event->key.keysym.mod;
2057 rep = event->key.repeat;
2058
2059 /* Hack to simulate key repetition */
2060 if (event->type == SDL_KEYDOWN)
2061 toolkit_regKey(key);
2062 else if (event->type == SDL_KEYUP)
2063 toolkit_unregKey(key);
2064
2065 /* See if window is valid. */
2066 if (wdw == NULL)
2067 return 0;
2068
2069 /* Get widget. */
2070 wgt = toolkit_getFocus( wdw );
2071
2072 /* We only want keydown from now on. */
2073 if (event->type != SDL_KEYDOWN)
2074 return 0;
2075
2076 /* Trigger event function if exists. */
2077 if (wgt != NULL) {
2078 if (wgt->keyevent != NULL) {
2079 ret = wgt->keyevent( wgt, input_key, input_mod, rep );
2080 if (ret!=0)
2081 return ret;
2082 }
2083 }
2084
2085 if (input_key != 0 && !rep) {
2086 /* Handle button hotkeys. We don't want a held-down key to keep activating buttons, so forbid "repeat". */
2087 for ( wgt = wdw->widgets; wgt != NULL; wgt = wgt->next ) {
2088 if ( ( wgt->type == WIDGET_BUTTON ) && ( wgt->dat.btn.key == input_key )
2089 && wgt->keyevent != NULL ) {
2090 ret = wgt->keyevent( wgt, SDLK_RETURN, input_mod, rep );
2091 if (ret!=0)
2092 return ret;
2093 }
2094 }
2095
2096 /* Handle other cases where event might be used by the window... and we don't want key-repeat. */
2097 switch (key) {
2098 case SDLK_RETURN:
2099 case SDLK_KP_ENTER:
2100 if (wdw->accept_fptr != NULL) {
2101 wdw->accept_fptr( wdw->id, wdw->name );
2102 return 1;
2103 }
2104 break;
2105
2106 case SDLK_ESCAPE:
2107 if (wdw->cancel_fptr != NULL) {
2108 wdw->cancel_fptr( wdw->id, wdw->name );
2109 return 1;
2110 }
2111 break;
2112
2113 default:
2114 break;
2115 }
2116 }
2117
2118 /* Finally the stuff gets passed to the custom key handler if it's defined. */
2119 if (wdw->keyevent != NULL) {
2120 ret = (*wdw->keyevent)( wdw->id, input_key, input_mod, rep );
2121 if (ret!=0)
2122 return ret;
2123 }
2124
2125 /* Placed here so it can be overriden in console for tab completion. */
2126 if (key == SDLK_TAB) {
2127 if (mod & (KMOD_LSHIFT | KMOD_RSHIFT))
2128 toolkit_prevFocus( wdw );
2129 else
2130 toolkit_nextFocus( wdw );
2131 return 1;
2132 }
2133
2134 return 0;
2135}
2136static int toolkit_textEvent( Window *wdw, SDL_Event* event )
2137{
2138 Widget *wgt;
2139
2140 /* See if window is valid. */
2141 if (wdw == NULL)
2142 return 0;
2143
2144 /* Get widget. */
2145 wgt = toolkit_getFocus( wdw );
2146
2147 /* Trigger event function if exists. */
2148 if ((wgt != NULL) && (wgt->textevent != NULL)) {
2149 int ret = (*wgt->textevent)( wgt, event->text.text );
2150 if (ret!=0)
2151 return ret;
2152 }
2153
2154 return 0;
2155}
2156
2160static void toolkit_purgeDead (void)
2161{
2162 Window *wdw, *wlast;
2163
2164 /* Must be windows. */
2165 if (windows == NULL)
2166 return;
2167
2168 /* Destroy what is needed. */
2169 wlast = NULL;
2170 wdw = windows;
2171 while (wdw != NULL) {
2172 if (window_isFlag( wdw, WINDOW_KILL )) {
2173 /* Save target. */
2174 Window *wkill = wdw;
2175 /* Clean up while still in list. */
2176 window_cleanup( wdw );
2177 /* Reattach linked list. */
2178 if (wlast == NULL)
2179 windows = wdw->next;
2180 else
2181 wlast->next = wdw->next;
2182 wdw = wlast;
2183 /* Kill target. */
2184 wkill->next = NULL;
2185 window_remove( wkill );
2186 }
2187 else {
2188 Widget *wgtlast = NULL;
2189 Widget *wgt = wdw->widgets;
2190 while (wgt != NULL) {
2191 if (wgt_isFlag( wgt, WGT_FLAG_KILL )) {
2192 /* Save target. */
2193 Widget *wgtkill = wgt;
2194 /* Reattach linked list. */
2195 if (wgtlast == NULL)
2196 wdw->widgets = wgt->next;
2197 else
2198 wgtlast->next = wgt->next;
2199 wgt = wgtlast;
2200 /* Kill target. */
2201 wgtkill->next = NULL;
2202 widget_kill( wgtkill );
2203 }
2204 /* Save position. */
2205 wgtlast = wgt;
2206 if (wgt == NULL)
2207 wgt = wdw->widgets;
2208 else
2209 wgt = wgt->next;
2210 }
2211 }
2212 /* Save position. */
2213 wlast = wdw;
2214 if (wdw == NULL)
2215 wdw = windows;
2216 else
2217 wdw = wdw->next;
2218 }
2219}
2220
2225{
2226 /* Clean up the dead if needed. */
2227 if (!dialogue_isOpen()) { /* Hack, since dialogues use secondary loop. */
2228 if (toolkit_delayCounter > 0)
2230 else
2232 }
2233
2234 /* Killed all the windows. */
2235 if (!toolkit_isOpen()) {
2236
2238 if (paused && !player_paused)
2239 unpause_game();
2240 }
2241}
2242
2249static void toolkit_expose( Window *wdw, int expose )
2250{
2251 if (expose == wdw->exposed)
2252 return;
2253 else
2254 wdw->exposed = expose;
2255
2256 if (expose)
2257 toolkit_focusSanitize( wdw );
2258 else
2259 toolkit_focusClear( wdw );
2260
2261 if (wdw->focus != -1)
2262 return;
2263
2264 /* Notify widgets (for tabbed children, etc.) */
2265 for (Widget *wgt = wdw->widgets; wgt != NULL; wgt = wgt->next)
2266 if (wgt->exposeevent != NULL)
2267 wgt->exposeevent( wgt, expose );
2268}
2269
2273void toolkit_focusClear( Window *wdw )
2274{
2275 if (wdw->focus == -1)
2276 return;
2277
2278 for (Widget *wgt=wdw->widgets; wgt!=NULL; wgt=wgt->next)
2279 toolkit_defocusWidget( wdw, wgt );
2280}
2281
2287void toolkit_focusSanitize( Window *wdw )
2288{
2289 int focus = wdw->focus;
2290
2291 /* Clear focus. */
2292 toolkit_focusClear( wdw );
2293
2294 /* No focus is always safe. */
2295 if (focus == -1)
2296 return;
2297
2298 /* Check focused widget. */
2299 for (Widget *wgt=wdw->widgets; wgt!=NULL; wgt=wgt->next) {
2300 if (focus == wgt->id) {
2301 /* Not focusable. */
2302 if (!toolkit_isFocusable(wgt))
2303 toolkit_nextFocus( wdw ); /* Get first focus. */
2304 else
2305 toolkit_focusWidget( wdw, wgt );
2306
2307 return;
2308 }
2309 }
2310}
2311
2315void toolkit_nextFocus( Window *wdw )
2316{
2317 int next;
2318
2319 /* Clear focus. */
2320 toolkit_focusClear( wdw );
2321
2322 /* See what to focus. */
2323 next = (wdw->focus == -1);
2324 for (Widget *wgt=wdw->widgets; wgt!=NULL; wgt=wgt->next) {
2325 if (!toolkit_isFocusable(wgt))
2326 continue;
2327
2328 if (next) {
2329 toolkit_focusWidget( wdw, wgt );
2330 return;
2331 }
2332 else if (wdw->focus == wgt->id) {
2333 next = 1;
2334 }
2335 }
2336
2337 /* Focus nothing. */
2338 wdw->focus = -1;
2340 return;
2341}
2342
2346void toolkit_prevFocus( Window *wdw )
2347{
2348 Widget *prev;
2349 int focus = wdw->focus;
2350
2351 /* Clear focus. */
2352 toolkit_focusClear( wdw );
2353
2354 /* See what to focus. */
2355 prev = NULL;
2356 for (Widget *wgt=wdw->widgets; wgt!=NULL; wgt=wgt->next) {
2357 if (!toolkit_isFocusable(wgt))
2358 continue;
2359
2360 /* See if we found the current one. */
2361 if (focus == wgt->id) {
2362 if (prev != NULL)
2363 toolkit_focusWidget( wdw, prev );
2364 return;
2365 }
2366
2367 /* Store last focusable widget. */
2368 prev = wgt;
2369 }
2370
2371 /* Focus nothing. */
2372 if (prev != NULL)
2373 toolkit_focusWidget( wdw, prev );
2374
2375 return;
2376}
2377
2381void toolkit_focusWidget( Window *wdw, Widget *wgt )
2382{
2383 if (!toolkit_isFocusable(wgt) || wgt_isFlag( wgt, WGT_FLAG_FOCUSED ))
2384 return;
2385
2386 wdw->focus = wgt->id;
2387 wgt_setFlag( wgt, WGT_FLAG_FOCUSED );
2388 if (wgt->focusGain != NULL)
2389 wgt->focusGain( wgt );
2390
2392}
2393
2398void toolkit_defocusWidget( Window *wdw, Widget *wgt )
2399{
2400 if (wdw->focus != wgt->id || !wgt_isFlag( wgt, WGT_FLAG_FOCUSED ))
2401 return;
2402
2403 wdw->focus = -1;
2404 wgt_rmFlag( wgt, WGT_FLAG_FOCUSED );
2405 if (wgt->focusLose != NULL)
2406 wgt->focusLose( wgt );
2407
2409}
2410
2417static int toolkit_isFocusable( const Widget *wgt )
2418{
2419 if (wgt==NULL)
2420 return 0;
2421
2422 return wgt_isFlag(wgt, WGT_FLAG_CANFOCUS);
2423}
2424
2431{
2432 /* Get window that can be focused. */
2433 Window *wlast = NULL;
2434 for (Window *wdw = windows; wdw!=NULL; wdw = wdw->next)
2435 if (!window_isFlag(wdw, WINDOW_NOFOCUS) &&
2436 !window_isFlag(wdw, WINDOW_KILL))
2437 wlast = wdw;
2438 return wlast;
2439}
2440
2447static Widget* toolkit_getFocus( Window *wdw )
2448{
2449 /* No focus. */
2450 if (wdw->focus == -1)
2451 return NULL;
2452
2453 /* Find focus. */
2454 for (Widget *wgt=wdw->widgets; wgt!=NULL; wgt=wgt->next)
2455 if (wdw->focus == wgt->id)
2456 return wgt;
2457
2458 /* Not found. */
2459 toolkit_focusClear( wdw );
2460 wdw->focus = -1;
2461 return NULL;
2462}
2463
2471void window_setFocus( unsigned int wid, const char* wgtname )
2472{
2473 Window *wdw;
2474 Widget *wgt;
2475
2476 /* Get window. */
2477 wdw = window_wget(wid);
2478 if (wdw == NULL)
2479 return;
2480
2481 toolkit_focusClear( wdw );
2482
2483 /* Get widget. */
2484 wgt = wgtname==NULL ? NULL : window_getwgt( wid, wgtname );
2485 if (wgt == NULL)
2486 return;
2487
2488 toolkit_focusWidget( wdw, wgt );
2489}
2490
2497char* window_getFocus( unsigned int wid )
2498{
2499 /* Get window. */
2500 Window *wdw = window_wget(wid);
2501 if (wdw == NULL)
2502 return NULL;
2503
2504 /* Find focused widget. */
2505 for (Widget *wgt=wdw->widgets; wgt!=NULL; wgt=wgt->next)
2506 if (wgt->id == wdw->focus)
2507 return strdup( wgt->name );
2508
2509 return NULL;
2510}
2511
2517void window_raise( unsigned int wid )
2518{
2519 Window *wdw, *wtmp, *wprev, *wlast;
2520
2521 wdw = window_wget(wid);
2522
2523 /* Not found, or already top of the stack. */
2524 if (wdw == NULL || wdw->next == NULL)
2525 return;
2526
2527 wprev = NULL;
2528 wlast = NULL;
2529
2530 for (wtmp = windows; wtmp != NULL; wtmp = wtmp->next)
2531 if (wtmp->next == wdw)
2532 wprev = wtmp;
2533 else if (wtmp->next == NULL)
2534 wlast = wtmp;
2535
2536 if (wprev != NULL)
2537 wprev->next = wdw->next; /* wdw-1 links to wdw+1 */
2538
2539 if (wlast != NULL)
2540 wlast->next = wdw; /* last links to wdw */
2541
2542 wdw->next = NULL; /* wdw becomes new last window */
2543
2544 wtmp = toolkit_getActiveWindow();
2545
2546 /* No active window, or window is the same. */
2547 if (wtmp == NULL || wtmp == wdw)
2548 return;
2549
2550 toolkit_expose( wtmp, 0 ); /* wtmp is hidden */
2551 toolkit_expose( wdw, 1 ); /* wdw is visible */
2553}
2554
2560void window_lower( unsigned int wid )
2561{
2562 Window *wdw, *wtmp, *wprev;
2563
2564 wdw = window_wget(wid);
2565
2566 /* Not found, or already bottom of the stack. */
2567 if (wdw == NULL || wdw == windows)
2568 return;
2569
2570 wprev = NULL;
2571 for (wtmp = windows; wtmp != NULL; wtmp = wtmp->next)
2572 if (wtmp->next == wdw)
2573 wprev = wtmp;
2574
2575 if (wprev != NULL)
2576 wprev->next = wdw->next; /* wdw-1 links to wdw+1 */
2577
2578 wdw->next = windows; /* wdw links to first window */
2579 windows = wdw; /* wdw becomes new first window */
2580
2581 wtmp = toolkit_getActiveWindow();
2582
2583 /* No active window, or window is the same. */
2584 if (wtmp == NULL || wtmp == wdw)
2585 return;
2586
2587 toolkit_expose( wtmp, 1 ); /* wtmp is visible */
2588 toolkit_expose( wdw, 0 ); /* wdw is hidden */
2590}
2591
2596{
2597 for (Window *w = windows; w != NULL; w = w->next) {
2598 int xdiff, ydiff;
2599
2600 /* Fullscreen windows must always be full size, though their widgets
2601 * don't auto-scale. */
2602 if (window_isFlag( w, WINDOW_FULLSCREEN )) {
2603 w->w = gl_screen.nw;
2604 w->h = gl_screen.nh;
2605 continue;
2606 }
2607
2608 /* Skip if position is fixed. */
2609 if (w->xrel == -1. && w->yrel == -1.)
2610 continue;
2611
2612 xdiff = 0.;
2613 ydiff = 0.;
2614
2615 if (w->xrel != -1.) {
2616 int xorig = w->x;
2617 w->x = (gl_screen.nw - w->w) * w->xrel;
2618 xdiff = w->x - xorig;
2619 }
2620
2621 if (w->yrel != -1.) {
2622 int yorig = w->y;
2623 w->y = (gl_screen.nh - w->h) * w->yrel;
2624 ydiff = w->y - yorig;
2625 }
2626
2627 /* Tabwin children aren't in the stack and must be manually updated. */
2628 for (Widget *wgt=w->widgets; wgt!=NULL; wgt=wgt->next) {
2629 if (wgt->type != WIDGET_TABBEDWINDOW)
2630 continue;
2631
2632 for (int i=0; i<wgt->dat.tab.ntabs; i++) {
2633 Window *wtmp = window_wget( wgt->dat.tab.windows[i] );
2634 wtmp->x += xdiff;
2635 wtmp->y += ydiff;
2636 }
2637 }
2638 }
2640}
2641
2648{
2649 GLsizei size;
2650
2651 /* Create the VBO. */
2652 toolkit_vboColourOffset = sizeof(GLshort) * 2 * 31;
2653 size = (sizeof(GLshort)*2 + sizeof(GLfloat)*4) * 31;
2654 toolkit_vbo = gl_vboCreateStream( size, NULL );
2655
2656 /* Disable the cursor. */
2658
2659 return 0;
2660}
2661
2665void toolkit_exit (void)
2666{
2667 /* Destroy the windows. */
2668 while (windows!=NULL) {
2669 Window *wdw = windows;
2670 windows = windows->next;
2671 window_cleanup(wdw);
2672 window_remove(wdw);
2673 }
2674
2675 /* Free the VBO. */
2677 toolkit_vbo = NULL;
2678}
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:1027
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:961
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:788
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:870
void input_clicked(void *clicked)
Sets the last-clicked item, for double-click detection.
Definition input.c:1449
void input_mouseShow(void)
Shows the mouse.
Definition input.c:368
int input_isDoubleClick(void *clicked)
Checks whether a clicked item is the same as the last-clicked.
Definition input.c:1462
void input_mouseHide(void)
Hides the mouse.
Definition input.c:377
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
Header file with generic functions and naev-specifics.
#define MIN(x, y)
Definition naev.h:40
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:246
gl_vbo * gl_vboCreateStream(GLsizei size, const void *data)
Creates a stream vbo.
Definition opengl_vbo.c:145
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:226
void gl_vboSubData(gl_vbo *vbo, GLint offset, GLsizei size, const void *data)
Loads some data into the VBO.
Definition opengl_vbo.c:130
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
int h
Definition font.h:18
double myscale
Definition opengl.h:58
GLuint fbo_tex[OPENGL_NUM_FBOS]
Definition opengl.h:72
double mxscale
Definition opengl.h:57
GLuint fbo[OPENGL_NUM_FBOS]
Definition opengl.h:71
int nw
Definition opengl.h:47
int nh
Definition opengl.h:48
GLuint current_fbo
Definition opengl.h:70
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:709
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:691
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:2398
void window_setOnFocus(unsigned int wid, void(*focus)(unsigned int))
Sets the focus function of the window.
Definition toolkit.c:888
void window_renderDynamic(Window *w)
Renders the dynamic components of a window.
Definition toolkit.c:1540
static GLsizei toolkit_vboColourOffset
Definition toolkit.c:66
void toolkit_resize(void)
Repositions windows and their children if resolution changes.
Definition toolkit.c:2595
void toolkit_update(void)
Updates the toolkit input for repeating keys.
Definition toolkit.c:2224
void window_dimWidget(unsigned int wid, const char *name, int *w, int *h)
Gets the dimensions of a widget.
Definition toolkit.c:416
void toolkit_exit(void)
Exits the toolkit.
Definition toolkit.c:2665
static Widget * toolkit_getFocus(Window *wdw)
Gets the focused widget in a window.
Definition toolkit.c:2447
void window_setDynamic(unsigned int wid, int dynamic)
Sets a window as dynamic, so that it is drawn every frame completely.
Definition toolkit.c:647
unsigned int window_getParent(unsigned int wid)
Gets the window's parent.
Definition toolkit.c:806
void toolkit_drawScrollbar(int x, int y, int w, int h, double pos)
Draws a scrollbar.
Definition toolkit.c:1577
static SDL_Keymod toolkit_mapMod(SDL_Keycode key)
Maps modifier keysyms (ctrl, alt, shift) to SDL_Keymods.
Definition toolkit.c:1978
void window_setFocus(unsigned int wid, const char *wgtname)
Sets the focused widget in a window.
Definition toolkit.c:2471
void window_render(Window *w, int top)
Renders a window.
Definition toolkit.c:1509
static unsigned int genwid
Definition toolkit.c:29
const glColour * toolkit_col
Definition toolkit.c:50
static void toolkit_purgeDead(void)
Purges the dead windows.
Definition toolkit.c:2160
void window_setAccept(unsigned int wid, void(*accept)(unsigned int, const char *))
Sets the default accept function of the window.
Definition toolkit.c:847
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:94
void window_move(unsigned int wid, int x, int y)
Moves a window to the specified coordinates.
Definition toolkit.c:179
void window_setCancel(unsigned int wid, void(*cancel)(unsigned int, const char *))
Sets the default cancel function of the window.
Definition toolkit.c:868
static int toolkit_mouseEvent(Window *w, SDL_Event *event)
Handles the mouse events.
Definition toolkit.c:1827
Window * window_wgetW(unsigned int wid)
Gets a Window by ID, without warning.
Definition toolkit.c:317
int window_existsID(unsigned int wid)
Checks to see if a window with a certain ID exists.
Definition toolkit.c:612
static void window_renderBorder(const Window *w)
Renders a window border.
Definition toolkit.c:1470
static void widget_kill(Widget *wgt)
Destroy a widget really.
Definition toolkit.c:1195
static void toolkit_unregKey(SDL_Keycode key)
Unregisters a key.
Definition toolkit.c:2021
void toolkit_drawAltText(int bx, int by, const char *alt)
Draws an alt text.
Definition toolkit.c:1429
const glColour * tab_background
Definition toolkit.c:60
const glColour * tab_inactiveB
Definition toolkit.c:59
void toolkit_closeAll(void)
Closes all open toolkit windows.
Definition toolkit.c:1014
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:1851
void window_onClose(unsigned int wid, void(*fptr)(unsigned int, const char *))
Sets the default close function of the window.
Definition toolkit.c:826
const glColour * tab_inactive
Definition toolkit.c:58
void window_canFocusWidget(unsigned int wid, const char *name, int canfocus)
Allows or disallows focusing a widget.
Definition toolkit.c:521
void toolkit_clearKey(void)
Clears the registered keys.
Definition toolkit.c:2036
void window_raise(unsigned int wid)
Raises a window (causes all other windows to appear below it).
Definition toolkit.c:2517
void toolkit_drawRect(int x, int y, int w, int h, const glColour *c, const glColour *lc)
Draws a rectangle.
Definition toolkit.c:1343
static void window_remove(Window *wdw)
Frees up a window. Make sure to clean up the window first.
Definition toolkit.c:1116
static SDL_Keycode input_key
Definition toolkit.c:43
static int toolkit_delayCounter
Definition toolkit.c:32
void toolkit_focusSanitize(Window *wdw)
Sanitizes the focus of a window.
Definition toolkit.c:2287
void window_moveWidget(unsigned int wid, const char *name, int x, int y)
Moves a widget.
Definition toolkit.c:465
const glColour * tab_activeB
Definition toolkit.c:57
Widget * window_newWidget(Window *w, const char *name)
Allocates room for a new widget.
Definition toolkit.c:226
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:196
void toolkit_drawTriangle(int x1, int y1, int x2, int y2, int x3, int y3, const glColour *c)
Draws a rectangle.
Definition toolkit.c:1391
void toolkit_delay(void)
Delays the toolkit purge by an iteration, useful for dialogues.
Definition toolkit.c:106
static void window_cleanup(Window *wdw)
Cleans up the window, should be done before window_remove.
Definition toolkit.c:1102
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:2381
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:2249
Uint32 toolkit_inputTranslateCoords(const Window *w, SDL_Event *event, int *x, int *y, int *rx, int *ry)
Translates the mouse coordinates.
Definition toolkit.c:1761
int toolkit_init(void)
Initializes the toolkit.
Definition toolkit.c:2647
Window * window_wgetNameW(const char *name)
Gets a Window by name, without warning.
Definition toolkit.c:331
void window_destroyWidget(unsigned int wid, const char *wgtname)
Destroys a widget in a window.
Definition toolkit.c:1165
static int toolkit_isFocusable(const Widget *wgt)
Checks to see if a widget is focusable.
Definition toolkit.c:2417
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:566
static gl_vbo * toolkit_vbo
Definition toolkit.c:65
void toolkit_setWindowPos(Window *wdw, int x, int y)
Moves a window to the specified coordinates.
Definition toolkit.c:141
void toolkit_render(double dt)
Renders the windows.
Definition toolkit.c:1593
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:1216
void toolkit_prevFocus(Window *wdw)
Focus previous widget.
Definition toolkit.c:2346
int window_isTop(unsigned int wid)
Checks to see if a window is at the top.
Definition toolkit.c:549
void window_handleKeys(unsigned int wid, int(*keyhandler)(unsigned int, SDL_Keycode, SDL_Keymod, int))
Sets the key handler for the window.
Definition toolkit.c:960
const glColour * toolkit_colDark
Definition toolkit.c:51
unsigned int window_get(const char *wdwname)
Gets the ID of a window.
Definition toolkit.c:666
void window_lower(unsigned int wid)
Lowers a window (causes all other windows to appear above it).
Definition toolkit.c:2560
void window_setBorder(unsigned int wid, int enable)
Sets or removes the border of a window.
Definition toolkit.c:941
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:1293
void toolkit_nextFocus(Window *wdw)
Focus next widget.
Definition toolkit.c:2315
int toolkit_input(SDL_Event *event)
Toolkit input handled here.
Definition toolkit.c:1672
void toolkit_rerender(void)
Marks the toolkit for needing a full rerender.
Definition toolkit.c:1661
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:922
void toolkit_setPos(const Window *wdw, Widget *wgt, int x, int y)
Sets the internal widget position.
Definition toolkit.c:119
void window_kill(Window *wdw)
Kills the window (and children).
Definition toolkit.c:1086
void window_setParent(unsigned int wid, unsigned int parent)
Sets a window as a window's parent.
Definition toolkit.c:789
void window_setData(unsigned int wid, void *data)
Sets custom data for a window.
Definition toolkit.c:905
static SDL_Keymod input_mod
Definition toolkit.c:44
void window_resizeWidget(unsigned int wid, const char *name, int w, int h)
Resizes a widget.
Definition toolkit.c:493
int toolkit_inputWindow(Window *wdw, SDL_Event *event, int purge)
Toolkit window input is handled here.
Definition toolkit.c:1686
void toolkit_focusClear(Window *wdw)
Clears the window focus.
Definition toolkit.c:2273
int window_exists(const char *wdwname)
Checks to see if a window exists.
Definition toolkit.c:596
const glColour * toolkit_colLight
Definition toolkit.c:49
int widget_exists(unsigned int wid, const char *wgtname)
Checks to see if a widget exists.
Definition toolkit.c:1142
static Window * windows
Definition toolkit.c:38
void widget_cleanup(Widget *widget)
Destroys a widget.
Definition toolkit.c:994
int window_setDisplayname(unsigned int wid, const char *displayname)
Sets the displayname of a window.
Definition toolkit.c:629
static void toolkit_regKey(SDL_Keycode key)
Registers a key as down (for key repetition).
Definition toolkit.c:2003
static int toolkit_keyEvent(Window *wdw, SDL_Event *event)
Handles keyboard events.
Definition toolkit.c:2047
void window_close(unsigned int wid, const char *str)
Helper function to automatically close the window calling it.
Definition toolkit.c:1026
Window * toolkit_getActiveWindow(void)
Gets the active window in the toolkit.
Definition toolkit.c:2430
void window_destroy(unsigned int wid)
Kills the window.
Definition toolkit.c:1037
char * window_getFocus(unsigned int wid)
Gets the focused widget in a window (does strdup!!).
Definition toolkit.c:2497
void window_handleEvents(unsigned int wid, int(*eventhandler)(unsigned int, SDL_Event *))
Sets the event handler for the window.
Definition toolkit.c:977
void window_renderOverlay(Window *w)
Renders the window overlays.
Definition toolkit.c:1560
static int toolkit_needsRender
Definition toolkit.c:31
const glColour * tab_active
Definition toolkit.c:56