dxx-rebirth/common/arch/sdl/window.cpp

221 lines
5.1 KiB
C++
Raw Normal View History

2014-06-01 17:55:23 +00:00
/*
* This file is part of the DXX-Rebirth project <http://www.dxx-rebirth.com/>.
* It is copyright by its individual contributors, as recorded in the
* project's Git history. See COPYING.txt at the top level for license
* terms and a link to the Git history.
*/
2009-05-21 12:16:39 +00:00
/*
* A 'window' is simply a canvas that can receive events.
* It can be anything from a simple message box to the
* game screen when playing.
*
* See event.c for event handling code.
*
* -kreator 2009-05-06
*/
#include "gr.h"
#include "window.h"
#include "u_mem.h"
#include "dxxerror.h"
2009-05-21 12:16:39 +00:00
struct window
{
grs_canvas w_canv; // the window's canvas to draw to
2014-10-04 21:47:13 +00:00
window_event_result (*w_callback)(window *wind,const d_event &event, void *data); // the event handler
2009-05-21 12:16:39 +00:00
int w_visible; // whether it's visible
int w_modal; // modal = accept all user input exclusively
2009-05-21 12:16:39 +00:00
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
};
static window *FrontWindow = NULL;
static window *FirstWindow = NULL;
2014-12-20 04:36:09 +00:00
window *window_create(grs_canvas *src, int x, int y, int w, int h, window_subfunction_t<void>::type event_callback, void *data, const void *createdata)
2009-05-21 12:16:39 +00:00
{
window *prev = window_get_front();
2014-12-20 04:36:09 +00:00
d_create_event event;
2014-09-17 02:45:23 +00:00
window *wind = new window;
2009-05-21 12:16:39 +00:00
Assert(src != NULL);
Assert(event_callback != NULL);
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
2009-05-21 12:16:39 +00:00
wind->data = data;
if (FirstWindow == NULL)
FirstWindow = wind;
wind->prev = FrontWindow;
if (FrontWindow)
FrontWindow->next = wind;
2009-05-21 12:16:39 +00:00
wind->next = NULL;
FrontWindow = wind;
if (prev)
WINDOW_SEND_EVENT(prev, EVENT_WINDOW_DEACTIVATED);
2014-12-20 04:36:09 +00:00
event.createdata = createdata;
WINDOW_SEND_EVENT(wind, EVENT_WINDOW_CREATED);
WINDOW_SEND_EVENT(wind, EVENT_WINDOW_ACTIVATED);
2009-05-21 12:16:39 +00:00
return wind;
}
int window_close(window *wind)
2009-05-21 12:16:39 +00:00
{
window *prev;
d_event event;
2014-10-04 21:47:13 +00:00
window_event_result (*w_callback)(window *wind,const d_event &event, void *data) = wind->w_callback;
if (wind == window_get_front())
WINDOW_SEND_EVENT(wind, EVENT_WINDOW_DEACTIVATED); // Deactivate first
2014-08-06 02:10:49 +00:00
if (WINDOW_SEND_EVENT(wind, EVENT_WINDOW_CLOSE) == window_event_result::handled)
{
// User 'handled' the event, cancelling close
if (wind == window_get_front())
{
WINDOW_SEND_EVENT(wind, EVENT_WINDOW_ACTIVATED);
}
return 0;
}
2009-05-21 12:16:39 +00:00
if (wind == FrontWindow)
FrontWindow = wind->prev;
if (wind == FirstWindow)
FirstWindow = wind->next;
if (wind->next)
wind->next->prev = wind->prev;
if (wind->prev)
wind->prev->next = wind->next;
if ((prev = window_get_front()))
WINDOW_SEND_EVENT(prev, EVENT_WINDOW_ACTIVATED);
event.type = EVENT_WINDOW_CLOSED;
2014-10-04 21:47:13 +00:00
w_callback(wind, event, NULL); // callback needs to recognise this is a NULL pointer!
2014-09-17 02:45:23 +00:00
delete wind;
return 1;
2009-05-21 12:16:39 +00:00
}
int window_exists(window *wind)
{
window *w;
for (w = FirstWindow; w && w != wind; w = w->next) {}
return w && w == wind;
}
2009-05-21 12:16:39 +00:00
// Get the top window that's visible
window *window_get_front(void)
{
window *wind;
for (wind = FrontWindow; (wind != NULL) && !wind->w_visible; wind = wind->prev) {}
return wind;
}
window *window_get_first(void)
{
return FirstWindow;
}
window *window_get_next(window *wind)
{
return wind->next;
}
window *window_get_prev(window *wind)
{
return wind->prev;
}
2009-05-21 12:16:39 +00:00
// Make wind the front window
void window_select(window *wind)
{
window *prev = window_get_front();
d_event event;
2009-05-21 12:16:39 +00:00
Assert (wind != NULL);
if (wind == FrontWindow)
return;
if ((wind == FirstWindow) && FirstWindow->next)
FirstWindow = FirstWindow->next;
if (wind->next)
wind->next->prev = wind->prev;
if (wind->prev)
wind->prev->next = wind->next;
wind->prev = FrontWindow;
FrontWindow->next = wind;
2009-05-21 12:16:39 +00:00
wind->next = NULL;
FrontWindow = wind;
if (window_is_visible(wind))
{
if (prev)
WINDOW_SEND_EVENT(prev, EVENT_WINDOW_DEACTIVATED);
WINDOW_SEND_EVENT(wind, EVENT_WINDOW_ACTIVATED);
}
2009-05-21 12:16:39 +00:00
}
void window_set_visible(window *wind, int visible)
{
window *prev = window_get_front();
d_event event;
2009-05-21 12:16:39 +00:00
wind->w_visible = visible;
wind = window_get_front(); // get the new front window
if (wind == prev)
return;
if (prev)
WINDOW_SEND_EVENT(prev, EVENT_WINDOW_DEACTIVATED);
if (wind)
WINDOW_SEND_EVENT(wind, EVENT_WINDOW_ACTIVATED);
2009-05-21 12:16:39 +00:00
}
int window_is_visible(window *wind)
{
return wind->w_visible;
}
2015-01-17 18:31:40 +00:00
grs_canvas &window_get_canvas(window &wind)
2009-05-21 12:16:39 +00:00
{
2015-01-17 18:31:40 +00:00
return wind.w_canv;
2009-05-21 12:16:39 +00:00
}
extern void window_update_canvases(void)
{
window *wind;
for (wind = FirstWindow; wind != NULL; wind = wind->next)
2014-11-30 22:09:21 +00:00
gr_init_sub_bitmap (wind->w_canv.cv_bitmap,
*wind->w_canv.cv_bitmap.bm_parent,
wind->w_canv.cv_bitmap.bm_x,
wind->w_canv.cv_bitmap.bm_y,
wind->w_canv.cv_bitmap.bm_w,
wind->w_canv.cv_bitmap.bm_h);
}
2014-10-04 21:47:13 +00:00
window_event_result window_send_event(window *wind,const d_event &event)
2009-05-21 12:16:39 +00:00
{
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;
}