2014-06-01 17:55:23 +00:00
|
|
|
/*
|
2018-09-02 00:57:29 +00:00
|
|
|
* This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
|
2014-06-01 17:55:23 +00:00
|
|
|
* 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"
|
2009-05-22 10:53:14 +00:00
|
|
|
#include "u_mem.h"
|
2012-07-07 18:35:06 +00:00
|
|
|
#include "dxxerror.h"
|
2015-10-09 02:46:10 +00:00
|
|
|
#include "event.h"
|
2009-05-21 12:16:39 +00:00
|
|
|
|
2015-12-13 18:00:49 +00:00
|
|
|
namespace dcx {
|
2015-12-05 22:57:24 +00:00
|
|
|
|
2016-10-03 03:10:11 +00:00
|
|
|
static window *FrontWindow = nullptr;
|
|
|
|
static window *FirstWindow = nullptr;
|
2009-05-21 12:16:39 +00:00
|
|
|
|
2016-11-19 17:24:52 +00:00
|
|
|
window::window(grs_canvas &src, const int x, const int y, const int w, const int h) :
|
2016-10-03 03:10:11 +00:00
|
|
|
// Default to visible and modal
|
2016-11-19 17:24:52 +00:00
|
|
|
w_visible(1), w_modal(1), prev(FrontWindow), next(nullptr), w_exists(nullptr)
|
2009-05-21 12:16:39 +00:00
|
|
|
{
|
2016-10-15 00:53:21 +00:00
|
|
|
gr_init_sub_canvas(w_canv, src, x, y, w, h);
|
2009-05-21 12:16:39 +00:00
|
|
|
|
2016-10-03 03:10:11 +00:00
|
|
|
if (FirstWindow == nullptr)
|
2016-10-15 00:53:21 +00:00
|
|
|
FirstWindow = this;
|
|
|
|
}
|
|
|
|
|
2020-10-22 02:26:16 +00:00
|
|
|
void window::send_creation_events()
|
2016-10-15 00:53:21 +00:00
|
|
|
{
|
|
|
|
const auto prev_front = window_get_front();
|
2009-08-10 10:47:17 +00:00
|
|
|
if (FrontWindow)
|
2016-10-15 00:53:21 +00:00
|
|
|
FrontWindow->next = this;
|
|
|
|
FrontWindow = this;
|
2016-10-02 06:49:22 +00:00
|
|
|
if (prev_front)
|
2016-10-15 00:53:21 +00:00
|
|
|
{
|
2018-05-12 18:24:19 +00:00
|
|
|
const d_event event{EVENT_WINDOW_DEACTIVATED};
|
|
|
|
WINDOW_SEND_EVENT(prev_front);
|
2016-10-15 00:53:21 +00:00
|
|
|
}
|
|
|
|
{
|
2020-10-22 02:26:16 +00:00
|
|
|
const d_create_event event{};
|
2018-05-12 18:24:19 +00:00
|
|
|
WINDOW_SEND_EVENT(this);
|
2016-10-15 00:53:21 +00:00
|
|
|
}
|
|
|
|
{
|
2018-05-12 18:24:19 +00:00
|
|
|
const d_event event{EVENT_WINDOW_ACTIVATED};
|
|
|
|
WINDOW_SEND_EVENT(this);
|
2016-10-15 00:53:21 +00:00
|
|
|
}
|
2009-05-21 12:16:39 +00:00
|
|
|
}
|
|
|
|
|
2016-10-02 09:49:19 +00:00
|
|
|
window::~window()
|
|
|
|
{
|
2016-10-28 08:49:53 +00:00
|
|
|
if (w_exists)
|
|
|
|
*w_exists = false;
|
2016-10-02 09:49:19 +00:00
|
|
|
if (this == FrontWindow)
|
|
|
|
FrontWindow = this->prev;
|
|
|
|
if (this == FirstWindow)
|
|
|
|
FirstWindow = this->next;
|
|
|
|
if (this->next)
|
|
|
|
this->next->prev = this->prev;
|
|
|
|
if (this->prev)
|
|
|
|
this->prev->next = this->next;
|
|
|
|
}
|
|
|
|
|
2009-12-02 13:49:54 +00:00
|
|
|
int window_close(window *wind)
|
2009-05-21 12:16:39 +00:00
|
|
|
{
|
2010-02-02 03:38:29 +00:00
|
|
|
window *prev;
|
2016-10-04 06:05:44 +00:00
|
|
|
window_event_result result;
|
2009-12-02 13:49:54 +00:00
|
|
|
|
2010-02-08 06:08:55 +00:00
|
|
|
if (wind == window_get_front())
|
2018-05-12 18:24:19 +00:00
|
|
|
{
|
|
|
|
const d_event event{EVENT_WINDOW_DEACTIVATED};
|
|
|
|
WINDOW_SEND_EVENT(wind); // Deactivate first
|
|
|
|
}
|
2010-02-08 06:08:55 +00:00
|
|
|
|
2018-05-12 18:24:19 +00:00
|
|
|
{
|
|
|
|
const d_event event{EVENT_WINDOW_CLOSE};
|
|
|
|
result = WINDOW_SEND_EVENT(wind);
|
|
|
|
}
|
|
|
|
if (result == window_event_result::handled)
|
2010-02-02 03:38:29 +00:00
|
|
|
{
|
2010-02-08 06:08:55 +00:00
|
|
|
// User 'handled' the event, cancelling close
|
|
|
|
if (wind == window_get_front())
|
2011-02-03 10:47:54 +00:00
|
|
|
{
|
2018-05-12 18:24:19 +00:00
|
|
|
const d_event event{EVENT_WINDOW_ACTIVATED};
|
|
|
|
WINDOW_SEND_EVENT(wind);
|
2011-02-03 10:47:54 +00:00
|
|
|
}
|
2010-02-08 06:08:55 +00:00
|
|
|
return 0;
|
2010-02-02 03:38:29 +00:00
|
|
|
}
|
2009-12-02 13:49:54 +00:00
|
|
|
|
2016-11-19 18:09:26 +00:00
|
|
|
menu_destroy_hook(wind);
|
|
|
|
|
2016-10-04 06:05:44 +00:00
|
|
|
if (result != window_event_result::deleted) // don't attempt to re-delete
|
|
|
|
delete wind;
|
|
|
|
|
2010-02-02 03:38:29 +00:00
|
|
|
if ((prev = window_get_front()))
|
2018-05-12 18:24:19 +00:00
|
|
|
{
|
|
|
|
const d_event event{EVENT_WINDOW_ACTIVATED};
|
|
|
|
WINDOW_SEND_EVENT(prev);
|
|
|
|
}
|
2011-02-03 10:47:54 +00:00
|
|
|
|
2009-12-02 13:49:54 +00:00
|
|
|
return 1;
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make wind the front window
|
2015-01-17 18:31:41 +00:00
|
|
|
void window_select(window &wind)
|
2009-05-21 12:16:39 +00:00
|
|
|
{
|
2010-02-02 03:38:29 +00:00
|
|
|
window *prev = window_get_front();
|
2015-01-17 18:31:41 +00:00
|
|
|
if (&wind == FrontWindow)
|
2009-05-21 12:16:39 +00:00
|
|
|
return;
|
2015-01-17 18:31:41 +00:00
|
|
|
if (&wind == FirstWindow && wind.next)
|
2009-05-21 12:16:39 +00:00
|
|
|
FirstWindow = FirstWindow->next;
|
|
|
|
|
2015-01-17 18:31:41 +00:00
|
|
|
if (wind.next)
|
|
|
|
wind.next->prev = wind.prev;
|
|
|
|
if (wind.prev)
|
|
|
|
wind.prev->next = wind.next;
|
|
|
|
wind.prev = FrontWindow;
|
|
|
|
FrontWindow->next = &wind;
|
|
|
|
wind.next = nullptr;
|
|
|
|
FrontWindow = &wind;
|
2010-01-20 05:10:32 +00:00
|
|
|
|
2016-10-02 06:32:30 +00:00
|
|
|
if (wind.is_visible())
|
2010-02-02 03:38:29 +00:00
|
|
|
{
|
|
|
|
if (prev)
|
2018-05-12 18:24:19 +00:00
|
|
|
{
|
|
|
|
const d_event event{EVENT_WINDOW_DEACTIVATED};
|
|
|
|
WINDOW_SEND_EVENT(prev);
|
|
|
|
}
|
|
|
|
const d_event event{EVENT_WINDOW_ACTIVATED};
|
|
|
|
WINDOW_SEND_EVENT(&wind);
|
2010-02-02 03:38:29 +00:00
|
|
|
}
|
2009-05-21 12:16:39 +00:00
|
|
|
}
|
|
|
|
|
2015-01-17 18:31:41 +00:00
|
|
|
window *window_set_visible(window &w, int visible)
|
2009-05-21 12:16:39 +00:00
|
|
|
{
|
2010-02-02 03:38:29 +00:00
|
|
|
window *prev = window_get_front();
|
2015-01-17 18:31:41 +00:00
|
|
|
w.w_visible = visible;
|
|
|
|
auto wind = window_get_front(); // get the new front window
|
2010-02-02 03:38:29 +00:00
|
|
|
if (wind == prev)
|
2015-01-17 18:31:41 +00:00
|
|
|
return wind;
|
2010-02-02 03:38:29 +00:00
|
|
|
|
|
|
|
if (prev)
|
2018-05-12 18:24:19 +00:00
|
|
|
{
|
|
|
|
const d_event event{EVENT_WINDOW_DEACTIVATED};
|
|
|
|
WINDOW_SEND_EVENT(prev);
|
|
|
|
}
|
2010-02-05 14:05:57 +00:00
|
|
|
|
|
|
|
if (wind)
|
2018-05-12 18:24:19 +00:00
|
|
|
{
|
|
|
|
const d_event event{EVENT_WINDOW_ACTIVATED};
|
|
|
|
WINDOW_SEND_EVENT(wind);
|
|
|
|
}
|
2015-01-17 18:31:41 +00:00
|
|
|
return wind;
|
2009-05-21 12:16:39 +00:00
|
|
|
}
|
|
|
|
|
2016-09-24 18:06:11 +00:00
|
|
|
#if !DXX_USE_OGL
|
2015-12-04 03:36:31 +00:00
|
|
|
void window_update_canvases()
|
2012-03-24 06:43:08 +00:00
|
|
|
{
|
|
|
|
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,
|
2012-03-24 06:43:08 +00:00
|
|
|
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);
|
|
|
|
}
|
2015-12-04 03:36:31 +00:00
|
|
|
#endif
|
2012-03-24 06:43:08 +00:00
|
|
|
|
2015-12-05 22:57:24 +00:00
|
|
|
}
|