naev 0.12.5
toolkit.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include "naev.h"
12
13#include "toolkit.h"
14
15#include "dialogue.h"
16#include "input.h"
17#include "log.h"
18#include "ntracing.h"
19#include "opengl.h"
20#include "pause.h"
21#include "tk/toolkit_priv.h"
22
23#define INPUT_DELAY conf.repeat_delay
24#define INPUT_FREQ conf.repeat_freq
25
26static unsigned int genwid = 0;
27
29 1;
31 0;
32
33/*
34 * window stuff
35 */
36#define MIN_WINDOWS 4
37static Window *windows =
38 NULL;
39
40/*
41 * simulate keypresses when holding
42 */
43static SDL_Keycode input_key = 0;
44static SDL_Keymod input_mod = 0;
45
46/*
47 * default outline colours
48 */
49const glColour *toolkit_colLight = &cGrey50;
50const glColour *toolkit_col = &cGrey20;
51const glColour *toolkit_colDark = &cGrey5;
52
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;
61
62/*
63 * VBO
64 */
65static gl_vbo *toolkit_vbo;
67
68/*
69 * static prototypes
70 */
71/* input */
72static int toolkit_mouseEvent( Window *w, SDL_Event *event );
73static int toolkit_mouseEventWidget( Window *w, Widget *wgt, SDL_Event *event,
74 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 void toolkit_expose( Window *wdw, int expose );
80/* render */
81static void window_renderBorder( const Window *w );
82/* Death. */
83static void widget_kill( Widget *wgt );
84static void window_cleanup( Window *wdw );
85static void window_remove( Window *wdw );
86static void toolkit_purgeDead( void );
87
93int toolkit_isOpen( void )
94{
95 /* Check to see if there is any active window. */
96 for ( Window *wdw = windows; wdw != NULL; wdw = wdw->next )
97 if ( !window_isFlag( wdw, WINDOW_KILL | WINDOW_NORENDER ) )
98 return 1;
99 return 0;
100}
101
105void toolkit_delay( void )
106{
108}
109
118void toolkit_setPos( const Window *wdw, Widget *wgt, int x, int y )
119{
120 /* X position. */
121 if ( x < 0 )
122 wgt->x = wdw->w - wgt->w + x;
123 else
124 wgt->x = (double)x;
125
126 /* Y position. */
127 if ( y < 0 )
128 wgt->y = wdw->h - wgt->h + y;
129 else
130 wgt->y = (double)y;
131}
132
140void toolkit_setWindowPos( Window *wdw, int x, int y )
141{
142 wdw->xrel = -1.;
143 wdw->yrel = -1.;
144
145 window_rmFlag( wdw, WINDOW_CENTERX );
146 window_rmFlag( wdw, WINDOW_CENTERY );
147
148 /* x pos */
149 if ( x == -1 ) { /* Center */
150 wdw->x = ( gl_screen.nw - wdw->w ) / 2.;
151 wdw->xrel = 0.5;
152 window_setFlag( wdw, WINDOW_CENTERX );
153 } else if ( x < 0 )
154 wdw->x = gl_screen.nw - wdw->w + (double)x;
155 else
156 wdw->x = (double)x;
157
158 /* y pos */
159 if ( y == -1 ) { /* Center */
160 wdw->y = ( gl_screen.nh - wdw->h ) / 2.;
161 wdw->yrel = 0.5;
162 window_setFlag( wdw, WINDOW_CENTERY );
163 } else if ( y < 0 )
164 wdw->y = gl_screen.nh - wdw->h + (double)y;
165 else
166 wdw->y = (double)y;
167}
168
176void window_move( unsigned int wid, int x, int y )
177{
178 /* Get the window. */
179 Window *wdw = window_wget( wid );
180 if ( wdw == NULL )
181 return;
182
183 toolkit_setWindowPos( wdw, x, y );
184}
185
193void window_resize( unsigned int wid, int w, int h )
194{
195 /* Get the window. */
196 Window *wdw = window_wget( wid );
197 if ( wdw == NULL )
198 return;
199
200 wdw->w = ( w == -1 ) ? gl_screen.nw : (double)w;
201 wdw->h = ( h == -1 ) ? gl_screen.nh : (double)h;
202 if ( ( w == -1 ) && ( h == -1 ) ) {
203 window_setFlag( wdw, WINDOW_FULLSCREEN );
204 wdw->x = 0.;
205 wdw->y = 0.;
206 window_setFlag( wdw, WINDOW_CENTERX );
207 window_setFlag( wdw, WINDOW_CENTERY );
208 } else {
209 window_rmFlag( wdw, WINDOW_FULLSCREEN );
210 if ( window_isFlag( wdw, WINDOW_CENTERX ) &&
211 window_isFlag( wdw, WINDOW_CENTERY ) )
212 toolkit_setWindowPos( wdw, -1, -1 );
213 }
214}
215
223Widget *window_newWidget( Window *w, const char *name )
224{
225 Widget *wgt, *wlast, *wtmp;
226 char *saved_name = NULL;
227
228 /* NULL protection. */
229 if ( w == NULL )
230 return NULL;
231
232 /* Try to find one with the same name first. */
233 wlast = NULL;
234 for ( wgt = w->widgets; wgt != NULL; wgt = wgt->next ) {
235
236 /* Must match name. */
237 if ( strcmp( name, wgt->name ) != 0 ) {
238 wlast = wgt;
239 continue;
240 }
241
242 /* Should be destroyed. */
243 if ( !wgt_isFlag( wgt, WGT_FLAG_KILL ) ) {
244 WARN( _( "Trying to create widget '%s' over existing one that hasn't "
245 "been destroyed" ),
246 name );
247 return NULL;
248 }
249
250 /* Relink. */
251 if ( wlast == NULL )
252 w->widgets = wgt->next;
253 else
254 wlast->next = wgt->next;
255
256 /* Prepare and return this widget. */
257 saved_name = wgt->name;
258 wgt->name = NULL;
259 widget_cleanup( wgt );
260 break;
261 }
262
263 /* Must grow widgets. */
264 if ( wgt == NULL )
265 wgt = nmalloc( sizeof( Widget ) );
266
267 /* Safe defaults. */
268 memset( wgt, 0, sizeof( Widget ) );
269 wgt->type = WIDGET_NULL;
270 wgt->status = WIDGET_STATUS_NORMAL;
271 wgt->wdw = w->id;
272 if ( saved_name !=
273 NULL ) /* Hack to avoid frees so _getFocus works in the same frame. */
274 wgt->name = saved_name;
275 else
276 wgt->name = strdup( name );
277 wgt->id = ++w->idgen;
278
279 /* Set up. */
280 wlast = NULL;
281 for ( wtmp = w->widgets; wtmp != NULL; wtmp = wtmp->next )
282 wlast = wtmp;
283 if ( wlast == NULL )
284 w->widgets = wgt;
285 else
286 wlast->next = wgt;
287
289 return wgt;
290}
291
298Window *window_wget( unsigned int wid )
299{
300 if ( windows == NULL ) {
301 WARN( _( "Window '%u' not found in list!" ), wid );
302 return NULL;
303 }
304 Window *w = window_wgetW( wid );
305 if ( w == NULL )
306 WARN( _( "Window '%u' not found in list!" ), wid );
307 return w;
308}
309
316Window *window_wgetW( unsigned int wid )
317{
318 for ( Window *w = windows; w != NULL; w = w->next )
319 if ( w->id == wid )
320 return w;
321 return NULL;
322}
323
330Window *window_wgetNameW( const char *name )
331{
332 for ( Window *w = windows; w != NULL; w = w->next )
333 if ( strcmp( w->name, name ) == 0 )
334 return w;
335 return NULL;
336}
337
345Widget *window_getwgt( unsigned int wid, const char *name )
346{
347 /* Get the window. */
348 Window *wdw = window_wget( wid );
349 if ( wdw == NULL ) {
350 WARN( _( "Widget '%s' not found in window '%u'!" ), name, wid );
351 return NULL;
352 }
353
354 /* Find the widget. */
355 for ( Widget *wgt = wdw->widgets; wgt != NULL; wgt = wgt->next )
356 if ( strcmp( wgt->name, name ) == 0 )
357 return wgt;
358
359 WARN( _( "Widget '%s' not found in window '%u'!" ), name, wid );
360 return NULL;
361}
362
370void window_dimWindow( unsigned int wid, int *w, int *h )
371{
372 /* Get the window. */
373 const Window *wdw = window_wget( wid );
374 if ( wdw == NULL ) {
375 *w = -1;
376 *h = -1;
377 return;
378 }
379
380 /* Set dimensions. */
381 *w = wdw->w;
382 *h = wdw->h;
383}
384
392void window_posWindow( unsigned int wid, int *x, int *y )
393{
394 /* Get the window. */
395 const Window *wdw = window_wget( wid );
396 if ( wdw == NULL ) {
397 *x = -1;
398 *y = -1;
399 return;
400 }
401
402 /* Set dimensions. */
403 *x = wdw->x;
404 *y = wdw->y;
405}
406
415void window_dimWidget( unsigned int wid, const char *name, int *w, int *h )
416{
417 /* Get widget. */
418 const Widget *wgt = window_getwgt( wid, name );
419 if ( wgt == NULL ) {
420 if ( w != NULL )
421 *w = -1;
422 if ( h != NULL )
423 *h = -1;
424 return;
425 }
426
427 if ( w != NULL )
428 *w = wgt->w;
429 if ( h != NULL )
430 *h = wgt->h;
431}
432
441void window_posWidget( unsigned int wid, const char *name, int *x, int *y )
442{
443 /* Get widget. */
444 const Widget *wgt = window_getwgt( wid, name );
445 if ( wgt == NULL )
446 return;
447
448 /* Return position. */
449 if ( x != NULL )
450 ( *x ) = wgt->x;
451 if ( y != NULL )
452 ( *y ) = wgt->y;
453}
454
463void window_moveWidget( unsigned int wid, const char *name, int x, int y )
464{
465 Window *wdw;
466 Widget *wgt;
467
468 /* Get window. */
469 wdw = window_wget( wid );
470 if ( wdw == NULL )
471 return;
472
473 /* Get widget. */
474 wgt = window_getwgt( wid, name );
475 if ( wgt == NULL )
476 return;
477
478 /* Set position. */
479 toolkit_setPos( wdw, wgt, x, y );
480}
481
490void window_resizeWidget( unsigned int wid, const char *name, int w, int h )
491{
492 Window *wdw;
493 Widget *wgt;
494
495 /* Get window. */
496 wdw = window_wget( wid );
497 if ( wdw == NULL )
498 return;
499
500 /* Get widget. */
501 wgt = window_getwgt( wid, name );
502 if ( wgt == NULL )
503 return;
504
505 /* Set position. */
506 wgt->w = w;
507 wgt->h = h;
508}
509
517void window_canFocusWidget( unsigned int wid, const char *name, int canfocus )
518{
519 Window *wdw;
520 Widget *wgt;
521
522 /* Get window. */
523 wdw = window_wget( wid );
524 if ( wdw == NULL )
525 return;
526
527 /* Get widget. */
528 wgt = window_getwgt( wid, name );
529 if ( wgt == NULL )
530 return;
531
532 /* Set position. */
533 if ( canfocus )
534 wgt_setFlag( wgt, WGT_FLAG_CANFOCUS );
535 else
536 wgt_rmFlag( wgt, WGT_FLAG_CANFOCUS );
537}
538
544int window_isTop( unsigned int wid )
545{
546 Window *n, *w = window_wget( wid );
547 if ( w == NULL )
548 return 0;
549 n = w->next;
550 while ( n != NULL ) {
551 if ( !window_isFlag( n, WINDOW_KILL | WINDOW_NORENDER ) )
552 return 0;
553 n = n->next;
554 }
555 return 1;
556}
557
561int widget_isCovered( unsigned int wid, const char *name, int x, int y )
562{
563 int bx, by, rx, ry;
564 Widget *wgt = window_getwgt( wid, name );
565 if ( wgt == NULL )
566 return 0;
567
568 /* Undo transform. */
569 bx = x + wgt->x;
570 by = y + wgt->y;
571
572 /* Find if the point is covered. */
573 for ( Widget *w = wgt->next; w != NULL; w = w->next ) {
574 if ( ( wgt->render == NULL ) || wgt_isFlag( w, WGT_FLAG_KILL ) )
575 continue;
576
577 rx = bx - w->x;
578 ry = by - w->y;
579 if ( !( ( rx < 0 ) || ( rx >= w->w ) || ( ry < 0 ) || ( ry >= w->h ) ) )
580 return 1;
581 }
582 return 0;
583}
584
591int window_exists( const char *wdwname )
592{
593 if ( windows == NULL )
594 return 0;
595 for ( Window *w = windows; w != NULL; w = w->next )
596 if ( ( strcmp( w->name, wdwname ) == 0 ) &&
597 !window_isFlag( w, WINDOW_KILL ) )
598 return 1;
599 return 0; /* doesn't exist */
600}
601
608int window_existsID( unsigned int wid )
609{
610 if ( ( windows == NULL ) || ( wid == 0 ) )
611 return 0;
612 for ( Window *w = windows; w != NULL; w = w->next )
613 if ( ( w->id == wid ) && !window_isFlag( w, WINDOW_KILL ) )
614 return 1;
615 return 0; /* doesn't exist */
616}
617
625int window_setDisplayname( unsigned int wid, const char *displayname )
626{
627 Window *wdw = window_wget( wid );
628 if ( wdw == NULL )
629 return -1;
630 free( wdw->displayname );
631 wdw->displayname = NULL;
632 if ( displayname != NULL )
633 wdw->displayname = strdup( displayname );
634 return 0;
635}
636
643void window_setDynamic( unsigned int wid, int dynamic )
644{
645 Window *wdw = window_wget( wid );
646 if ( wdw == NULL )
647 return;
648 if ( dynamic )
649 wdw->flags |= WINDOW_DYNAMIC;
650 else
651 wdw->flags &= ~WINDOW_DYNAMIC;
652}
653
662unsigned int window_get( const char *wdwname )
663{
664 Window *last;
665 if ( windows == NULL )
666 return 0;
667 last = NULL;
668 for ( Window *w = windows; w != NULL; w = w->next )
669 if ( ( strcmp( w->name, wdwname ) == 0 ) &&
670 !window_isFlag( w, WINDOW_KILL ) )
671 last = w;
672 if ( last == NULL )
673 return 0;
674 return last->id;
675}
676
688unsigned int window_create( const char *name, const char *displayname,
689 const int x, const int y, const int w, const int h )
690{
691 return window_createFlags( name, displayname, x, y, w, h, 0 );
692}
693
706unsigned int window_createFlags( const char *name, const char *displayname,
707 const int x, const int y, const int w,
708 const int h, unsigned int flags )
709{
710 Window *wdw = ncalloc( 1, sizeof( Window ) );
711
712 const int wid = ( ++genwid ); /* unique id */
713
714 /* Create the window. */
715 wdw->id = wid;
716 wdw->name = strdup( name );
717 wdw->displayname = strdup( displayname );
718
719 /* Safe defaults. */
720 wdw->idgen = -1;
721 wdw->focus = -1;
722 wdw->xrel = -1.;
723 wdw->yrel = -1.;
724 wdw->flags = flags;
725 wdw->exposed = !window_isFlag( wdw, WINDOW_NOFOCUS );
726
727 /* Dimensions. */
728 wdw->w = ( w == -1 ) ? gl_screen.nw : (double)w;
729 wdw->h = ( h == -1 ) ? gl_screen.nh : (double)h;
730 if ( ( w == -1 ) && ( h == -1 ) ) {
731 window_setFlag( wdw, WINDOW_FULLSCREEN );
732 wdw->x = 0.;
733 wdw->y = 0.;
734 } else
735 toolkit_setWindowPos( wdw, x, y );
736
737 if ( !toolkit_isOpen() ) {
739 pause_game();
740 gl_defViewport(); /* Reset the default viewport */
741 }
742
743 /* Clear key repeat. */
745
746 /* Add to list. */
747 wdw->next = NULL;
748 if ( windows == NULL )
749 windows = wdw;
750 else {
751 Window *wlast;
752 /* Take focus from the old window. */
753 if ( wdw->exposed ) {
754 Window *wcur = toolkit_getActiveWindow();
755 if ( wcur != NULL )
756 toolkit_expose( wcur, 0 ); /* wcur is hidden */
757 }
758
759 wlast = windows;
760 while ( 1 ) {
761 if ( ( strcmp( wlast->name, name ) == 0 ) &&
762 !window_isFlag( wlast, WINDOW_KILL ) &&
763 !window_isFlag( wlast, WINDOW_NOFOCUS ) )
764 WARN( _( "Window with name '%s' already exists!" ), wlast->name );
765
766 if ( wlast->next == NULL )
767 break;
768
769 wlast = wlast->next;
770 }
771
772 wlast->next = wdw;
773 }
774
776 return wid;
777}
778
787void window_setParent( unsigned int wid, unsigned int parent )
788{
789 /* Get the window. */
790 Window *wdw = window_wget( wid );
791 if ( wdw == NULL )
792 return;
793
794 /* Set the parent. */
795 wdw->parent = parent;
796}
797
804unsigned int window_getParent( unsigned int wid )
805{
806 /* Get the window. */
807 const Window *wdw = window_wget( wid );
808 if ( wdw == NULL )
809 return 0;
810
811 /* Get the parent. */
812 return wdw->parent;
813}
814
824void window_onClose( unsigned int wid,
825 void ( *fptr )( unsigned int, const char * ) )
826{
827 /* Get the window. */
828 Window *wdw = window_wget( wid );
829 if ( wdw == NULL )
830 return;
831
832 /* Set the close function. */
833 wdw->close_fptr = fptr;
834}
835
846void window_setAccept( unsigned int wid,
847 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,
869 void ( *cancel )( unsigned int, const char * ) )
870{
871 /* Get the window. */
872 Window *wdw = window_wget( wid );
873 if ( wdw == NULL )
874 return;
875
876 /* Set the cancel function. */
877 wdw->cancel_fptr = cancel;
878}
879
889void window_setOnFocus( unsigned int wid, void ( *focus )( unsigned int ) )
890{
891 /* Get the window. */
892 Window *wdw = window_wget( wid );
893 if ( wdw == NULL )
894 return;
895
896 /* Set the cancel function. */
897 wdw->focus_fptr = focus;
898}
899
906void window_setData( unsigned int wid, void *data )
907{
908 /* Get the window. */
909 Window *wdw = window_wget( wid );
910 if ( wdw == NULL )
911 return;
912
913 /* Set data. */
914 wdw->udata = data;
915}
916
923void *window_getData( unsigned int wid )
924{
925 /* Get the window. */
926 const Window *wdw = window_wget( wid );
927 if ( wdw == NULL )
928 return NULL;
929
930 /* Get data. */
931 return wdw->udata;
932}
933
942void window_setBorder( unsigned int wid, int enable )
943{
944 /* Get the window. */
945 Window *wdw = window_wget( wid );
946 if ( wdw == NULL )
947 return;
948
949 if ( enable )
950 window_rmFlag( wdw, WINDOW_NOBORDER );
951 else
952 window_setFlag( wdw, WINDOW_NOBORDER );
953}
954
961void window_handleKeys( unsigned int wid,
962 int ( *keyhandler )( unsigned int, SDL_Keycode,
963 SDL_Keymod, int ) )
964{
965 /* Get the window. */
966 Window *wdw = window_wget( wid );
967 if ( wdw == NULL )
968 return;
969
970 /* Set key event handler function. */
971 wdw->keyevent = keyhandler;
972}
973
979void window_handleEvents( unsigned int wid,
980 int ( *eventhandler )( unsigned int, SDL_Event * ) )
981{
982 /* Get the window. */
983 Window *wdw = window_wget( wid );
984 if ( wdw == NULL )
985 return;
986
987 /* Set key event handler function. */
988 wdw->eventevent = eventhandler;
989}
990
996void widget_cleanup( Widget *widget )
997{
998 /* Type specific clean up. */
999 if ( widget->cleanup != NULL )
1000 widget->cleanup( widget );
1001
1002 /* General freeing. */
1003 free( widget->name );
1004}
1005
1006void widget_setStatus( Widget *wgt, WidgetStatus sts )
1007{
1008 if ( wgt->status != sts )
1010 wgt->status = sts;
1011}
1012
1017{
1018 for ( Window *w = windows; w != NULL; w = w->next )
1019 window_destroy( w->id );
1020}
1021
1028void window_close( unsigned int wid, const char *str )
1029{
1030 (void)str;
1031 window_destroy( wid );
1032}
1033
1039void window_destroy( unsigned int wid )
1040{
1041 if ( windows == NULL )
1042 return;
1043 /* Destroy the window */
1044 for ( Window *wdw = windows; wdw != NULL; wdw = wdw->next ) {
1045 Window *wactive;
1046
1047 /* Not the window we're looking for. */
1048 if ( wdw->id != wid )
1049 continue;
1050
1051 /* Already being killed, skip. */
1052 if ( window_isFlag( wdw, WINDOW_KILL ) )
1053 continue;
1054
1055 /* Mark children for death. */
1056 for ( Window *w = windows; w != NULL; w = w->next )
1057 if ( w->parent == wid )
1058 window_destroy( w->id );
1059
1060 /* Clean up. */
1061 window_cleanup( wdw );
1062 window_setFlag( wdw, WINDOW_KILL );
1064
1065 /* Disable text input, etc. */
1066 toolkit_focusClear( wdw );
1067
1068 wactive = toolkit_getActiveWindow();
1069 if ( wactive == NULL )
1070 break;
1071
1072 toolkit_expose( wactive, 1 );
1073 break;
1074 }
1075
1076 /* Do focus. */
1077 for ( Window *w = windows; w != NULL; w = w->next ) {
1078 if ( !window_isFlag( w, WINDOW_KILL ) && ( w->focus_fptr != NULL ) )
1079 w->focus_fptr( w->id );
1080 }
1081}
1082
1088void window_kill( Window *wdw )
1089{
1090 for ( Window *w = windows; w != NULL; w = w->next )
1091 if ( w->parent == wdw->id )
1092 window_kill( w );
1093 window_cleanup( wdw );
1094 window_setFlag( wdw, WINDOW_KILL );
1096}
1097
1104static void window_cleanup( Window *wdw )
1105{
1106 /* Run the close function first. */
1107 if ( wdw->close_fptr != NULL )
1108 wdw->close_fptr( wdw->id, wdw->name );
1109 wdw->close_fptr = NULL;
1110}
1111
1118static void window_remove( Window *wdw )
1119{
1120 Widget *wgt;
1121
1122 /* Destroy the window. */
1123 free( wdw->name );
1124 free( wdw->displayname );
1125 wgt = wdw->widgets;
1126 while ( wgt != NULL ) {
1127 Widget *wgtkill = wgt;
1128 wgt = wgtkill->next;
1129 widget_kill( wgtkill );
1130 }
1131 nfree( wdw );
1132
1133 /* Clear key repeat, since toolkit could miss the keyup event. */
1135}
1136
1144int widget_exists( unsigned int wid, const char *wgtname )
1145{
1146 /* Get window. */
1147 Window *w = window_wget( wid );
1148 if ( w == NULL ) {
1149 WARN( _( "window '%d' does not exist" ), wid );
1150 return 0;
1151 }
1152
1153 /* Check for widget. */
1154 for ( Widget *wgt = w->widgets; wgt != NULL; wgt = wgt->next )
1155 if ( strcmp( wgtname, wgt->name ) == 0 )
1156 return !wgt_isFlag( wgt, WGT_FLAG_KILL );
1157
1158 return 0;
1159}
1160
1167void window_destroyWidget( unsigned int wid, const char *wgtname )
1168{
1169 Window *wdw;
1170 Widget *wgt;
1171
1172 /* Get the window. */
1173 wdw = window_wget( wid );
1174 if ( wdw == NULL )
1175 return;
1176
1177 /* Get the widget. */
1178 for ( wgt = wdw->widgets; wgt != NULL; wgt = wgt->next )
1179 if ( strcmp( wgt->name, wgtname ) == 0 )
1180 break;
1181
1182 if ( wgt == NULL ) {
1183 WARN( _( "Widget '%s' not found in window '%s'" ), wgtname,
1184 wdw->displayname );
1185 return;
1186 }
1187
1188 toolkit_defocusWidget( wdw, wgt );
1189
1190 /* There's dead stuff now. */
1191 wgt_rmFlag( wgt, WGT_FLAG_FOCUSED );
1192 wgt_setFlag( wgt, WGT_FLAG_KILL );
1193}
1194
1195void window_clearWidgets( unsigned int wid )
1196{
1197 Window *wdw;
1198 Widget *wgt;
1199
1200 /* Get the window. */
1201 wdw = window_wget( wid );
1202 if ( wdw == NULL )
1203 return;
1204
1205 /* Get the widget. */
1206 for ( wgt = wdw->widgets; wgt != NULL; wgt = wgt->next ) {
1207 toolkit_defocusWidget( wdw, wgt );
1208
1209 /* There's dead stuff now. */
1210 wgt_rmFlag( wgt, WGT_FLAG_FOCUSED );
1211 wgt_setFlag( wgt, WGT_FLAG_KILL );
1212 }
1213}
1214
1218static void widget_kill( Widget *wgt )
1219{
1220 /* Clean up. */
1221 widget_cleanup( wgt );
1222 nfree( wgt );
1223}
1224
1239void toolkit_drawOutlineThick( int x, int y, int w, int h, int b, int thick,
1240 const glColour *c, const glColour *lc )
1241{
1242 GLshort tri[5][4];
1243 glColour colours[10];
1244
1245 x -= ( b - thick );
1246 w += 2 * ( b - thick );
1247 y -= ( b - thick );
1248 h += 2 * ( b - thick );
1249 lc = lc ? lc : c;
1250
1251 /* Left-up. */
1252 tri[0][0] = x; /* Inner */
1253 tri[0][1] = y;
1254 tri[0][2] = x - thick; /* Outer */
1255 tri[0][3] = y - thick;
1256 colours[0] = *lc;
1257 colours[1] = *lc;
1258
1259 /* Left-down. */
1260 tri[1][0] = x; /* Inner. */
1261 tri[1][1] = y + h;
1262 tri[1][2] = x - thick; /* Outer. */
1263 tri[1][3] = y + h + thick;
1264 colours[2] = *c;
1265 colours[3] = *c;
1266
1267 /* Right-down. */
1268 tri[2][0] = x + w; /* Inner. */
1269 tri[2][1] = y + h;
1270 tri[2][2] = x + w + thick; /* Outer. */
1271 tri[2][3] = y + h + thick;
1272 colours[4] = *c;
1273 colours[5] = *c;
1274
1275 /* Right-up. */
1276 tri[3][0] = x + w; /* Inner. */
1277 tri[3][1] = y;
1278 tri[3][2] = x + w + thick; /* Outer. */
1279 tri[3][3] = y - thick;
1280 colours[6] = *lc;
1281 colours[7] = *lc;
1282
1283 /* Left-up. */
1284 tri[4][0] = x; /* Inner */
1285 tri[4][1] = y;
1286 tri[4][2] = x - thick; /* Outer */
1287 tri[4][3] = y - thick;
1288 colours[8] = *lc;
1289 colours[9] = *lc;
1290
1291 /* Upload to the VBO. */
1292 gl_vboSubData( toolkit_vbo, 0, sizeof( tri ), tri );
1294 colours );
1295
1296 gl_beginSmoothProgram( gl_view_matrix );
1297 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex, 0, 2,
1298 GL_SHORT, 0 );
1299 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex_colour,
1300 toolkit_vboColourOffset, 4, GL_FLOAT, 0 );
1301 glDrawArrays( GL_TRIANGLE_STRIP, 0, 10 );
1302 gl_endSmoothProgram();
1303}
1304
1318void toolkit_drawOutline( int x, int y, int w, int h, int b, const glColour *c,
1319 const glColour *lc )
1320{
1321 GLshort lines[4][2];
1322 glColour colours[4];
1323
1324 x -= b, w += 2 * b;
1325 y -= b, h += 2 * b;
1326 lc = lc ? lc : c;
1327
1328 /* Lines. */
1329 lines[0][0] = x; /* left-up */
1330 lines[0][1] = y;
1331 colours[0] = *lc;
1332
1333 lines[1][0] = x; /* left-down */
1334 lines[1][1] = y + h;
1335 colours[1] = *c;
1336
1337 lines[2][0] = x + w; /* right-down */
1338 lines[2][1] = y + h;
1339 colours[2] = *c;
1340
1341 lines[3][0] = x + w; /* right-up */
1342 lines[3][1] = y;
1343 colours[3] = *lc;
1344
1345 /* Upload to the VBO. */
1346 gl_vboSubData( toolkit_vbo, 0, sizeof( lines ), lines );
1348 colours );
1349
1350 gl_beginSmoothProgram( gl_view_matrix );
1351 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex, 0, 2,
1352 GL_SHORT, 0 );
1353 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex_colour,
1354 toolkit_vboColourOffset, 4, GL_FLOAT, 0 );
1355 glDrawArrays( GL_LINE_LOOP, 0, 4 );
1356 gl_endSmoothProgram();
1357}
1358
1370void toolkit_drawRect( int x, int y, int w, int h, const glColour *c,
1371 const glColour *lc )
1372{
1373 GLshort vertex[4][2];
1374 glColour colours[4];
1375
1376 lc = lc == NULL ? c : lc;
1377
1378 /* Set up vertices and colours. */
1379 vertex[0][0] = x; /* left-up */
1380 vertex[0][1] = y;
1381 colours[0] = *c;
1382
1383 vertex[1][0] = x; /* left-down */
1384 vertex[1][1] = y + h;
1385 colours[1] = *lc;
1386
1387 vertex[2][0] = x + w; /* right-up */
1388 vertex[2][1] = y;
1389 colours[2] = *c;
1390
1391 vertex[3][0] = x + w; /* right-down */
1392 vertex[3][1] = y + h;
1393 colours[3] = *lc;
1394
1395 /* Upload to the VBO. */
1396 gl_vboSubData( toolkit_vbo, 0, sizeof( vertex ), vertex );
1398 colours );
1399
1400 gl_beginSmoothProgram( gl_view_matrix );
1401 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex, 0, 2,
1402 GL_SHORT, 0 );
1403 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex_colour,
1404 toolkit_vboColourOffset, 4, GL_FLOAT, 0 );
1405 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
1406 gl_endSmoothProgram();
1407}
1408
1420void toolkit_drawTriangle( int x1, int y1, int x2, int y2, int x3, int y3,
1421 const glColour *c )
1422{
1423 GLshort vertex[3][2];
1424 glColour colours[3];
1425
1426 /* Set up vertices and colours. */
1427 vertex[0][0] = x1; /* left-up */
1428 vertex[0][1] = y1;
1429 colours[0] = *c;
1430
1431 vertex[1][0] = x2; /* left-down */
1432 vertex[1][1] = y2;
1433 colours[1] = *c;
1434
1435 vertex[2][0] = x3; /* right-up */
1436 vertex[2][1] = y3;
1437 colours[2] = *c;
1438
1439 /* Upload to the VBO. */
1440 gl_vboSubData( toolkit_vbo, 0, sizeof( vertex ), vertex );
1442 colours );
1443
1444 gl_beginSmoothProgram( gl_view_matrix );
1445 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex, 0, 2,
1446 GL_SHORT, 0 );
1447 gl_vboActivateAttribOffset( toolkit_vbo, shaders.smooth.vertex_colour,
1448 toolkit_vboColourOffset, 4, GL_FLOAT, 0 );
1449 glDrawArrays( GL_TRIANGLE_STRIP, 0, 3 );
1450 gl_endSmoothProgram();
1451}
1452
1460void toolkit_drawAltText( int bx, int by, const char *alt )
1461{
1462 double w, h;
1463 double x, y;
1464 glColour c;
1465 glColour c2;
1466
1467 /* We're on top of anything previously drawn. */
1468 glClear( GL_DEPTH_BUFFER_BIT );
1469
1470 /* Get dimensions. */
1471 w = MIN( gl_printWidthRaw( &gl_smallFont, alt ), 400 );
1472 h = gl_printHeightRaw( &gl_smallFont, w, alt );
1473
1474 /* Choose position. */
1475 x = bx + 10.;
1476 y = by - h - gl_smallFont.h - 10.;
1477 if ( y < 10. )
1478 y = 10.;
1479 if ( x + w + 10. > gl_screen.nw )
1480 x -= w;
1481
1482 /* Set colours. */
1483 c.r = cGrey20.r;
1484 c.g = cGrey20.g;
1485 c.b = cGrey20.b;
1486 c.a = 0.9;
1487 c2.r = cGrey10.r;
1488 c2.g = cGrey10.g;
1489 c2.b = cGrey10.b;
1490 c2.a = 0.7;
1491 toolkit_drawRect( x + 1, y + 1, w + 18, h + 18, &c2, NULL );
1492 toolkit_drawRect( x, y, w + 18, h + 18, &c, NULL );
1493 gl_printTextRaw( &gl_smallFont, w, h, x + 9, y + 9, 0, &cFontWhite, -1.,
1494 alt );
1495}
1496
1502static void window_renderBorder( const Window *w )
1503{
1504 /* Position */
1505 double x = w->x;
1506 double y = w->y;
1507
1508 /*
1509 * Case fullscreen.
1510 */
1511 if ( window_isFlag( w, WINDOW_FULLSCREEN ) ) {
1512 /* Background. */
1513 toolkit_drawRect( x, y, w->w, w->h, toolkit_col, NULL );
1514 /* Name. */
1515 gl_printMidRaw( &gl_defFont, w->w, x, y + w->h - 20., &cFontWhite, -1.,
1516 w->displayname );
1517 return;
1518 }
1519
1520 toolkit_drawRect( x, y, w->w, w->h, toolkit_col, NULL );
1521 toolkit_drawOutlineThick( x, y, w->w, w->h, 1, 2, toolkit_colDark, NULL );
1522 toolkit_drawOutline( x + 3, y + 2, w->w - 5, w->h - 5, 1, toolkit_colLight,
1523 NULL );
1524
1525 /*
1526 * render window name
1527 */
1528 gl_printMidRaw( &gl_defFont, w->w, x, y + w->h - 20., &cFontWhite, -1.,
1529 w->displayname );
1530}
1531
1538void window_render( Window *w, int top )
1539{
1540 /* We're on top of anything previously drawn. */
1541 glClear( GL_DEPTH_BUFFER_BIT );
1542
1543 /* See if needs border. */
1544 if ( !window_isFlag( w, WINDOW_NOBORDER ) )
1546
1547 /* Iterate over widgets. */
1548 for ( Widget *wgt = w->widgets; wgt != NULL; wgt = wgt->next ) {
1549 if ( wgt->render == NULL )
1550 continue;
1551 if ( wgt_isFlag( wgt, WGT_FLAG_KILL ) )
1552 continue;
1553
1554 /* Only render non-dynamics. */
1555 if ( !wgt_isFlag( wgt, WGT_FLAG_DYNAMIC ) || !top )
1556 wgt->render( wgt, w->x, w->y );
1557
1558 if ( wgt->id == w->focus ) {
1559 double wx = w->x + wgt->x - 2;
1560 double wy = w->y + wgt->y - 2;
1562 wx, wy, wgt->w + 4, wgt->h + 4, 0, 2,
1563 ( wgt->type == WIDGET_BUTTON ? &cGrey70 : &cGrey30 ), NULL );
1564 }
1565 }
1566}
1567
1571void window_renderDynamic( Window *w )
1572{
1573 /* Iterate over widgets. */
1574 for ( Widget *wgt = w->widgets; wgt != NULL; wgt = wgt->next ) {
1575 if ( wgt->render == NULL )
1576 continue;
1577 if ( wgt_isFlag( wgt, WGT_FLAG_KILL ) )
1578 continue;
1579 if ( wgt_isFlag( wgt, WGT_FLAG_DYNAMIC ) ||
1580 window_isFlag( w, WINDOW_DYNAMIC ) )
1581 wgt->render( wgt, w->x, w->y );
1582 if ( wgt->renderDynamic != NULL )
1583 wgt->renderDynamic( wgt, w->x, w->y );
1584 }
1585}
1586
1592void window_renderOverlay( Window *w )
1593{
1594 /* Draw overlays. */
1595 for ( Widget *wgt = w->widgets; wgt != NULL; wgt = wgt->next )
1596 if ( ( wgt->renderOverlay != NULL ) && !wgt_isFlag( wgt, WGT_FLAG_KILL ) )
1597 wgt->renderOverlay( wgt, w->x, w->y );
1598}
1599
1609void toolkit_drawScrollbar( int x, int y, int w, int h, double pos )
1610{
1611 double sy;
1612
1613 /* scrollbar background */
1614 toolkit_drawRect( x, y, w, h, &cGrey10, NULL );
1615
1616 /* Bar itself. */
1617 sy = y + ( h - 30. ) * ( 1. - pos );
1618 toolkit_drawRect( x, sy, w, 30., toolkit_colLight, NULL );
1619 toolkit_drawOutline( x + 1, sy, w - 2, 30., 0., toolkit_colDark, NULL );
1620}
1621
1625void toolkit_render( double dt )
1626{
1627 (void)dt;
1628 Window *top = toolkit_getActiveWindow();
1629
1630 NTracingZone( _ctx, 1 );
1631
1632 if ( toolkit_needsRender ) {
1633 GLuint current_fbo = gl_screen.current_fbo;
1634 gl_screen.current_fbo = gl_screen.fbo[3];
1636
1637 glBindFramebuffer( GL_FRAMEBUFFER, gl_screen.current_fbo );
1638 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
1639
1640 /* Render base. */
1641 for ( Window *w = windows; w != NULL; w = w->next ) {
1642 if ( window_isFlag( w, WINDOW_NORENDER | WINDOW_KILL ) )
1643 continue;
1644 if ( ( w == top ) && window_isFlag( w, WINDOW_DYNAMIC ) )
1645 continue;
1646
1647 /* The actual rendering. */
1648 window_render( w, w == top );
1649 }
1650
1651 gl_screen.current_fbo = current_fbo;
1652 glBindFramebuffer( GL_FRAMEBUFFER, gl_screen.current_fbo );
1653 }
1654
1655 /* We can just rendered stored FBO onto the screen. */
1656 const mat4 ortho = mat4_ortho( 0., 1., 0., 1., 1., -1. );
1657 const mat4 I = mat4_identity();
1658 gl_renderTextureRawH( gl_screen.fbo_tex[3], &ortho, &I, &cWhite );
1659
1660 /* We render only the active window dynamically, otherwise we wouldn't be
1661 * able to respect the order. However, since the dynamic stuff is also
1662 * rendered to the framebuffer below, it shouldn't be too bad. */
1663 if ( ( top != NULL ) &&
1664 !window_isFlag( top, WINDOW_NORENDER | WINDOW_KILL ) ) {
1665 window_renderDynamic( top );
1666 window_renderOverlay( top );
1667 }
1668
1669 NTracingZoneEnd( _ctx );
1670}
1671
1676{
1678}
1679
1686int toolkit_input( SDL_Event *event )
1687{
1688 /* Get window that can be focused. */
1689 Window *wdw = toolkit_getActiveWindow();
1690 if ( wdw == NULL )
1691 return 0;
1692
1693 /* Pass event to window. */
1694 return toolkit_inputWindow( wdw, event, 1 );
1695}
1696
1700int toolkit_inputWindow( Window *wdw, SDL_Event *event, int purge )
1701{
1702 int ret;
1703
1704 /* See if widget needs event. */
1705 for ( Widget *wgt = wdw->widgets; wgt != NULL; wgt = wgt->next ) {
1706 if ( !wgt_isFlag( wgt, WGT_FLAG_RAWINPUT ) )
1707 continue;
1708 if ( wgt->rawevent == NULL )
1709 continue;
1710 ret = wgt->rawevent( wgt, event );
1711 if ( ret != 0 ) {
1713 return ret;
1714 }
1715 }
1716
1717 /* Event handler. */
1718 if ( wdw->eventevent != NULL ) {
1719 ret = wdw->eventevent( wdw->id, event );
1720 if ( ret != 0 ) {
1722 return ret;
1723 }
1724 }
1725
1726 /* Hack in case window got destroyed in eventevent. */
1727 ret = 0;
1728 if ( !window_isFlag( wdw, WINDOW_KILL ) ) {
1729 /* Pass it on. */
1730 switch ( event->type ) {
1731 case SDL_MOUSEMOTION:
1732 case SDL_MOUSEBUTTONDOWN:
1733 case SDL_MOUSEBUTTONUP:
1734 case SDL_MOUSEWHEEL:
1735 ret |= toolkit_mouseEvent( wdw, event );
1736 break;
1737
1738 case SDL_KEYDOWN:
1739 case SDL_KEYUP:
1740 ret |= toolkit_keyEvent( wdw, event );
1741 break;
1742
1743 case SDL_TEXTINPUT:
1744 ret |= toolkit_textEvent( wdw, event );
1745 break;
1746 case SDL_TEXTEDITING:
1747 break;
1748 }
1749 }
1750 if ( ret )
1752
1753 /* Clean up the dead if needed. */
1754 if ( purge &&
1755 !dialogue_isOpen() ) { /* Hack, since dialogues use secondary loop. */
1756 if ( toolkit_delayCounter > 0 )
1758 else
1760 }
1761
1762 return ret; /* don't block input */
1763}
1764
1776Uint32 toolkit_inputTranslateCoords( const Window *w, SDL_Event *event, int *x,
1777 int *y, int *rx, int *ry )
1778{
1779 /* Extract the position as event. */
1780 if ( event->type == SDL_MOUSEMOTION ) {
1781 *x = event->motion.x;
1782 *y = event->motion.y;
1783 } else if ( ( event->type == SDL_MOUSEBUTTONDOWN ) ||
1784 ( event->type == SDL_MOUSEBUTTONUP ) ) {
1785 *x = event->button.x;
1786 *y = event->button.y;
1787 } else if ( event->type == SDL_MOUSEWHEEL )
1788 SDL_GetMouseState( x, y );
1789
1790 /* Translate offset. */
1791 gl_windowToScreenPos( x, y, *x, *y );
1792
1793 /* Transform to relative to window. */
1794 *x -= w->x;
1795 *y -= w->y;
1796
1797 /* Relative only matter if mouse motion. */
1798 if ( event->type == SDL_MOUSEMOTION ) {
1799 *ry = (double)event->motion.yrel * gl_screen.mxscale;
1800 *rx = (double)event->motion.xrel * gl_screen.myscale;
1801 } else {
1802 *ry = 0;
1803 *rx = 0;
1804 }
1805
1806 return event->type;
1807}
1808
1809static int toolkit_mouseEventSingle( Window *w, SDL_Event *event, Widget *wgt,
1810 int x, int y, int rx, int ry )
1811{
1812 int ret = 0;
1813 /* Custom widgets take it from here */
1814 if ( wgt->type == WIDGET_CUST ) {
1815 if ( wgt->dat.cst.mouse )
1816 ret = wgt->dat.cst.mouse( w->id, event, x - wgt->x, y - wgt->y, wgt->w,
1817 wgt->h, rx, ry, wgt->dat.cst.userdata );
1818 } else
1819 ret = toolkit_mouseEventWidget( w, wgt, event, x, y, rx, ry );
1820 return ret;
1821}
1822static int toolkit_mouseEventReverse( Window *w, SDL_Event *event, Widget *wgt,
1823 int x, int y, int rx, int ry )
1824{
1825 if ( wgt->next != NULL ) {
1826 int ret = toolkit_mouseEventReverse( w, event, wgt->next, x, y, rx, ry );
1827 if ( ret )
1828 return ret;
1829 }
1830
1831 return toolkit_mouseEventSingle( w, event, wgt, x, y, rx, ry );
1832}
1839static int toolkit_mouseEvent( Window *w, SDL_Event *event )
1840{
1841 int x, y, rx, ry;
1842
1843 /* Translate mouse coords. */
1844 toolkit_inputTranslateCoords( w, event, &x, &y, &rx, &ry );
1845
1846 /* Check each widget. */
1847 if ( w->widgets != NULL )
1848 return toolkit_mouseEventReverse( w, event, w->widgets, x, y, rx, ry );
1849 return 0;
1850}
1851
1863static int toolkit_mouseEventWidget( Window *w, Widget *wgt, SDL_Event *event,
1864 int x, int y, int rx, int ry )
1865{
1866 int ret, inbounds;
1867 Uint8 button;
1868
1869 /* Widget translations. */
1870 x -= wgt->x;
1871 y -= wgt->y;
1872
1873 /* Handle mouse event. */
1874 if ( event->type == SDL_MOUSEMOTION )
1875 button = event->motion.state;
1876 else
1877 button = event->button.button;
1878
1879 /* Check inbounds. */
1880 inbounds = !( ( x < 0 ) || ( x >= wgt->w ) || ( y < 0 ) || ( y >= wgt->h ) );
1881
1882 /* Regular widgets. */
1883 ret = 0;
1884 switch ( event->type ) {
1885 case SDL_MOUSEMOTION:
1886 /* Change the status of the widget if mouse isn't down. */
1887
1888 /* Not scrolling. */
1889 if ( wgt->status != WIDGET_STATUS_SCROLLING ) {
1890 if ( inbounds ) {
1891 if ( wgt->status != WIDGET_STATUS_MOUSEDOWN )
1892 widget_setStatus( wgt, WIDGET_STATUS_MOUSEOVER );
1893 } else
1894 widget_setStatus( wgt, WIDGET_STATUS_NORMAL );
1895 } else
1896 inbounds = 1; /* Scrolling is always inbounds. */
1897
1898 /* If always gets the event. */
1899 if ( wgt_isFlag( wgt, WGT_FLAG_ALWAYSMMOVE ) )
1900 inbounds = 1;
1901
1902 /* Try to give the event to the widget. */
1903 if ( inbounds && ( wgt->mmoveevent != NULL ) )
1904 ret |= ( *wgt->mmoveevent )( wgt, x, y, rx, ry );
1905
1906 break;
1907
1908 case SDL_MOUSEWHEEL:
1909 if ( !inbounds )
1910 break;
1911
1912 /* Try to give the event to the widget. */
1913 if ( wgt->mwheelevent != NULL )
1914 ret |= ( *wgt->mwheelevent )( wgt, event->wheel );
1915 if ( ret )
1917
1918 break;
1919
1920 case SDL_MOUSEBUTTONDOWN:
1921 if ( !inbounds )
1922 break;
1923
1924 /* Update the status. */
1925 if ( button == SDL_BUTTON_LEFT )
1926 widget_setStatus( wgt, WIDGET_STATUS_MOUSEDOWN );
1927
1928 if ( toolkit_isFocusable( wgt ) ) {
1929 toolkit_focusClear( w );
1930 toolkit_focusWidget( w, wgt );
1931 }
1932
1933 /* Try to give the event to the widget. */
1934 if ( wgt->mdoubleclickevent != NULL &&
1935 input_isDoubleClick( (void *)wgt ) )
1936 ret |= ( *wgt->mdoubleclickevent )( wgt, button, x, y );
1937 else if ( wgt->mclickevent != NULL )
1938 ret |= ( *wgt->mclickevent )( wgt, button, x, y );
1939 if ( ret ) {
1940 input_clicked( (void *)wgt );
1942 }
1943 break;
1944
1945 case SDL_MOUSEBUTTONUP:
1946 /* Since basically only buttons are handled here, we ignore
1947 * it all except the left mouse button. */
1948 if ( button != SDL_BUTTON_LEFT )
1949 break;
1950
1951 if ( wgt->status == WIDGET_STATUS_MOUSEDOWN ) {
1952 /* Soft-disabled buttons will run anyway. */
1953 if ( ( wgt->type == WIDGET_BUTTON ) &&
1954 ( ( wgt->dat.btn.disabled == 0 ) ||
1955 ( wgt->dat.btn.softdisable ) ) ) {
1956 if ( wgt->dat.btn.fptr == NULL )
1957 DEBUG( _( "Toolkit: Button '%s' of Window '%s' "
1958 "doesn't have a function trigger" ),
1959 wgt->name, w->displayname );
1960 else {
1961 ( *wgt->dat.btn.fptr )( w->id, wgt->name );
1962 ret = 1;
1964 }
1965 }
1966 }
1967
1968 /* Signal scroll done if necessary. */
1969 if ( ( wgt->status == WIDGET_STATUS_SCROLLING ) &&
1970 ( wgt->scrolldone != NULL ) )
1971 wgt->scrolldone( wgt );
1972
1973 /* Always goes normal unless is below mouse. */
1974 if ( inbounds )
1975 widget_setStatus( wgt, WIDGET_STATUS_MOUSEOVER );
1976 else
1977 widget_setStatus( wgt, WIDGET_STATUS_NORMAL );
1978
1979 break;
1980 }
1981
1982 return ret;
1983}
1984
1991static SDL_Keymod toolkit_mapMod( SDL_Keycode key )
1992{
1993 switch ( key ) {
1994 case SDLK_LCTRL:
1995 return KMOD_LCTRL;
1996 case SDLK_RCTRL:
1997 return KMOD_RCTRL;
1998 case SDLK_LALT:
1999 return KMOD_LALT;
2000 case SDLK_RALT:
2001 return KMOD_RALT;
2002 case SDLK_LSHIFT:
2003 return KMOD_LSHIFT;
2004 case SDLK_RSHIFT:
2005 return KMOD_RSHIFT;
2006 default:
2007 return 0;
2008 }
2009}
2010
2016static void toolkit_regKey( SDL_Keycode key )
2017{
2018 /* See if our key is in fact a modifier key, and if it is, convert it to a
2019 * mod. If it is indeed a mod, do not register a new key but add the modifier
2020 * to the mod mask instead.
2021 */
2022 SDL_Keymod mod = toolkit_mapMod( key );
2023 if ( mod )
2024 input_mod |= mod;
2025 /* Don't reset values on repeat keydowns. */
2026 else
2027 input_key = key;
2028}
2029
2035static void toolkit_unregKey( SDL_Keycode key )
2036{
2037 /* See if our key is in fact a modifier key, and if it is, convert it to a
2038 * mod. If it is indeed a mod, do not unregister the key but subtract the
2039 * modifier from the mod mask instead.
2040 */
2041 SDL_Keymod mod = toolkit_mapMod( key );
2042 if ( mod )
2043 input_mod &= ~mod;
2044 else
2046}
2047
2052{
2053 input_key = 0;
2054}
2055
2062static int toolkit_keyEvent( Window *wdw, SDL_Event *event )
2063{
2064 Widget *wgt;
2065 SDL_Keycode key;
2066 SDL_Keymod mod;
2067 int rep, ret;
2068
2069 /* Event info. */
2070 key = event->key.keysym.sym;
2071 mod = event->key.keysym.mod;
2072 rep = event->key.repeat;
2073
2074 /* Hack to simulate key repetition */
2075 if ( event->type == SDL_KEYDOWN )
2076 toolkit_regKey( key );
2077 else if ( event->type == SDL_KEYUP )
2078 toolkit_unregKey( key );
2079
2080 /* See if window is valid. */
2081 if ( wdw == NULL )
2082 return 0;
2083
2084 /* Get widget. */
2085 wgt = toolkit_getFocus( wdw );
2086
2087 /* We only want keydown from now on. */
2088 if ( event->type != SDL_KEYDOWN )
2089 return 0;
2090
2091 /* Trigger event function if exists. */
2092 if ( wgt != NULL ) {
2093 if ( wgt->keyevent != NULL ) {
2094 ret = wgt->keyevent( wgt, input_key, input_mod, rep );
2095 if ( ret != 0 )
2096 return ret;
2097 }
2098 }
2099
2100 if ( input_key != 0 && !rep ) {
2101 /* Handle button hotkeys. We don't want a held-down key to keep activating
2102 * buttons, so forbid "repeat". */
2103 for ( wgt = wdw->widgets; wgt != NULL; wgt = wgt->next ) {
2104 if ( ( wgt->type == WIDGET_BUTTON ) &&
2105 ( wgt->dat.btn.key == input_key ) && wgt->keyevent != NULL ) {
2106 ret = wgt->keyevent( wgt, SDLK_RETURN, input_mod, rep );
2107 if ( ret != 0 )
2108 return ret;
2109 }
2110 }
2111
2112 /* Handle other cases where event might be used by the window... and we
2113 * don't want key-repeat. */
2114 switch ( key ) {
2115 case SDLK_RETURN:
2116 case SDLK_KP_ENTER:
2117 if ( wdw->accept_fptr != NULL ) {
2118 wdw->accept_fptr( wdw->id, wdw->name );
2119 return 1;
2120 }
2121 break;
2122
2123 case SDLK_ESCAPE:
2124 if ( wdw->cancel_fptr != NULL ) {
2125 wdw->cancel_fptr( wdw->id, wdw->name );
2126 return 1;
2127 }
2128 break;
2129
2130 default:
2131 break;
2132 }
2133 }
2134
2135 /* Finally the stuff gets passed to the custom key handler if it's defined.
2136 */
2137 if ( wdw->keyevent != NULL ) {
2138 ret = ( *wdw->keyevent )( wdw->id, input_key, input_mod, rep );
2139 if ( ret != 0 )
2140 return ret;
2141 }
2142
2143 /* Placed here so it can be overriden in console for tab completion. */
2144 if ( key == SDLK_TAB ) {
2145 if ( mod & ( KMOD_LSHIFT | KMOD_RSHIFT ) )
2146 toolkit_prevFocus( wdw );
2147 else
2148 toolkit_nextFocus( wdw );
2149 return 1;
2150 }
2151
2152 return 0;
2153}
2154static int toolkit_textEvent( Window *wdw, SDL_Event *event )
2155{
2156 Widget *wgt;
2157
2158 /* See if window is valid. */
2159 if ( wdw == NULL )
2160 return 0;
2161
2162 /* Get widget. */
2163 wgt = toolkit_getFocus( wdw );
2164
2165 /* Trigger event function if exists. */
2166 if ( ( wgt != NULL ) && ( wgt->textevent != NULL ) ) {
2167 int ret = ( *wgt->textevent )( wgt, event->text.text );
2168 if ( ret != 0 )
2169 return ret;
2170 }
2171
2172 return 0;
2173}
2174
2178static void toolkit_purgeDead( void )
2179{
2180 Window *wdw, *wlast;
2181
2182 /* Must be windows. */
2183 if ( windows == NULL )
2184 return;
2185
2186 /* Destroy what is needed. */
2187 wlast = NULL;
2188 wdw = windows;
2189 while ( wdw != NULL ) {
2190 if ( window_isFlag( wdw, WINDOW_KILL ) ) {
2191 /* Save target. */
2192 Window *wkill = wdw;
2193 /* Clean up while still in list. */
2194 window_cleanup( wdw );
2195 /* Reattach linked list. */
2196 if ( wlast == NULL )
2197 windows = wdw->next;
2198 else
2199 wlast->next = wdw->next;
2200 wdw = wlast;
2201 /* Kill target. */
2202 wkill->next = NULL;
2203 window_remove( wkill );
2204 } else {
2205 Widget *wgtlast = NULL;
2206 Widget *wgt = wdw->widgets;
2207 while ( wgt != NULL ) {
2208 if ( wgt_isFlag( wgt, WGT_FLAG_KILL ) ) {
2209 /* Save target. */
2210 Widget *wgtkill = wgt;
2211 /* Reattach linked list. */
2212 if ( wgtlast == NULL )
2213 wdw->widgets = wgt->next;
2214 else
2215 wgtlast->next = wgt->next;
2216 wgt = wgtlast;
2217 /* Kill target. */
2218 wgtkill->next = NULL;
2219 widget_kill( wgtkill );
2220 }
2221 /* Save position. */
2222 wgtlast = wgt;
2223 if ( wgt == NULL )
2224 wgt = wdw->widgets;
2225 else
2226 wgt = wgt->next;
2227 }
2228 }
2229 /* Save position. */
2230 wlast = wdw;
2231 if ( wdw == NULL )
2232 wdw = windows;
2233 else
2234 wdw = wdw->next;
2235 }
2236}
2237
2241void toolkit_update( void )
2242{
2243 /* Clean up the dead if needed. */
2244 if ( !dialogue_isOpen() ) { /* Hack, since dialogues use secondary loop. */
2245 if ( toolkit_delayCounter > 0 )
2247 else
2249 }
2250
2251 /* Killed all the windows. */
2252 if ( !toolkit_isOpen() ) {
2253
2255 if ( paused && !player_paused )
2256 unpause_game();
2257 }
2258}
2259
2266static void toolkit_expose( Window *wdw, int expose )
2267{
2268 if ( expose == wdw->exposed )
2269 return;
2270 else
2271 wdw->exposed = expose;
2272
2273 if ( expose )
2274 toolkit_focusSanitize( wdw );
2275 else
2276 toolkit_focusClear( wdw );
2277
2278 if ( wdw->focus != -1 )
2279 return;
2280
2281 /* Notify widgets (for tabbed children, etc.) */
2282 for ( Widget *wgt = wdw->widgets; wgt != NULL; wgt = wgt->next )
2283 if ( wgt->exposeevent != NULL )
2284 wgt->exposeevent( wgt, expose );
2285}
2286
2290void toolkit_focusClear( Window *wdw )
2291{
2292 if ( wdw->focus == -1 )
2293 return;
2294
2295 for ( Widget *wgt = wdw->widgets; wgt != NULL; wgt = wgt->next )
2296 toolkit_defocusWidget( wdw, wgt );
2297}
2298
2304void toolkit_focusSanitize( Window *wdw )
2305{
2306 int focus = wdw->focus;
2307
2308 /* Clear focus. */
2309 toolkit_focusClear( wdw );
2310
2311 /* No focus is always safe. */
2312 if ( focus == -1 )
2313 return;
2314
2315 /* Check focused widget. */
2316 for ( Widget *wgt = wdw->widgets; wgt != NULL; wgt = wgt->next ) {
2317 if ( focus == wgt->id ) {
2318 /* Not focusable. */
2319 if ( !toolkit_isFocusable( wgt ) )
2320 toolkit_nextFocus( wdw ); /* Get first focus. */
2321 else
2322 toolkit_focusWidget( wdw, wgt );
2323
2324 return;
2325 }
2326 }
2327}
2328
2332void toolkit_nextFocus( Window *wdw )
2333{
2334 int next;
2335
2336 /* Clear focus. */
2337 toolkit_focusClear( wdw );
2338
2339 /* See what to focus. */
2340 next = ( wdw->focus == -1 );
2341 for ( Widget *wgt = wdw->widgets; wgt != NULL; wgt = wgt->next ) {
2342 if ( !toolkit_isFocusable( wgt ) )
2343 continue;
2344
2345 if ( next ) {
2346 toolkit_focusWidget( wdw, wgt );
2347 return;
2348 } else if ( wdw->focus == wgt->id ) {
2349 next = 1;
2350 }
2351 }
2352
2353 /* Focus nothing. */
2354 wdw->focus = -1;
2356 return;
2357}
2358
2362void toolkit_prevFocus( Window *wdw )
2363{
2364 Widget *prev;
2365 int focus = wdw->focus;
2366
2367 /* Clear focus. */
2368 toolkit_focusClear( wdw );
2369
2370 /* See what to focus. */
2371 prev = NULL;
2372 for ( Widget *wgt = wdw->widgets; wgt != NULL; wgt = wgt->next ) {
2373 if ( !toolkit_isFocusable( wgt ) )
2374 continue;
2375
2376 /* See if we found the current one. */
2377 if ( focus == wgt->id ) {
2378 if ( prev != NULL )
2379 toolkit_focusWidget( wdw, prev );
2380 return;
2381 }
2382
2383 /* Store last focusable widget. */
2384 prev = wgt;
2385 }
2386
2387 /* Focus nothing. */
2388 if ( prev != NULL )
2389 toolkit_focusWidget( wdw, prev );
2390
2391 return;
2392}
2393
2398void toolkit_focusWidget( Window *wdw, Widget *wgt )
2399{
2400 if ( !toolkit_isFocusable( wgt ) || wgt_isFlag( wgt, WGT_FLAG_FOCUSED ) )
2401 return;
2402
2403 wdw->focus = wgt->id;
2404 wgt_setFlag( wgt, WGT_FLAG_FOCUSED );
2405 if ( wgt->focusGain != NULL )
2406 wgt->focusGain( wgt );
2407
2409}
2410
2415void toolkit_defocusWidget( Window *wdw, Widget *wgt )
2416{
2417 if ( wdw->focus != wgt->id || !wgt_isFlag( wgt, WGT_FLAG_FOCUSED ) )
2418 return;
2419
2420 wdw->focus = -1;
2421 wgt_rmFlag( wgt, WGT_FLAG_FOCUSED );
2422 if ( wgt->focusLose != NULL )
2423 wgt->focusLose( wgt );
2424
2426}
2427
2434static int toolkit_isFocusable( const Widget *wgt )
2435{
2436 if ( wgt == NULL )
2437 return 0;
2438
2439 return wgt_isFlag( wgt, WGT_FLAG_CANFOCUS );
2440}
2441
2448{
2449 /* Get window that can be focused. */
2450 Window *wlast = NULL;
2451 for ( Window *wdw = windows; wdw != NULL; wdw = wdw->next )
2452 if ( !window_isFlag( wdw, WINDOW_NOFOCUS ) &&
2453 !window_isFlag( wdw, WINDOW_KILL ) )
2454 wlast = wdw;
2455 return wlast;
2456}
2457
2464Widget *toolkit_getFocus( Window *wdw )
2465{
2466 /* No focus. */
2467 if ( wdw->focus == -1 )
2468 return NULL;
2469
2470 /* Find focus. */
2471 for ( Widget *wgt = wdw->widgets; wgt != NULL; wgt = wgt->next )
2472 if ( wdw->focus == wgt->id )
2473 return wgt;
2474
2475 /* Not found. */
2476 toolkit_focusClear( wdw );
2477 wdw->focus = -1;
2478 return NULL;
2479}
2480
2488void window_setFocus( unsigned int wid, const char *wgtname )
2489{
2490 Window *wdw;
2491 Widget *wgt;
2492
2493 /* Get window. */
2494 wdw = window_wget( wid );
2495 if ( wdw == NULL )
2496 return;
2497
2498 toolkit_focusClear( wdw );
2499
2500 /* Get widget. */
2501 wgt = wgtname == NULL ? NULL : window_getwgt( wid, wgtname );
2502 if ( wgt == NULL )
2503 return;
2504
2505 toolkit_focusWidget( wdw, wgt );
2506}
2507
2514char *window_getFocus( unsigned int wid )
2515{
2516 /* Get window. */
2517 Window *wdw = window_wget( wid );
2518 if ( wdw == NULL )
2519 return NULL;
2520
2521 /* Find focused widget. */
2522 for ( Widget *wgt = wdw->widgets; wgt != NULL; wgt = wgt->next )
2523 if ( wgt->id == wdw->focus )
2524 return strdup( wgt->name );
2525
2526 return NULL;
2527}
2528
2534void window_raise( unsigned int wid )
2535{
2536 Window *wdw, *wtmp, *wprev, *wlast;
2537
2538 wdw = window_wget( wid );
2539
2540 /* Not found, or already top of the stack. */
2541 if ( wdw == NULL || wdw->next == NULL )
2542 return;
2543
2544 wprev = NULL;
2545 wlast = NULL;
2546
2547 for ( wtmp = windows; wtmp != NULL; wtmp = wtmp->next )
2548 if ( wtmp->next == wdw )
2549 wprev = wtmp;
2550 else if ( wtmp->next == NULL )
2551 wlast = wtmp;
2552
2553 if ( wprev != NULL )
2554 wprev->next = wdw->next; /* wdw-1 links to wdw+1 */
2555
2556 if ( wlast != NULL )
2557 wlast->next = wdw; /* last links to wdw */
2558
2559 wdw->next = NULL; /* wdw becomes new last window */
2560
2561 wtmp = toolkit_getActiveWindow();
2562
2563 /* No active window, or window is the same. */
2564 if ( wtmp == NULL || wtmp == wdw )
2565 return;
2566
2567 toolkit_expose( wtmp, 0 ); /* wtmp is hidden */
2568 toolkit_expose( wdw, 1 ); /* wdw is visible */
2570}
2571
2577void window_lower( unsigned int wid )
2578{
2579 Window *wdw, *wtmp, *wprev;
2580
2581 wdw = window_wget( wid );
2582
2583 /* Not found, or already bottom of the stack. */
2584 if ( wdw == NULL || wdw == windows )
2585 return;
2586
2587 wprev = NULL;
2588 for ( wtmp = windows; wtmp != NULL; wtmp = wtmp->next )
2589 if ( wtmp->next == wdw )
2590 wprev = wtmp;
2591
2592 if ( wprev != NULL )
2593 wprev->next = wdw->next; /* wdw-1 links to wdw+1 */
2594
2595 wdw->next = windows; /* wdw links to first window */
2596 windows = wdw; /* wdw becomes new first window */
2597
2598 wtmp = toolkit_getActiveWindow();
2599
2600 /* No active window, or window is the same. */
2601 if ( wtmp == NULL || wtmp == wdw )
2602 return;
2603
2604 toolkit_expose( wtmp, 1 ); /* wtmp is visible */
2605 toolkit_expose( wdw, 0 ); /* wdw is hidden */
2607}
2608
2612void toolkit_resize( void )
2613{
2614 for ( Window *w = windows; w != NULL; w = w->next ) {
2615 int xdiff, ydiff;
2616
2617 /* Fullscreen windows must always be full size, though their widgets
2618 * don't auto-scale. */
2619 if ( window_isFlag( w, WINDOW_FULLSCREEN ) ) {
2620 w->w = gl_screen.nw;
2621 w->h = gl_screen.nh;
2622 continue;
2623 }
2624
2625 /* Skip if position is fixed. */
2626 if ( w->xrel == -1. && w->yrel == -1. )
2627 continue;
2628
2629 xdiff = 0.;
2630 ydiff = 0.;
2631
2632 if ( w->xrel != -1. ) {
2633 int xorig = w->x;
2634 w->x = ( gl_screen.nw - w->w ) * w->xrel;
2635 xdiff = w->x - xorig;
2636 }
2637
2638 if ( w->yrel != -1. ) {
2639 int yorig = w->y;
2640 w->y = ( gl_screen.nh - w->h ) * w->yrel;
2641 ydiff = w->y - yorig;
2642 }
2643
2644 /* Tabwin children aren't in the stack and must be manually updated. */
2645 for ( Widget *wgt = w->widgets; wgt != NULL; wgt = wgt->next ) {
2646 if ( wgt->type != WIDGET_TABBEDWINDOW )
2647 continue;
2648
2649 for ( int i = 0; i < wgt->dat.tab.ntabs; i++ ) {
2650 Window *wtmp = window_wget( wgt->dat.tab.windows[i] );
2651 wtmp->x += xdiff;
2652 wtmp->y += ydiff;
2653 }
2654 }
2655 }
2657}
2658
2664int toolkit_init( void )
2665{
2666 GLsizei size;
2667
2668 /* Create the VBO. */
2669 toolkit_vboColourOffset = sizeof( GLshort ) * 2 * 31;
2670 size = ( sizeof( GLshort ) * 2 + sizeof( GLfloat ) * 4 ) * 31;
2671 toolkit_vbo = gl_vboCreateStream( size, NULL );
2672
2673 /* Disable the cursor. */
2675
2676 return 0;
2677}
2678
2682void toolkit_exit( void )
2683{
2684 /* Destroy the windows. */
2685 while ( windows != NULL ) {
2686 Window *wdw = windows;
2687 windows = windows->next;
2688 window_cleanup( wdw );
2689 window_remove( wdw );
2690 }
2691
2692 /* Free the VBO. */
2694 toolkit_vbo = NULL;
2695}
int dialogue_isOpen(void)
Checks to see if a dialogue is open.
Definition dialogue.c:96
int gl_printHeightRaw(const glFont *ft_font, const int width, const char *text)
Gets the height of a non-formatted string.
Definition font.c:1050
glFont gl_smallFont
Definition font.c:159
int gl_printWidthRaw(const glFont *ft_font, const char *text)
Gets the width that it would take to print some text.
Definition font.c:984
glFont gl_defFont
Definition font.c:158
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:821
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:895
int input_isDoubleClick(const void *clicked)
Checks whether a clicked item is the same as the last-clicked.
Definition input.c:1789
void input_mouseShow(void)
Shows the mouse.
Definition input.c:453
void input_clicked(const void *clicked)
Sets the last-clicked item, for double-click detection.
Definition input.c:1776
void input_mouseHide(void)
Hides the mouse.
Definition input.c:462
mat4 mat4_identity(void)
Creates an identity matrix.
Definition mat4.c:335
mat4 mat4_ortho(double left, double right, double bottom, double top, double nearVal, double farVal)
Creates an orthographic projection matrix.
Definition mat4.c:347
Header file with generic functions and naev-specifics.
#define MIN(x, y)
Definition naev.h:39
void gl_defViewport(void)
Resets viewport to default.
Definition opengl.c:754
void gl_windowToScreenPos(int *sx, int *sy, int wx, int wy)
Translates the window position to screen position.
Definition opengl.c:762
glInfo gl_screen
Definition opengl.c:47
void gl_renderTextureRawH(GLuint texture, const mat4 *projection, const mat4 *tex_mat, const glColour *c)
Texture blitting backend.
void gl_vboDestroy(gl_vbo *vbo)
Destroys a VBO.
Definition opengl_vbo.c:244
gl_vbo * gl_vboCreateStream(GLsizei size, const void *data)
Creates a stream vbo.
Definition opengl_vbo.c:143
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:224
void gl_vboSubData(gl_vbo *vbo, GLint offset, GLsizei size, const void *data)
Loads some data into the VBO.
Definition opengl_vbo.c:128
void pause_game(void)
Pauses the game.
Definition pause.c:25
int player_paused
Definition pause.c:19
int paused
Definition pause.c:18
void unpause_game(void)
Unpauses the game.
Definition pause.c:43
static const double c[]
Definition rng.c:256
Definition mat4.h:12
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:706
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:688
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:2415
void window_setOnFocus(unsigned int wid, void(*focus)(unsigned int))
Sets the focus function of the window.
Definition toolkit.c:889
void window_renderDynamic(Window *w)
Renders the dynamic components of a window.
Definition toolkit.c:1571
static GLsizei toolkit_vboColourOffset
Definition toolkit.c:66
void toolkit_resize(void)
Repositions windows and their children if resolution changes.
Definition toolkit.c:2612
void toolkit_update(void)
Updates the toolkit input for repeating keys.
Definition toolkit.c:2241
void window_dimWidget(unsigned int wid, const char *name, int *w, int *h)
Gets the dimensions of a widget.
Definition toolkit.c:415
void toolkit_exit(void)
Exits the toolkit.
Definition toolkit.c:2682
void window_setDynamic(unsigned int wid, int dynamic)
Sets a window as dynamic, so that it is drawn every frame completely.
Definition toolkit.c:643
unsigned int window_getParent(unsigned int wid)
Gets the window's parent.
Definition toolkit.c:804
void toolkit_drawScrollbar(int x, int y, int w, int h, double pos)
Draws a scrollbar.
Definition toolkit.c:1609
static SDL_Keymod toolkit_mapMod(SDL_Keycode key)
Maps modifier keysyms (ctrl, alt, shift) to SDL_Keymods.
Definition toolkit.c:1991
void window_setFocus(unsigned int wid, const char *wgtname)
Sets the focused widget in a window.
Definition toolkit.c:2488
void window_render(Window *w, int top)
Renders a window.
Definition toolkit.c:1538
static unsigned int genwid
Definition toolkit.c:26
const glColour * toolkit_col
Definition toolkit.c:50
static void toolkit_purgeDead(void)
Purges the dead windows.
Definition toolkit.c:2178
void window_setAccept(unsigned int wid, void(*accept)(unsigned int, const char *))
Sets the default accept function of the window.
Definition toolkit.c:846
void window_dimWindow(unsigned int wid, int *w, int *h)
Gets the dimensions of a window.
Definition toolkit.c:370
int toolkit_isOpen(void)
Checks to see if the toolkit is open.
Definition toolkit.c:93
void window_move(unsigned int wid, int x, int y)
Moves a window to the specified coordinates.
Definition toolkit.c:176
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:1839
Window * window_wgetW(unsigned int wid)
Gets a Window by ID, without warning.
Definition toolkit.c:316
int window_existsID(unsigned int wid)
Checks to see if a window with a certain ID exists.
Definition toolkit.c:608
static void window_renderBorder(const Window *w)
Renders a window border.
Definition toolkit.c:1502
static void widget_kill(Widget *wgt)
Destroy a widget really.
Definition toolkit.c:1218
static void toolkit_unregKey(SDL_Keycode key)
Unregisters a key.
Definition toolkit.c:2035
void toolkit_drawAltText(int bx, int by, const char *alt)
Draws an alt text.
Definition toolkit.c:1460
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:1016
Window * window_wget(unsigned int wid)
Gets a Window by ID.
Definition toolkit.c:298
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:1863
void window_onClose(unsigned int wid, void(*fptr)(unsigned int, const char *))
Sets the default close function of the window.
Definition toolkit.c:824
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:517
void toolkit_clearKey(void)
Clears the registered keys.
Definition toolkit.c:2051
void window_raise(unsigned int wid)
Raises a window (causes all other windows to appear below it).
Definition toolkit.c:2534
void toolkit_drawRect(int x, int y, int w, int h, const glColour *c, const glColour *lc)
Draws a rectangle.
Definition toolkit.c:1370
static void window_remove(Window *wdw)
Frees up a window. Make sure to clean up the window first.
Definition toolkit.c:1118
static SDL_Keycode input_key
Definition toolkit.c:43
static int toolkit_delayCounter
Definition toolkit.c:30
void toolkit_focusSanitize(Window *wdw)
Sanitizes the focus of a window.
Definition toolkit.c:2304
void window_moveWidget(unsigned int wid, const char *name, int x, int y)
Moves a widget.
Definition toolkit.c:463
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:223
Widget * window_getwgt(unsigned int wid, const char *name)
Gets a widget from window id and widgetname.
Definition toolkit.c:345
void window_resize(unsigned int wid, int w, int h)
Resizes the window.
Definition toolkit.c:193
void toolkit_drawTriangle(int x1, int y1, int x2, int y2, int x3, int y3, const glColour *c)
Draws a rectangle.
Definition toolkit.c:1420
void toolkit_delay(void)
Delays the toolkit purge by an iteration, useful for dialogues.
Definition toolkit.c:105
static void window_cleanup(Window *wdw)
Cleans up the window, should be done before window_remove.
Definition toolkit.c:1104
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:2398
void window_posWidget(unsigned int wid, const char *name, int *x, int *y)
Gets a widget's position.
Definition toolkit.c:441
static void toolkit_expose(Window *wdw, int expose)
Exposes or hides a window and notifies its widgets.
Definition toolkit.c:2266
Uint32 toolkit_inputTranslateCoords(const Window *w, SDL_Event *event, int *x, int *y, int *rx, int *ry)
Translates the mouse coordinates.
Definition toolkit.c:1776
int toolkit_init(void)
Initializes the toolkit.
Definition toolkit.c:2664
Window * window_wgetNameW(const char *name)
Gets a Window by name, without warning.
Definition toolkit.c:330
void window_destroyWidget(unsigned int wid, const char *wgtname)
Destroys a widget in a window.
Definition toolkit.c:1167
static int toolkit_isFocusable(const Widget *wgt)
Checks to see if a widget is focusable.
Definition toolkit.c:2434
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:561
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:140
void toolkit_render(double dt)
Renders the windows.
Definition toolkit.c:1625
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:1239
void toolkit_prevFocus(Window *wdw)
Focus previous widget.
Definition toolkit.c:2362
int window_isTop(unsigned int wid)
Checks to see if a window is at the top.
Definition toolkit.c:544
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:961
const glColour * toolkit_colDark
Definition toolkit.c:51
unsigned int window_get(const char *wdwname)
Gets the ID of a window.
Definition toolkit.c:662
void window_lower(unsigned int wid)
Lowers a window (causes all other windows to appear above it).
Definition toolkit.c:2577
void window_setBorder(unsigned int wid, int enable)
Sets or removes the border of a window.
Definition toolkit.c:942
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:1318
void toolkit_nextFocus(Window *wdw)
Focus next widget.
Definition toolkit.c:2332
int toolkit_input(SDL_Event *event)
Toolkit input handled here.
Definition toolkit.c:1686
void toolkit_rerender(void)
Marks the toolkit for needing a full rerender.
Definition toolkit.c:1675
void window_posWindow(unsigned int wid, int *x, int *y)
Gets the dimensions of a window.
Definition toolkit.c:392
void * window_getData(unsigned int wid)
Gets the custom data of a window.
Definition toolkit.c:923
void toolkit_setPos(const Window *wdw, Widget *wgt, int x, int y)
Sets the internal widget position.
Definition toolkit.c:118
void window_kill(Window *wdw)
Kills the window (and children).
Definition toolkit.c:1088
void window_setParent(unsigned int wid, unsigned int parent)
Sets a window as a window's parent.
Definition toolkit.c:787
void window_setData(unsigned int wid, void *data)
Sets custom data for a window.
Definition toolkit.c:906
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:490
int toolkit_inputWindow(Window *wdw, SDL_Event *event, int purge)
Toolkit window input is handled here.
Definition toolkit.c:1700
void toolkit_focusClear(Window *wdw)
Clears the window focus.
Definition toolkit.c:2290
int window_exists(const char *wdwname)
Checks to see if a window exists.
Definition toolkit.c:591
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:1144
static Window * windows
Definition toolkit.c:37
Widget * toolkit_getFocus(Window *wdw)
Gets the focused widget in a window.
Definition toolkit.c:2464
void widget_cleanup(Widget *widget)
Destroys a widget.
Definition toolkit.c:996
int window_setDisplayname(unsigned int wid, const char *displayname)
Sets the displayname of a window.
Definition toolkit.c:625
static void toolkit_regKey(SDL_Keycode key)
Registers a key as down (for key repetition).
Definition toolkit.c:2016
static int toolkit_keyEvent(Window *wdw, SDL_Event *event)
Handles keyboard events.
Definition toolkit.c:2062
void window_close(unsigned int wid, const char *str)
Helper function to automatically close the window calling it.
Definition toolkit.c:1028
Window * toolkit_getActiveWindow(void)
Gets the active window in the toolkit.
Definition toolkit.c:2447
void window_destroy(unsigned int wid)
Kills the window.
Definition toolkit.c:1039
char * window_getFocus(unsigned int wid)
Gets the focused widget in a window (does strdup!!).
Definition toolkit.c:2514
void window_handleEvents(unsigned int wid, int(*eventhandler)(unsigned int, SDL_Event *))
Sets the event handler for the window.
Definition toolkit.c:979
void window_renderOverlay(Window *w)
Renders the window overlays.
Definition toolkit.c:1592
static int toolkit_needsRender
Definition toolkit.c:28
const glColour * tab_active
Definition toolkit.c:56