From 3121fb4990901f77fceb57b094fefa3556b53871 Mon Sep 17 00:00:00 2001 From: Chris Taylor Date: Sun, 9 Oct 2011 18:31:44 +0800 Subject: [PATCH] Add support for 'modeless' windows - windows that will allow events to be passed on to the underlying window. Intended for the editor --- CHANGELOG.txt | 1 + arch/include/event.h | 4 ++-- arch/include/window.h | 2 ++ arch/sdl/event.c | 17 +++++++++++------ arch/sdl/window.c | 12 ++++++++++++ include/ui.h | 23 ++++++++++++++--------- ui/dialog.c | 7 ++++++- ui/file.c | 2 +- ui/keypress.c | 2 +- ui/menu.c | 2 +- ui/message.c | 2 +- ui/popup.c | 2 +- 12 files changed, 53 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 77a16e9d3..6b1f6aa7b 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -3,6 +3,7 @@ D1X-Rebirth Changelog 20111009 -------- main/render.c: Initialise dyn_light using memset, fixing a warning +arch/include/event.h, arch/include/window.h, arch/sdl/event.c, arch/sdl/window.c, include/ui.h, ui/dialog.c, ui/file.c, ui/keypress.c, ui/menu.c, ui/message.c, ui/popup.c: Add support for 'modeless' windows - windows that will allow events to be passed on to the underlying window. Intended for the editor 20110927 -------- diff --git a/arch/include/event.h b/arch/include/event.h index 41df96208..ce7861d3c 100644 --- a/arch/include/event.h +++ b/arch/include/event.h @@ -14,7 +14,7 @@ typedef enum event_type EVENT_MOUSE_BUTTON_DOWN, EVENT_MOUSE_BUTTON_UP, - EVENT_MOUSE_DOUBLE_CLICKED, // editor only for now + EVENT_MOUSE_DOUBLE_CLICKED, EVENT_MOUSE_MOVED, EVENT_KEY_COMMAND, @@ -47,7 +47,7 @@ void event_flush(); void set_default_handler(int (*handler)(d_event *event)); int call_default_handler(d_event *event); -// Send an event to the front window as first priority, then the default handler +// Send an event to the front window as first priority, then to the windows behind if it's not modal (editor), then the default handler void event_send(d_event *event); // Sends input, idle and draw events to event handlers diff --git a/arch/include/window.h b/arch/include/window.h index f6bf26af0..2ad12e020 100644 --- a/arch/include/window.h +++ b/arch/include/window.h @@ -29,6 +29,8 @@ extern void window_set_visible(window *wind, int visible); extern int window_is_visible(window *wind); extern grs_canvas *window_get_canvas(window *wind); extern int window_send_event(window *wind, d_event *event); +extern void window_set_modal(window *wind, int modal); +extern int window_is_modal(window *wind); #define WINDOW_SEND_EVENT(w, e) \ do { \ diff --git a/arch/sdl/event.c b/arch/sdl/event.c index e0961f14d..399ff1de1 100644 --- a/arch/sdl/event.c +++ b/arch/sdl/event.c @@ -124,13 +124,18 @@ int call_default_handler(d_event *event) void event_send(d_event *event) { window *wind; + int handled = 0; - if ((wind = window_get_front())) - { - if (!window_send_event(wind, event)) - call_default_handler(event); - } - else + for (wind = window_get_front(); wind != NULL && !handled; wind = window_get_prev(wind)) + if (window_is_visible(wind)) + { + handled = window_send_event(wind, event); + + if (window_is_modal(wind)) + break; + } + + if (!handled) call_default_handler(event); } diff --git a/arch/sdl/window.c b/arch/sdl/window.c index 91d1b12bd..bef02aaa5 100644 --- a/arch/sdl/window.c +++ b/arch/sdl/window.c @@ -18,6 +18,7 @@ struct window grs_canvas w_canv; // the window's canvas to draw to int (*w_callback)(window *wind, d_event *event, void *data); // the event handler int w_visible; // whether it's visible + int w_modal; // modal = accept all user input exclusively void *data; // whatever the user wants (eg menu data for 'newmenu' menus) struct window *prev; // the previous window in the doubly linked list struct window *next; // the next window in the doubly linked list @@ -41,6 +42,7 @@ window *window_create(grs_canvas *src, int x, int y, int w, int h, int (*event_c gr_init_sub_canvas(&wind->w_canv, src, x, y, w, h); wind->w_callback = event_callback; wind->w_visible = 1; // default to visible + wind->w_modal = 1; // default to modal wind->data = data; if (FirstWindow == NULL) @@ -194,3 +196,13 @@ int window_send_event(window *wind, d_event *event) { return wind->w_callback(wind, event, wind->data); } + +void window_set_modal(window *wind, int modal) +{ + wind->w_modal = modal; +} + +int window_is_modal(window *wind) +{ + return wind->w_modal; +} diff --git a/include/ui.h b/include/ui.h index 0f800e153..88d1c3e90 100644 --- a/include/ui.h +++ b/include/ui.h @@ -186,12 +186,18 @@ typedef struct { int moved; } UI_GADGET_LISTBOX; +enum dialog_flags +{ + DF_BORDER = 1, + DF_FILLED = 2, + DF_SAVE_BG = 4, + DF_DIALOG = (4+2+1), + DF_MODAL = 8 // modal = accept all user input exclusively +}; + typedef struct _ui_window { struct window *wind; int (*callback)(struct _ui_window *, struct d_event *, void *); - short x, y; - short width, height; - short text_x, text_y; grs_canvas * canvas; grs_canvas * oldcanvas; grs_bitmap * background; @@ -200,6 +206,10 @@ typedef struct _ui_window { struct _ui_window * next; struct _ui_window * prev; void *userdata; + short x, y; + short width, height; + short text_x, text_y; + enum dialog_flags flags; } UI_DIALOG; typedef struct { @@ -270,12 +280,7 @@ extern int ui_mouse_motion_process(struct d_event *event); extern void ui_mouse_hide(); extern void ui_mouse_show(); -#define DF_BORDER 1 -#define DF_FILLED 2 -#define DF_SAVE_BG 4 -#define DF_DIALOG (4+2+1) - -extern UI_DIALOG * ui_create_dialog( short x, short y, short w, short h, int flags, int (*callback)(UI_DIALOG *, struct d_event *, void *), void *userdata ); +extern UI_DIALOG * ui_create_dialog( short x, short y, short w, short h, enum dialog_flags flags, int (*callback)(UI_DIALOG *, struct d_event *, void *), void *userdata ); extern void ui_close_dialog( UI_DIALOG * dlg ); extern UI_GADGET * ui_gadget_add( UI_DIALOG * dlg, short kind, short x1, short y1, short x2, short y2 ); diff --git a/ui/dialog.c b/ui/dialog.c index 3155c684f..4ac0a8add 100644 --- a/ui/dialog.c +++ b/ui/dialog.c @@ -257,7 +257,7 @@ int ui_dialog_handler(window *wind, d_event *event, UI_DIALOG *dlg) return 0; } -UI_DIALOG * ui_create_dialog( short x, short y, short w, short h, int flags, int (*callback)(UI_DIALOG *, d_event *, void *), void *userdata ) +UI_DIALOG * ui_create_dialog( short x, short y, short w, short h, enum dialog_flags flags, int (*callback)(UI_DIALOG *, d_event *, void *), void *userdata ) { UI_DIALOG *dlg; int sw, sh, req_w, req_h; @@ -277,6 +277,8 @@ UI_DIALOG * ui_create_dialog( short x, short y, short w, short h, int flags, int req_w = w; req_h = h; + + dlg->flags = flags; if (flags & DF_BORDER) { @@ -332,6 +334,9 @@ UI_DIALOG * ui_create_dialog( short x, short y, short w, short h, int flags, int return NULL; } + if (!(flags & DF_MODAL)) + window_set_modal(dlg->wind, 0); // make this window modeless, allowing events to propogate through the window stack + if (flags & DF_FILLED) ui_draw_box_out( 0, 0, req_w-1, req_h-1 ); diff --git a/ui/file.c b/ui/file.c index b51f47356..ebdafdca2 100644 --- a/ui/file.c +++ b/ui/file.c @@ -159,7 +159,7 @@ int ui_get_filename( char * filename, char * Filespec, char * message ) Spaces[i] = ' '; Spaces[34] = 0; - dlg = ui_create_dialog( 200, 100, 400, 370, DF_DIALOG, NULL, NULL ); + dlg = ui_create_dialog( 200, 100, 400, 370, DF_DIALOG | DF_MODAL, NULL, NULL ); ui_dprintf_at( dlg, 10, 5, message ); diff --git a/ui/keypress.c b/ui/keypress.c index 82a85280b..adbfe58b2 100644 --- a/ui/keypress.c +++ b/ui/keypress.c @@ -110,7 +110,7 @@ int GetKeyCode(char * text) text = text; - dlg = ui_create_dialog( 200, 200, 400, 200, DF_DIALOG, NULL, NULL ); + dlg = ui_create_dialog( 200, 200, 400, 200, DF_DIALOG | DF_MODAL, NULL, NULL ); DoneButton = ui_add_gadget_button( dlg, 170, 165, 60, 25, "Ok", NULL ); diff --git a/ui/menu.c b/ui/menu.c index 1b8da1dda..af8b45027 100644 --- a/ui/menu.c +++ b/ui/menu.c @@ -84,7 +84,7 @@ int MenuX( int x, int y, int NumButtons, char * text[] ) y = h - height; } - dlg = ui_create_dialog( x, y, width, height, DF_FILLED | DF_SAVE_BG, NULL, NULL ); + dlg = ui_create_dialog( x, y, width, height, DF_FILLED | DF_SAVE_BG | DF_MODAL, NULL, NULL ); x = MENU_BORDER+3; y = MENU_BORDER+3; diff --git a/ui/message.c b/ui/message.c index 2d27e3781..8c75db026 100644 --- a/ui/message.c +++ b/ui/message.c @@ -116,7 +116,7 @@ int MessageBoxN( short xc, short yc, int NumButtons, char * text, char * Button[ y = h - height; } - dlg = ui_create_dialog( x, y, width, height, DF_DIALOG, NULL, NULL ); + dlg = ui_create_dialog( x, y, width, height, DF_DIALOG | DF_MODAL, NULL, NULL ); //ui_draw_line_in( MESSAGEBOX_BORDER, MESSAGEBOX_BORDER, width-MESSAGEBOX_BORDER, height-MESSAGEBOX_BORDER ); diff --git a/ui/popup.c b/ui/popup.c index 5b3d39015..5e7425bd6 100644 --- a/ui/popup.c +++ b/ui/popup.c @@ -104,7 +104,7 @@ int PopupMenu( int NumButtons, char * text[] ) Mouse.y = y + (MENU_BORDER+3) + button_height/2; } - dlg = ui_create_dialog( x, y, width, height, DF_DIALOG, NULL, NULL ); + dlg = ui_create_dialog( x, y, width, height, DF_DIALOG | DF_MODAL, NULL, NULL ); //mouse_set_pos(Mouse.x, Mouse.y);