2013-06-07 16:27:59 +00:00
|
|
|
/*
|
2013-06-15 11:09:02 +00:00
|
|
|
* This file is subject to the terms of the GFX License. If a copy of
|
2013-06-07 16:27:59 +00:00
|
|
|
* the license was not distributed with this file, you can obtain one at:
|
|
|
|
*
|
2013-07-21 20:20:37 +00:00
|
|
|
* http://ugfx.org/license.html
|
2013-06-07 16:27:59 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "gfx.h"
|
|
|
|
|
|
|
|
// Used by the NULL window manager
|
|
|
|
#define MIN_WIN_WIDTH 3
|
|
|
|
#define MIN_WIN_HEIGHT 3
|
|
|
|
|
|
|
|
/*-----------------------------------------------
|
|
|
|
* The default window manager (GNullWindowManager)
|
|
|
|
*-----------------------------------------------*/
|
|
|
|
|
|
|
|
#if GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER
|
|
|
|
|
2014-02-18 14:36:52 +00:00
|
|
|
#include "src/gwin/class_gwin.h"
|
2013-06-07 16:27:59 +00:00
|
|
|
|
|
|
|
/*-----------------------------------------------
|
|
|
|
* Data
|
|
|
|
*-----------------------------------------------*/
|
|
|
|
|
|
|
|
static void WM_Init(void);
|
|
|
|
static void WM_DeInit(void);
|
2013-07-03 14:20:32 +00:00
|
|
|
static bool_t WM_Add(GHandle gh, const GWindowInit *pInit);
|
2013-06-07 16:27:59 +00:00
|
|
|
static void WM_Delete(GHandle gh);
|
2013-11-15 16:01:16 +00:00
|
|
|
static void WM_Redraw(GHandle gh, int flags);
|
2014-05-09 15:11:30 +00:00
|
|
|
static void WM_Size(GHandle gh, coord_t w, coord_t h);
|
|
|
|
static void WM_Move(GHandle gh, coord_t x, coord_t y);
|
2013-06-07 16:27:59 +00:00
|
|
|
static void WM_Raise(GHandle gh);
|
|
|
|
static void WM_MinMax(GHandle gh, GWindowMinMax minmax);
|
|
|
|
|
|
|
|
static const gwmVMT GNullWindowManagerVMT = {
|
|
|
|
WM_Init,
|
|
|
|
WM_DeInit,
|
|
|
|
WM_Add,
|
|
|
|
WM_Delete,
|
2013-11-15 16:01:16 +00:00
|
|
|
WM_Redraw,
|
2014-05-09 15:11:30 +00:00
|
|
|
WM_Size,
|
|
|
|
WM_Move,
|
2013-06-07 16:27:59 +00:00
|
|
|
WM_Raise,
|
|
|
|
WM_MinMax,
|
|
|
|
};
|
|
|
|
|
2013-07-07 09:40:37 +00:00
|
|
|
static const GWindowManager GNullWindowManager = {
|
2013-06-07 16:27:59 +00:00
|
|
|
&GNullWindowManagerVMT,
|
|
|
|
};
|
|
|
|
|
2014-05-09 15:11:30 +00:00
|
|
|
static gfxQueueASync _GWINList;
|
2013-07-07 09:40:37 +00:00
|
|
|
GWindowManager * _GWINwm;
|
2013-11-17 10:25:02 +00:00
|
|
|
#if GFX_USE_GTIMER
|
|
|
|
static GTimer RedrawTimer;
|
|
|
|
static GDisplay * RedrawDisplay;
|
|
|
|
static bool_t RedrawPreserve;
|
|
|
|
static void _gwinRedrawDisplay(void * param);
|
|
|
|
#endif
|
2013-07-07 09:40:37 +00:00
|
|
|
|
|
|
|
/*-----------------------------------------------
|
|
|
|
* Window Routines
|
|
|
|
*-----------------------------------------------*/
|
|
|
|
|
2014-02-02 18:24:43 +00:00
|
|
|
void _gwmInit(void)
|
|
|
|
{
|
2013-07-07 09:40:37 +00:00
|
|
|
gfxQueueASyncInit(&_GWINList);
|
|
|
|
_GWINwm = (GWindowManager *)&GNullWindowManager;
|
|
|
|
_GWINwm->vmt->Init();
|
2013-11-17 10:25:02 +00:00
|
|
|
#if GFX_USE_GTIMER
|
|
|
|
gtimerInit(&RedrawTimer);
|
|
|
|
gtimerStart(&RedrawTimer, _gwinRedrawDisplay, 0, TRUE, TIME_INFINITE);
|
|
|
|
#endif
|
2013-07-07 09:40:37 +00:00
|
|
|
}
|
|
|
|
|
2014-02-02 18:24:43 +00:00
|
|
|
void _gwmDeinit(void)
|
|
|
|
{
|
|
|
|
/* ToDo */
|
|
|
|
}
|
|
|
|
|
2013-07-07 09:40:37 +00:00
|
|
|
void gwinSetWindowManager(struct GWindowManager *gwm) {
|
|
|
|
if (!gwm)
|
|
|
|
gwm = (GWindowManager *)&GNullWindowManager;
|
|
|
|
if (_GWINwm != gwm) {
|
|
|
|
_GWINwm->vmt->DeInit();
|
|
|
|
_GWINwm = gwm;
|
|
|
|
_GWINwm->vmt->Init();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void gwinSetMinMax(GHandle gh, GWindowMinMax minmax) {
|
|
|
|
_GWINwm->vmt->MinMax(gh, minmax);
|
|
|
|
}
|
|
|
|
|
|
|
|
void gwinRaise(GHandle gh) {
|
|
|
|
_GWINwm->vmt->Raise(gh);
|
|
|
|
}
|
|
|
|
|
|
|
|
GWindowMinMax gwinGetMinMax(GHandle gh) {
|
|
|
|
if (gh->flags & GWIN_FLG_MINIMIZED)
|
|
|
|
return GWIN_MINIMIZE;
|
|
|
|
if (gh->flags & GWIN_FLG_MAXIMIZED)
|
|
|
|
return GWIN_MAXIMIZE;
|
|
|
|
return GWIN_NORMAL;
|
|
|
|
}
|
|
|
|
|
2013-11-15 16:01:16 +00:00
|
|
|
void gwinRedrawDisplay(GDisplay *g, bool_t preserve) {
|
2013-11-17 10:25:02 +00:00
|
|
|
#if GFX_USE_GTIMER
|
|
|
|
RedrawDisplay = g;
|
|
|
|
RedrawPreserve = preserve;
|
|
|
|
gtimerJab(&RedrawTimer);
|
|
|
|
}
|
|
|
|
static void _gwinRedrawDisplay(void * param) {
|
|
|
|
GDisplay *g = RedrawDisplay;
|
|
|
|
bool_t preserve = RedrawPreserve;
|
|
|
|
(void) param;
|
|
|
|
#endif
|
|
|
|
|
2013-11-15 16:01:16 +00:00
|
|
|
GHandle gh;
|
|
|
|
|
2014-05-09 15:11:30 +00:00
|
|
|
for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
|
2013-11-15 16:01:16 +00:00
|
|
|
if (!g || gh->display == g)
|
|
|
|
_GWINwm->vmt->Redraw(gh,
|
|
|
|
preserve ? (GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR|GWIN_WMFLG_NOZORDER)
|
|
|
|
: (GWIN_WMFLG_NOBGCLEAR|GWIN_WMFLG_NOZORDER));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-07 16:27:59 +00:00
|
|
|
/*-----------------------------------------------
|
2014-05-09 11:34:12 +00:00
|
|
|
* "Null" Window Manager Routines
|
2013-06-07 16:27:59 +00:00
|
|
|
*-----------------------------------------------*/
|
|
|
|
|
|
|
|
static void WM_Init(void) {
|
|
|
|
// We don't need to do anything here.
|
|
|
|
// A full window manager would move the windows around, add borders etc
|
|
|
|
|
|
|
|
// clear the screen
|
|
|
|
// cycle through the windows already defined displaying them
|
|
|
|
// or cut all the window areas out of the screen and clear the remainder
|
|
|
|
}
|
|
|
|
|
|
|
|
static void WM_DeInit(void) {
|
|
|
|
// We don't need to do anything here.
|
|
|
|
// A full window manager would remove any borders etc
|
|
|
|
}
|
|
|
|
|
2013-07-03 14:20:32 +00:00
|
|
|
static bool_t WM_Add(GHandle gh, const GWindowInit *pInit) {
|
2014-05-09 11:34:12 +00:00
|
|
|
// Note the window will not currently be marked as visible
|
2013-07-03 14:20:32 +00:00
|
|
|
|
2014-05-09 11:34:12 +00:00
|
|
|
// Put it on the end of the queue
|
2013-06-07 16:27:59 +00:00
|
|
|
gfxQueueASyncPut(&_GWINList, &gh->wmq);
|
|
|
|
|
2014-05-09 15:11:30 +00:00
|
|
|
// Make sure the size/position is valid - prefer position over size.
|
|
|
|
gh->width = MIN_WIN_WIDTH; gh->height = MIN_WIN_HEIGHT;
|
|
|
|
gh->x = gh->y = 0;
|
|
|
|
WM_Move(gh, pInit->x, pInit->y);
|
|
|
|
WM_Size(gh, pInit->width, pInit->height);
|
2013-06-07 16:27:59 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void WM_Delete(GHandle gh) {
|
2014-05-09 11:34:12 +00:00
|
|
|
// Remove it from the window list
|
2013-06-07 16:27:59 +00:00
|
|
|
gfxQueueASyncRemove(&_GWINList, &gh->wmq);
|
|
|
|
}
|
|
|
|
|
2013-11-15 16:01:16 +00:00
|
|
|
static void WM_Redraw(GHandle gh, int flags) {
|
2014-05-09 15:11:30 +00:00
|
|
|
#if GWIN_NEED_CONTAINERS
|
|
|
|
redo_redraw:
|
|
|
|
#endif
|
|
|
|
if ((gh->flags & GWIN_FLG_SYSVISIBLE)) {
|
2013-11-15 16:01:16 +00:00
|
|
|
if (gh->vmt->Redraw) {
|
|
|
|
#if GDISP_NEED_CLIP
|
2014-05-09 15:11:30 +00:00
|
|
|
if (!(flags & GWIN_WMFLG_KEEPCLIP))
|
|
|
|
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
|
2013-11-15 16:01:16 +00:00
|
|
|
#endif
|
2013-06-07 16:27:59 +00:00
|
|
|
gh->vmt->Redraw(gh);
|
2013-11-15 16:01:16 +00:00
|
|
|
} else if (!(flags & GWIN_WMFLG_PRESERVE)) {
|
|
|
|
#if GDISP_NEED_CLIP
|
2014-05-09 15:11:30 +00:00
|
|
|
if (!(flags & GWIN_WMFLG_KEEPCLIP))
|
|
|
|
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
|
2013-11-15 16:01:16 +00:00
|
|
|
#endif
|
2013-10-24 08:36:11 +00:00
|
|
|
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
|
2013-11-15 16:01:16 +00:00
|
|
|
if (gh->vmt->AfterClear)
|
|
|
|
gh->vmt->AfterClear(gh);
|
|
|
|
}
|
|
|
|
|
2013-07-05 15:42:10 +00:00
|
|
|
// A real window manager would also redraw the borders here
|
2013-11-15 16:01:16 +00:00
|
|
|
|
|
|
|
// A real window manager would then redraw any higher z-order windows
|
|
|
|
// if (!(flags & GWIN_WMFLG_NOZORDER))
|
|
|
|
// ...
|
|
|
|
|
|
|
|
} else if (!(flags & GWIN_WMFLG_NOBGCLEAR)) {
|
|
|
|
#if GDISP_NEED_CLIP
|
2014-05-09 15:11:30 +00:00
|
|
|
if (!(flags & GWIN_WMFLG_KEEPCLIP))
|
|
|
|
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
|
|
|
|
#endif
|
|
|
|
#if GWIN_NEED_CONTAINERS
|
|
|
|
if (gh->parent) {
|
|
|
|
// Get the parent to redraw the area
|
|
|
|
gh = gh->parent;
|
|
|
|
flags |= GWIN_WMFLG_KEEPCLIP;
|
|
|
|
goto redo_redraw;
|
|
|
|
}
|
2013-11-15 16:01:16 +00:00
|
|
|
#endif
|
2013-10-24 08:36:11 +00:00
|
|
|
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor());
|
2013-11-15 16:01:16 +00:00
|
|
|
}
|
2013-06-07 16:27:59 +00:00
|
|
|
}
|
|
|
|
|
2014-05-09 15:11:30 +00:00
|
|
|
static void WM_Size(GHandle gh, coord_t w, coord_t h) {
|
2014-05-10 08:20:05 +00:00
|
|
|
// Give it a minimum size
|
|
|
|
if (w < MIN_WIN_WIDTH) w = MIN_WIN_WIDTH;
|
|
|
|
if (h < MIN_WIN_HEIGHT) h = MIN_WIN_HEIGHT;
|
|
|
|
|
2014-05-09 15:11:30 +00:00
|
|
|
#if GWIN_NEED_CONTAINERS
|
2014-05-10 08:20:05 +00:00
|
|
|
if (gh->parent) {
|
|
|
|
// Clip to the container
|
|
|
|
if (gh->x+w > gh->parent->x+gh->parent->width) w = gh->parent->x + gh->parent->width - gh->x;
|
|
|
|
if (gh->y+h > gh->parent->y+gh->parent->height) h = gh->parent->y + gh->parent->height - gh->y;
|
2014-05-11 03:09:36 +00:00
|
|
|
if (((const gcontainerVMT *)gh->parent->vmt)->AdjustSize)
|
|
|
|
((const gcontainerVMT *)gh->parent->vmt)->AdjustSize(gh, &w, &h);
|
2014-05-10 08:20:05 +00:00
|
|
|
}
|
2014-05-09 15:11:30 +00:00
|
|
|
#endif
|
|
|
|
|
2014-05-10 08:20:05 +00:00
|
|
|
// Clip to the screen
|
2014-05-09 15:11:30 +00:00
|
|
|
if (gh->x+w > gdispGGetWidth(gh->display)) w = gdispGGetWidth(gh->display) - gh->x;
|
|
|
|
if (gh->y+h > gdispGGetHeight(gh->display)) h = gdispGGetHeight(gh->display) - gh->y;
|
2013-07-03 14:20:32 +00:00
|
|
|
|
|
|
|
// If there has been no resize just exit
|
2014-05-09 15:11:30 +00:00
|
|
|
if (gh->width == w && gh->height == h)
|
2013-07-03 14:20:32 +00:00
|
|
|
return;
|
|
|
|
|
2014-05-09 15:11:30 +00:00
|
|
|
// Clear the old area and then redraw
|
|
|
|
if ((gh->flags & GWIN_FLG_SYSVISIBLE)) {
|
|
|
|
gh->flags &= ~GWIN_FLG_SYSVISIBLE;
|
|
|
|
WM_Redraw(gh, 0);
|
|
|
|
gh->width = w; gh->height = h;
|
|
|
|
gh->flags |= GWIN_FLG_SYSVISIBLE;
|
|
|
|
WM_Redraw(gh, 0);
|
|
|
|
} else {
|
|
|
|
gh->width = w; gh->height = h;
|
2013-11-15 16:01:16 +00:00
|
|
|
}
|
2014-05-09 15:11:30 +00:00
|
|
|
}
|
2013-07-03 14:20:32 +00:00
|
|
|
|
2014-05-09 15:11:30 +00:00
|
|
|
static void WM_Move(GHandle gh, coord_t x, coord_t y) {
|
|
|
|
#if GWIN_NEED_CONTAINERS
|
2014-05-10 08:20:05 +00:00
|
|
|
if (gh->parent) {
|
|
|
|
// Clip to the parent
|
|
|
|
if (x < 0) x = 0;
|
|
|
|
if (y < 0) y = 0;
|
|
|
|
if (x > gh->parent->width-gh->width) x = gh->parent->width-gh->width;
|
|
|
|
if (y > gh->parent->height-gh->height) y = gh->parent->height-gh->height;
|
|
|
|
|
|
|
|
// Allow the parent to adjust it
|
2014-05-11 03:09:36 +00:00
|
|
|
if (((const gcontainerVMT *)gh->parent->vmt)->AdjustPosition)
|
|
|
|
((const gcontainerVMT *)gh->parent->vmt)->AdjustPosition(gh, &x, &y);
|
2014-05-10 08:20:05 +00:00
|
|
|
|
|
|
|
// Convert to absolute position
|
|
|
|
x += gh->parent->x;
|
|
|
|
y += gh->parent->y;
|
|
|
|
}
|
2014-05-09 15:11:30 +00:00
|
|
|
#endif
|
2013-07-03 14:20:32 +00:00
|
|
|
|
2014-05-09 15:11:30 +00:00
|
|
|
// Clip to the screen
|
|
|
|
if (x < 0) x = 0;
|
|
|
|
if (y < 0) y = 0;
|
|
|
|
if (x > gdispGGetWidth(gh->display)-gh->width) x = gdispGGetWidth(gh->display)-gh->width;
|
|
|
|
if (y > gdispGGetHeight(gh->display)-gh->height) y = gdispGGetHeight(gh->display)-gh->height;
|
|
|
|
|
|
|
|
// If there has been no move just exit
|
|
|
|
if (gh->x == x && gh->y == y)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Clear the old area and then redraw
|
|
|
|
if ((gh->flags & GWIN_FLG_SYSVISIBLE)) {
|
|
|
|
gh->flags &= ~GWIN_FLG_SYSVISIBLE;
|
|
|
|
WM_Redraw(gh, 0);
|
|
|
|
gh->x = x; gh->y = y;
|
|
|
|
gh->flags |= GWIN_FLG_SYSVISIBLE;
|
|
|
|
WM_Redraw(gh, 0);
|
|
|
|
} else {
|
|
|
|
gh->x = x; gh->y = y;
|
|
|
|
}
|
2013-06-07 16:27:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void WM_MinMax(GHandle gh, GWindowMinMax minmax) {
|
|
|
|
(void)gh; (void) minmax;
|
|
|
|
// We don't support minimising, maximising or restoring
|
|
|
|
}
|
|
|
|
|
|
|
|
static void WM_Raise(GHandle gh) {
|
|
|
|
// Take it off the list and then put it back on top
|
|
|
|
// The order of the list then reflects the z-order.
|
2014-05-09 15:11:30 +00:00
|
|
|
|
2013-06-07 16:27:59 +00:00
|
|
|
gfxQueueASyncRemove(&_GWINList, &gh->wmq);
|
|
|
|
gfxQueueASyncPut(&_GWINList, &gh->wmq);
|
|
|
|
|
|
|
|
// Redraw the window
|
2013-11-15 16:01:16 +00:00
|
|
|
WM_Redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
|
2013-06-07 16:27:59 +00:00
|
|
|
}
|
|
|
|
|
2014-05-09 15:11:30 +00:00
|
|
|
GHandle gwinGetNextWindow(GHandle gh) {
|
|
|
|
return gh ? (GHandle)gfxQueueASyncNext(&gh->wmq) : (GHandle)gfxQueueASyncPeek(&_GWINList);
|
|
|
|
}
|
|
|
|
|
2013-06-07 16:27:59 +00:00
|
|
|
#endif /* GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER */
|
|
|
|
/** @} */
|