=== Overview ===
[xuni.git] / src / loop.c
blob1e3d3b8e6f543840addc6f2fc5e4deba42dffd72
1 /*! \file loop.c
3 */
5 #include <stdlib.h>
7 #include "SDL_framerate.h"
9 #include "graphics.h"
10 #include "gui.h"
11 #include "loop.h"
12 #include "memory.h"
13 #include "resource/resource.h"
15 #include "widget/dump.h"
16 #include "widget/widgets.h"
17 #include "widget/listbox.h"
19 static void call_event_funcs(struct xuni_t *xuni, SDL_Event *event,
20 struct widget_t *widget, panel_type_t *mode);
21 static int call_perform_click_func(struct xuni_t *xuni,
22 struct panel_data_t *panel, struct widget_t *widget, panel_type_t *mode);
23 static void call_free_funcs(struct widget_t *widget, struct xuni_t *xuni);
25 static SDL_Cursor *sdl_cursor_from_xpm(const char *image[]);
26 static void set_widget_cursor(struct xuni_t *xuni);
28 static void set_loop_caption(panel_type_t mode, struct xuni_t *xuni);
29 static int get_event(int frameupdate, SDL_Event *event);
30 static int process_event(SDL_Event *event, panel_type_t *mode,
31 struct xuni_t *xuni);
32 static void scroll_listbox(struct xuni_t *xuni, int dir);
33 static int set_loop_widget_sel(panel_type_t mode, int xp, int yp,
34 int click, struct xuni_t *xuni);
35 static int find_widget_accelerator(struct xuni_accelerator_t *accel,
36 SDL_keysym *key, struct xuni_t *xuni, panel_type_t *mode);
37 static int check_sdl_key_mod(SDLMod mod, SDLMod now);
38 static int event_mouse_button_up(int xp, int yp, panel_type_t *mode,
39 struct xuni_t *xuni);
40 static int perform_loop_click(struct xuni_t *xuni, panel_type_t *mode,
41 struct widget_t *widget);
42 static int event_key_down(struct xuni_t *xuni, SDL_keysym *keysym,
43 panel_type_t *mode, int *handled);
45 void call_init_funcs(struct xuni_t *xuni, struct widget_t *widget,
46 struct resource_t *settings) {
48 size_t x;
50 if(!widget) return;
52 if(widget->type == WIDGET_PANEL && widget->p.panel->init_func) {
53 (*widget->p.panel->init_func)(widget->p.panel->data, xuni, widget,
54 settings);
57 if(widget->compose) {
58 for(x = 0; x < widget->compose->widgets; x ++) {
59 call_init_funcs(xuni, widget->compose->widget[x], settings);
64 static void call_event_funcs(struct xuni_t *xuni, SDL_Event *event,
65 struct widget_t *widget, panel_type_t *mode) {
67 size_t x;
69 if(!widget) return;
71 if(widget->type == WIDGET_PANEL && widget->p.panel->event_func) {
72 /* !!! return value ignored */
73 (*widget->p.panel->event_func)(widget->p.panel->data, xuni, mode,
74 event);
77 if(widget->compose) {
78 for(x = 0; x < widget->compose->widgets; x ++) {
79 call_event_funcs(xuni, event, widget->compose->widget[x], mode);
84 static int call_perform_click_func(struct xuni_t *xuni,
85 struct panel_data_t *panel, struct widget_t *widget, panel_type_t *mode) {
87 perform_widget_click(xuni, widget);
89 /*print_widget_backtrace(xuni->gui->sel.p.widget);*/
91 /* !!! quick fix to disallow clicking on a panel. Without this, for
92 example, clicking on the options graphics panel triggers the
93 fullscreen checkbox, as
94 PANEL_OPTIONS_GRAPHICS == WID_GRAPHICS_FULLSCREEN */
95 if(widget && panel->perform_click_func
96 && widget_nameid_access(xuni->gui->widget, *mode) != widget) {
98 return (*panel->perform_click_func)(widget, mode, panel->data, xuni);
101 return 0;
104 void call_deactivate_func(struct xuni_t *xuni, struct widget_t *widget) {
105 struct widget_t *base = widget;
107 while(base && base->type != WIDGET_PANEL) base = base->base;
109 if(base && base->p.panel->deactivate_func) {
110 (*base->p.panel->deactivate_func)
111 (base->p.panel->data, xuni, widget);
115 static void call_free_funcs(struct widget_t *widget, struct xuni_t *xuni) {
116 size_t x;
118 if(!widget) return;
120 if(widget->type == WIDGET_PANEL) {
121 if(widget->p.panel->free_func) {
122 (*widget->p.panel->free_func)(widget->p.panel->data, xuni);
125 /* this is handled by free_widget() */
126 /*xuni_memory_free(widget->p.panel->data);*/
129 if(widget->compose) {
130 for(x = 0; x < widget->compose->widgets; x ++) {
131 call_free_funcs(widget->compose->widget[x], xuni);
136 /*#define HIDE_COMBOBOX_POPUPS*/
138 int set_default_widget_sel(struct xuni_t *xuni, panel_type_t mode,
139 int xp, int yp, int click, void *vdata) {
141 #ifdef HIDE_COMBOBOX_POPUPS
142 struct widget_t *widget = xuni->gui->sel.p.widget;
143 #endif
144 int r;
146 r = set_widget_sel_repaint(&xuni->gui->sel, xp, yp, click,
147 widget_nameid_access(xuni->gui->widget, mode));
149 /*if(xuni->gui->sel.p.widget) {
150 printf("%s\n", xuni->gui->sel.p.widget->name);
153 #ifdef HIDE_COMBOBOX_POPUPS
154 /* Hide combobox popups that have become unselected. */
155 if(widget && widget != xuni->gui->sel.p.widget) {
156 struct widget_t *w = xuni->gui->sel.p.widget, *t;
158 /* See if any comboboxes that were previously selected still are. */
159 while(w) {
160 if(w->visibility & WIDGET_VISIBILITY_VISIBLE
161 && w->type == WIDGET_COMBOBOX) {
163 for(t = widget; t; t = t->base) {
164 if(t == w) break;
167 if(t) break;
170 w = w->base;
173 /* If no comboboxes were selected and remain selected, hide the popups
174 for all comboboxes that were selected.
176 if(!w) {
177 do {
178 if(widget->type == WIDGET_COMBOBOX) {
179 widget->compose->widget[WID_COMBOBOX_DROPDOWN]->visibility
180 &= ~WIDGET_VISIBILITY_VISIBLE;
183 widget = widget->base;
184 } while(widget);
187 #endif
189 return r;
192 void set_panel_callbacks(struct widget_t *widget, void *vdata,
193 int frameupdate, init_func_t init_func, start_func_t start_func,
194 event_func_t event_func, set_widget_sel_func_t set_widget_sel_func,
195 perform_click_func_t perform_click_func,
196 deactivate_func_t deactivate_func, paint_func_t paint_func,
197 free_func_t free_func) {
199 widget->p.panel->data = vdata;
200 widget->p.panel->frameupdate = frameupdate;
201 widget->p.panel->init_func = init_func;
202 widget->p.panel->start_func = start_func;
203 widget->p.panel->event_func = event_func;
204 widget->p.panel->set_widget_sel_func = set_widget_sel_func;
205 widget->p.panel->perform_click_func = perform_click_func;
206 widget->p.panel->deactivate_func = deactivate_func;
207 widget->p.panel->paint_func = paint_func;
208 widget->p.panel->free_func = free_func;
210 widget->p.panel->nameid = 0;
212 widget->p.panel->accel = 0;
215 void execute_callback(struct xuni_t *xuni, struct xuni_callback_t *callback) {
216 if(callback && callback->func) {
217 (*callback->func)(callback->vdata, xuni);
221 /*! The main xuni loop. Indirectly calls all panel event-handling functions,
222 including initialization functions, event handlers, repaint functions,
223 etc.
225 This function should only be called once, after everything has been loaded
226 and set up. It should only return when the program is exiting -- but it
227 will return, so don't neglect that freeing code.
229 \param xuni The xuni structure, with most of the data required to display
230 and manage a Graphical User Interface (GUI, of course).
231 \param always A callback function that is executed for every loop of the
232 xuni event loop. Note that this can be called considerably more
233 frequently than repaint functions.
234 \param mode The panel to initially display.
236 void main_loop(struct xuni_t *xuni, struct xuni_callback_t *always,
237 panel_type_t mode) {
239 panel_type_t pmode = (size_t)-1;
240 struct panel_data_t *panel
241 = widget_nameid_access(xuni->gui->widget, mode)->p.panel;
242 FPSmanager fpsm;
243 SDL_Event event;
244 int repaint = 1;
246 /*call_init_funcs(data, smode, font, theme, gui, settings);*/
248 SDL_initFramerate(&fpsm);
249 SDL_setFramerate(&fpsm, 30);
251 while(mode != (size_t)-1) {
252 execute_callback(xuni, always);
254 /*dump_widgets_need_repaint(xuni->gui->widget);*/
256 if(get_event(widget_nameid_access(xuni->gui->widget, mode)
257 ->p.panel->frameupdate, &event)) {
259 do {
260 repaint = process_event(&event, &mode, xuni) || repaint;
262 if(mode == (size_t)-1) break;
263 } while(SDL_PollEvent(&event));
265 if(mode == (size_t)-1) break;
268 if(pmode != mode) { /* !!! process_event() is called before the start_func */
269 panel = widget_nameid_access(xuni->gui->widget, mode)->p.panel;
270 set_loop_caption(mode, xuni); /* !!! also pass pmode */
272 pmode = mode;
274 repaint = 1;
277 /* !!! this needs to go in a hover callback function of sorts */
278 set_widget_cursor(xuni);
280 if(xuni->smode->focus) {
281 if(repaint || panel->frameupdate) {
282 if(panel->paint_func) {
283 (*panel->paint_func)
284 (panel->data, mode, xuni);
289 repaint = 0;
291 if(!xuni->smode->focus || panel->frameupdate) {
292 SDL_framerateDelay(&fpsm);
296 set_caption("Quitting . . .");
298 call_free_funcs(xuni->gui->widget, xuni);
301 /* An XPM image of a CURSOR_TEXT, used when the mouse is inside textboxes. */
302 static const char *text_cursor[] = {
303 /* width height num_colors chars_per_pixel */
304 " 16 16 3 1",
305 /* colors */
306 "X c #000000",
307 ". c #ffffff",
308 " c None",
309 /* pixels */
310 " XXXXX ",
311 " X.....X ",
312 " XX.XX ",
313 " X.X ",
314 " X.X ",
315 " X.X ",
316 " X.X ",
317 " X.X ",
318 " X.X ",
319 " X.X ",
320 " X.X ",
321 " X.X ",
322 " X.X ",
323 " XX.XX ",
324 " X.....X ",
325 " XXXXX ",
326 "7,7"
329 static SDL_Cursor *sdl_cursor_from_xpm(const char *image[]) {
330 int i, x, y;
331 Uint8 data[4*16] = {0};
332 Uint8 mask[4*16] = {0};
333 int hot_x, hot_y;
335 i = -1;
336 for(x = 4; x < 16 + 4; x ++) {
337 for(y = 0; y < 16; y ++) {
338 if(y % 8) {
339 data[i] <<= 1;
340 mask[i] <<= 1;
342 else i ++;
344 switch (image[x][y]) {
345 case 'X':
346 data[i] |= 0x01;
347 mask[i] |= 0x01;
348 break;
349 case '.':
350 mask[i] |= 0x01;
351 break;
352 case ' ':
353 break;
358 sscanf(image[x], "%d,%d", &hot_x, &hot_y);
360 return SDL_CreateCursor(data, mask, 16, 16, hot_x, hot_y);
363 static void set_widget_cursor(struct xuni_t *xuni) {
364 enum cursor_t now;
366 if(xuni->gui->sel.p.widget
367 && xuni->gui->sel.p.widget->type == WIDGET_TEXTBOX) {
369 now = CURSOR_TEXT;
371 else now = CURSOR_NORMAL;
373 if(xuni->theme->cursors.which != now) {
374 xuni->theme->cursors.which = now;
376 if(xuni->theme->cursors.which) {
377 if(!xuni->theme->cursors.text) {
378 xuni->theme->cursors.text = sdl_cursor_from_xpm(text_cursor);
379 /* save the normal cursor before it is overwritten */
380 xuni->theme->cursors.normal = SDL_GetCursor();
383 SDL_SetCursor(xuni->theme->cursors.text);
385 else {
386 if(!xuni->theme->cursors.normal) {
387 xuni->theme->cursors.normal = SDL_GetCursor();
390 SDL_SetCursor(xuni->theme->cursors.normal);
395 static void set_loop_caption(panel_type_t mode, struct xuni_t *xuni) {
396 struct panel_data_t *panel
397 = widget_nameid_access(xuni->gui->widget, mode)->p.panel;
398 int xp, yp;
400 show_cursor(1);
402 clear_gui(xuni, mode, 0);
404 /* !!! set all other panels to invisible */
405 widget_nameid_access(xuni->gui->widget, mode)->visibility
406 |= WIDGET_VISIBILITY_VISIBLE;
408 if(panel->start_func) {
409 (*panel->start_func)(panel->data, xuni);
412 SDL_GetMouseState(&xp, &yp);
414 set_loop_widget_sel(mode, xp, yp, xuni->gui->sel.clickin, xuni);
417 static int get_event(int frameupdate, SDL_Event *event) {
418 return frameupdate ? SDL_PollEvent(event) : SDL_WaitEvent(event);
421 /* !!! should probably get rid of handled */
422 static int process_event(SDL_Event *event, panel_type_t *mode,
423 struct xuni_t *xuni) {
425 struct panel_data_t *panel
426 = widget_nameid_access(xuni->gui->widget, *mode)->p.panel;
427 int repaint = 0, handled = 0;
429 switch(event->type) {
430 case SDL_MOUSEBUTTONDOWN:
431 if(event->button.button == SDL_BUTTON_WHEELUP) {
432 scroll_listbox(xuni, -1);
434 repaint = 1;
435 handled = 1;
437 else if(event->button.button == SDL_BUTTON_WHEELDOWN) {
438 scroll_listbox(xuni, 1);
440 repaint = 1;
441 handled = 1;
444 if(event->button.button != 1) break;
446 repaint = set_loop_widget_sel(*mode, event->button.x, event->button.y,
447 1, xuni);
449 if(repaint) handled = 1;
450 break;
451 case SDL_MOUSEBUTTONUP:
452 if(event->button.button != 1) break;
454 repaint = event_mouse_button_up(event->button.x, event->button.y,
455 mode, xuni);
457 if(repaint) handled = 1;
458 break;
459 case SDL_MOUSEMOTION:
460 repaint = set_loop_widget_sel(*mode, event->button.x, event->button.y,
461 xuni->gui->sel.clickin, xuni);
463 /*if(repaint) handled = 1;*/
464 break;
465 case SDL_VIDEORESIZE:
466 if(!resize_screen(xuni->smode, &event->resize)) {
467 widget_event(xuni, xuni->gui->widget, WIDGET_EVENT_RESCALE);
469 call_event_funcs(xuni, event, xuni->gui->widget, mode);
472 if(focus_changed(xuni->smode, SDL_APPACTIVE)) {
473 if(xuni->smode->focus) {
474 set_loop_caption(*mode, xuni);
476 else {
477 show_cursor(1);
481 handled = 1;
482 repaint = 1;
483 break;
484 case SDL_VIDEOEXPOSE:
485 repaint = 1;
486 handled = 1;
487 break;
488 case SDL_KEYDOWN:
489 repaint = event_key_down(xuni, &event->key.keysym, mode, &handled);
491 break;
492 case SDL_KEYUP:
493 break;
494 case SDL_ACTIVEEVENT:
495 if(focus_changed(xuni->smode, SDL_APPACTIVE | SDL_APPINPUTFOCUS)) {
496 if(xuni->smode->focus) {
497 /* !!! this is only for the cursor */
498 set_loop_caption(*mode, xuni);
499 repaint = 1;
501 else {
502 /* preserve any textbox data etc in the active widget */
503 clear_active(xuni, &xuni->gui->active, 1);
504 show_cursor(1);
508 handled = 1;
509 break;
510 default:
511 break;
514 if(!handled && panel->event_func) {
515 repaint |= (*panel->event_func)(panel->data, xuni, mode, event);
518 return repaint;
521 /* !!! bad hack */
522 static void scroll_listbox(struct xuni_t *xuni, int dir) {
523 int step = 5;
525 if(xuni->gui->sel.p.widget
526 && xuni->gui->sel.p.widget->type == WIDGET_LISTBOX) {
528 move_scrollbar(xuni, xuni->gui->sel.p.widget->compose->widget
529 [WID_LISTBOX_VSCROLL], step * dir);
531 widget_event(xuni, xuni->gui->sel.p.widget, WIDGET_EVENT_REPOSITION);
534 if(xuni->gui->sel.p.widget
535 && xuni->gui->sel.p.widget->type == WIDGET_SCROLLBAR) {
537 move_scrollbar(xuni, xuni->gui->sel.p.widget, step * dir);
539 widget_event(xuni, xuni->gui->sel.p.widget->base,
540 WIDGET_EVENT_REPOSITION);
543 if(xuni->gui->sel.p.widget && xuni->gui->sel.p.widget->base
544 && xuni->gui->sel.p.widget->base->type == WIDGET_SCROLLBAR) {
546 move_scrollbar(xuni, xuni->gui->sel.p.widget->base, step * dir);
548 widget_event(xuni, xuni->gui->sel.p.widget->base->base,
549 WIDGET_EVENT_REPOSITION);
553 static int set_loop_widget_sel(panel_type_t mode, int xp, int yp,
554 int click, struct xuni_t *xuni) {
556 struct panel_data_t *panel
557 = widget_nameid_access(xuni->gui->widget, mode)->p.panel;
559 if(!panel->set_widget_sel_func) return 0;
561 return (*panel->set_widget_sel_func)(xuni, mode, xp, yp, click,
562 panel->data);
565 /*! Determines whether any accelerator key combinations have been or are being
566 pressed, and, if so, handles the click event.
568 \param accel This panel's accelerator array. Searched for accelerator
569 combinations matching the current keyboard state.
570 \param key The current keyboard state. Compared with accelerator
571 combinations for the current panel for matches.
572 \param xuni The xuni structure. Used to get a struct widget_t pointer to
573 the current panel.
574 \param mode The currently active panel. Only passed so that
575 call_perform_click_func() may be called.
577 static int find_widget_accelerator(struct xuni_accelerator_t *accel,
578 SDL_keysym *key, struct xuni_t *xuni, panel_type_t *mode) {
580 size_t x;
581 SDL_keysym *akey;
583 if(!accel) return 0;
585 for(x = 0; x < accel->n; x ++) {
586 akey = &accel->key[x].key;
587 if(akey->sym && akey->sym == key->sym
588 && check_sdl_key_mod(akey->mod, key->mod)) {
590 call_perform_click_func(xuni,
591 widget_nameid_access(xuni->gui->widget, *mode)->p.panel,
592 accel->key[x].widget, mode);
594 return 1;
598 return 0;
601 /* !!! needs to be reworked to allow OR, AND, NOT, etc. */
602 static int check_sdl_key_mod(SDLMod mod, SDLMod now) {
603 if(mod != KMOD_NONE) {
604 if((mod & KMOD_CTRL) == KMOD_CTRL) {
605 if(now & KMOD_CTRL) mod &= ~KMOD_CTRL;
606 else return 0;
608 if((mod & KMOD_SHIFT) == KMOD_SHIFT) {
609 if(now & KMOD_SHIFT) mod &= ~KMOD_SHIFT;
610 else return 0;
612 if((mod & KMOD_ALT) == KMOD_ALT) {
613 if(now & KMOD_ALT) mod &= ~KMOD_ALT;
614 else return 0;
618 if(now != mod) return 0;
620 return 1;
623 static int event_mouse_button_up(int xp, int yp, panel_type_t *mode,
624 struct xuni_t *xuni) {
626 struct panel_data_t *panel
627 = widget_nameid_access(xuni->gui->widget, *mode)->p.panel;
628 int repaint = 0, realclick;
630 if(xuni->gui->sel.p.widget && xuni->gui->sel.clickin
631 && pos_in_rect(xp, yp, xuni->gui->sel.p.widget->pos)) {
633 /*xuni->gui->sel.clickin = 0;*/
634 realclick = !set_widget_sel(&xuni->gui->sel, xp, yp, 1,
635 widget_nameid_access(xuni->gui->widget, *mode));
637 if(realclick) {
638 /* !!! return value ignored: repaint is always set to 1 */
639 call_perform_click_func(xuni, panel, xuni->gui->sel.p.widget,
640 mode);
643 xuni->gui->sel.wasin = 1;
644 xuni->gui->sel.clickin = 0;
645 repaint = 1;
647 if(realclick) {
648 if(xuni->gui->sel.p.widget &&
649 widget_can_be_active(xuni->gui->sel.p.widget)) {
651 xuni->gui->active = xuni->gui->sel.p;
652 activate_widget(xuni->gui->active.widget, xuni, xp, yp);
653 enable_unicode(xuni->gui->active.widget);
655 else if(xuni->gui->active.widget) {
656 repaint = 1;
658 clear_active(xuni, &xuni->gui->active, 1);
661 if(*mode != (size_t)-1) {
662 set_loop_widget_sel(*mode, xp, yp, xuni->gui->sel.clickin,
663 xuni);
667 else {
668 repaint = set_loop_widget_sel(*mode, xp, yp, 0, xuni);
670 if(xuni->gui->active.widget &&
671 !pos_in_rect(xp, yp, xuni->gui->active.widget->pos)) {
673 repaint = 1;
675 clear_active(xuni, &xuni->gui->active, 1);
679 return repaint;
682 static int perform_loop_click(struct xuni_t *xuni, panel_type_t *mode,
683 struct widget_t *widget) {
685 struct panel_data_t *panel
686 = widget_nameid_access(xuni->gui->widget, *mode)->p.panel;
687 int repaint, xp = 0, yp = 0; /* !!! */
689 /* !!! return value ignored: repaint is always set to 1 */
690 call_perform_click_func(xuni, panel, widget, mode);
692 xuni->gui->sel.wasin = 1;
693 xuni->gui->sel.clickin = 0;
694 repaint = 1;
696 if(xuni->gui->sel.p.widget &&
697 widget_can_be_active(xuni->gui->sel.p.widget)) {
699 xuni->gui->active = xuni->gui->sel.p;
700 activate_widget(xuni->gui->active.widget, xuni, xp, yp);
701 enable_unicode(xuni->gui->active.widget);
703 else if(xuni->gui->active.widget) {
704 repaint = 1;
706 clear_active(xuni, &xuni->gui->active, 1);
709 if(*mode != (size_t)-1) {
710 set_loop_widget_sel(*mode, xp, yp, xuni->gui->sel.clickin,
711 xuni);
714 return repaint;
717 static int event_key_down(struct xuni_t *xuni, SDL_keysym *keysym,
718 panel_type_t *mode, int *handled) {
720 int repaint = 0;
722 switch(keysym->sym) {
723 case SDLK_ESCAPE:
724 if(xuni->gui->active.widget) {
725 clear_active(xuni, &xuni->gui->active, 0);
727 *handled = 1;
728 repaint = 1;
731 break;
732 case SDLK_PRINT:
733 save_screenshot(xuni->smode->screen);
735 *handled = 1;
736 break;
737 case SDLK_RETURN:
738 if(keysym->mod & KMOD_ALT) {
739 if(!toggle_fullscreen(xuni->smode)) repaint = 1;
741 *handled = 1;
743 else if(xuni->gui->tab.panel != (size_t)-1
744 && xuni->gui->tab.sel != (size_t)-1) {
746 repaint |= perform_loop_click(xuni, mode,
747 widget_nameid_follow(xuni->gui->widget,
748 xuni->gui->tab.panel, xuni->gui->tab.sel,
749 (size_t)-1));
752 break;
753 case SDLK_TAB:
754 if(xuni->gui->tab.panel == (size_t)-1) break;
756 if(keysym->mod & KMOD_SHIFT) {
757 if(xuni->gui->tab.sel-- == (size_t)-1) {
758 xuni->gui->tab.sel =
759 widget_nameid_access(xuni->gui->widget,
760 xuni->gui->tab.panel)->compose->widgets - 1;
763 else {
764 if(++xuni->gui->tab.sel ==
765 widget_nameid_access(xuni->gui->widget,
766 xuni->gui->tab.panel)->compose->widgets) {
768 xuni->gui->tab.sel = (size_t)-1;
772 repaint = 1;
773 *handled = 1;
774 break;
775 case SDLK_F9:
776 if(keysym->mod & KMOD_ALT) {
777 if(!SDL_WM_IconifyWindow()) {
778 /* error !!! */
781 *handled = 1;
783 break;
784 /* keypresses for debugging purposes */
785 case SDLK_F8:
786 if(xuni->gui->sel.p.widget) {
787 print_widget_backtrace(xuni, xuni->gui->sel.p.widget);
790 *handled = 1;
791 break;
792 case SDLK_F7:
793 if(xuni->gui->active.widget) {
794 print_widget_backtrace(xuni, xuni->gui->active.widget);
797 *handled = 1;
798 break;
799 case SDLK_F6:
800 puts("====");
801 print_sel_widgets(xuni->gui->widget);
802 *handled = 1;
803 break;
804 case SDLK_F5:
806 int x, y, xrel, yrel;
807 Uint8 state;
809 state = SDL_GetMouseState(&x, &y);
810 SDL_GetRelativeMouseState(&xrel, &yrel);
812 printf("Mouse: at (%i,%i), moved (%i,%i), buttons %i%i%i\n",
813 x, y, xrel, yrel, state & SDL_BUTTON(1),
814 state & SDL_BUTTON(2), state & SDL_BUTTON(3));
816 SDL_WarpMouse(x, y);
818 break;
819 case SDLK_F4:
820 repaint = 1;
821 break;
822 /*case SDLK_F3:
824 const SDL_Rect *r;
825 int x;
827 r = &widget_nameid_follow(xuni->gui->widget, 3, 15, (size_t)-1)
828 ->compose->widget[2]->compose->widget[2]->pos->real;
829 printf("data: (x=%i,y=%i,w=%i,h=%i)\n", r->x, r->y, r->w, r->h);
830 for(x = 0; x < 2; x ++) {
831 r = &widget_nameid_follow(xuni->gui->widget, 3, 15,
832 (size_t)-1)->compose->widget[2]->compose->widget[2]
833 ->compose->widget[x]->pos->real;
834 printf("[%i]: (x=%i,y=%i,w=%i,h=%i)\n", x,
835 r->x, r->y, r->w, r->h);
838 break;*/
839 /*case SDLK_F3:
841 struct widget_t *font;
842 const char *name[] = {
843 "alienglow/font-sans",
844 "outline/font-sans",
845 "bluesq/font-sans"
847 size_t x;
849 for(x = 0; x < sizeof(name)/sizeof(*name); x ++) {
850 font = find_widget(xuni->gui->widget, name[x]);
851 printf("%20s: widget_t %p -> font_t %p -> TTF_Font %p\n",
852 name[x], (void *)font, (void *)font->p.font,
853 (void *)font->p.font->ttf);
856 break;*/
857 case SDLK_F3:
858 if(xuni->gui->edit.datawidget) {
859 printf("textbox data: \"%s\"\n",
860 xuni->gui->edit.datawidget->p.label->text);
862 else puts("No label selected");
863 break;
864 case SDLK_F2:
865 if(xuni->gui->sel.p.widget->type == WIDGET_TEXTBOX) {
866 printf("textbox leftpos: %i\n",
867 xuni->gui->sel.p.widget->p.textbox->leftpos);
869 break;
870 case SDLK_F1:
871 move_scrollbar(xuni, xuni->gui->widget, 1);
872 break;
873 default:
874 break;
877 if(*mode != (size_t)-1) {
878 if(!*handled && find_widget_accelerator(
879 widget_nameid_access(xuni->gui->widget, *mode)
880 ->p.panel->accel, keysym, xuni, mode)) {
882 *handled = 1;
885 if(xuni->gui->active.widget) {
886 repaint = widget_process_character(xuni, keysym);
888 update_widget(xuni, xuni->gui->active.widget);
892 if(repaint) *handled = 1;
894 return repaint;