Add support to GWIN for a routine that can redraw an entire display (subject to the controls being able to redraw).

This also removes a few change of visibility bugs in gwin and simplifies code.
ugfx_release_2.6
inmarket 2013-11-16 02:01:16 +10:00
parent 3c3bab5d82
commit d35bf6cda6
4 changed files with 115 additions and 93 deletions

View File

@ -104,6 +104,16 @@ typedef struct gwinVMT {
/* @} */
#endif
// These flags are needed whether or not we are running a window manager.
/**
* @brief Flags for redrawing after a visibility change
* @{
*/
#define GWIN_WMFLG_PRESERVE 0x0001 // @< Preserve whatever existing contents possible if a window can't redraw
#define GWIN_WMFLG_NOBGCLEAR 0x0002 // @< Don't clear the area if the window is not visible
#define GWIN_WMFLG_NOZORDER 0x0004 // @< Don't redraw higher z-order windows that overlap
/* @} */
#if GWIN_NEED_WINDOWMANAGER || defined(__DOXYGEN__)
#if 1 // When we know that wmq is the first element of the GWindowObject structure
#define QItem2GWindow(qi) ((GHandle)qi)
@ -125,7 +135,7 @@ typedef struct gwinVMT {
void (*DeInit) (void); // @< The window manager has just been removed as the current window manager
bool_t (*Add) (GHandle gh, const GWindowInit *pInit); // @< A window has been added
void (*Delete) (GHandle gh); // @< A window has been deleted
void (*Visible) (GHandle gh); // @< A window has changed its visibility state
void (*Redraw) (GHandle gh, int visflags); // @< A window needs to be redraw (or undrawn)
void (*Redim) (GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h); // @< A window wants to be moved or resized
void (*Raise) (GHandle gh); // @< A window wants to be on top
void (*MinMax) (GHandle gh, GWindowMinMax minmax); // @< A window wants to be minimized/maximised

View File

@ -378,6 +378,22 @@ extern "C" {
void gwinRedraw(GHandle gh);
#if GWIN_NEED_WINDOWMANAGER
/**
* @brief Redraw a window
*
* @param[in] g The display to redraw. Passing NULL will redraw all displays.
* @param[in] preserve Should the redraw try to preserve existing screen data for those
* windows that can't redraw themselves?
*
* @note This is normally never required as windows and widgets will redraw as required.
* @note Some windows are incapable of redrawing themselves as they don't save
* their drawing state.
* @note This does not clear the background - just redraws the gwin windows (where possible)
*
* @api
*/
void gwinRedrawDisplay(GDisplay *g, bool_t preserve);
/**
* @brief Minimize, Maximize or Restore a window
* @pre GWIN_NEED_WINDOWMANAGER must be TRUE

View File

@ -37,15 +37,31 @@ static color_t defaultBgColor = Black;
* Helper Routines
*-----------------------------------------------*/
#if !GWIN_NEED_WINDOWMANAGER
static void _gwm_vis(GHandle gh) {
if (gh->vmt->Redraw) {
#if GWIN_NEED_WINDOWMANAGER
#define _gwm_redraw(gh, flags) _GWINwm->vmt->Redraw(gh, flags)
#define _gwm_redim(gh,x,y,w,h) _GWINwm->vmt->Redim(gh,x,y,w,h);
#else
static void _gwm_redraw(GHandle gh, int flags) {
if ((gh->flags & GWIN_FLG_VISIBLE)) {
if (gh->vmt->Redraw) {
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
gh->vmt->Redraw(gh);
} else if (!(flags & GWIN_WMFLG_PRESERVE))
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
if (gh->vmt->AfterClear)
gh->vmt->AfterClear(gh);
}
} else if (!(flags & GWIN_WMFLG_NOBGCLEAR)) {
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
gh->vmt->Redraw(gh);
} else
gwinClear(gh);
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, defaultBgColor);
}
}
static void _gwm_redim(GHandle gh, coord_t x, coord_t y, coord_t width, coord_t height) {
gh->x = x; gh->y = y;
@ -60,14 +76,7 @@ static color_t defaultBgColor = Black;
if (gh->y+gh->height > gdispGetHeight()) gh->height = gdispGetHeight() - gh->y;
// Redraw the window
if ((gh->flags & GWIN_FLG_VISIBLE)) {
if (gh->vmt->Redraw) {
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
gh->vmt->Redraw(gh);
}
}
_gwm_redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
}
#endif
@ -108,15 +117,15 @@ GHandle _gwindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit
pgw->font = defaultFont;
#endif
#if GWIN_NEED_WINDOWMANAGER
if (!_GWINwm->vmt->Add(pgw, pInit)) {
if ((pgw->flags & GWIN_FLG_DYNAMIC))
gfxFree(pgw);
return 0;
}
#else
_gwm_redim(pgw, pInit->x, pInit->y, pInit->width, pInit->height);
#endif
#if GWIN_NEED_WINDOWMANAGER
if (!_GWINwm->vmt->Add(pgw, pInit)) {
if ((pgw->flags & GWIN_FLG_DYNAMIC))
gfxFree(pgw);
return 0;
}
#else
_gwm_redim(pgw, pInit->x, pInit->y, pInit->width, pInit->height);
#endif
return (GHandle)pgw;
}
@ -163,6 +172,9 @@ GHandle gwinGWindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pI
}
void gwinDestroy(GHandle gh) {
// Make the window invisible
gwinSetVisible(gh, FALSE);
// Remove from the window manager
#if GWIN_NEED_WINDOWMANAGER
_GWINwm->vmt->Delete(gh);
@ -188,18 +200,12 @@ void gwinSetVisible(GHandle gh, bool_t visible) {
if (visible) {
if (!(gh->flags & GWIN_FLG_VISIBLE)) {
gh->flags |= GWIN_FLG_VISIBLE;
#if GWIN_NEED_WINDOWMANAGER
_GWINwm->vmt->Visible(gh);
#else
_gwm_vis(gh);
#endif
_gwm_redraw(gh, 0);
}
} else {
if ((gh->flags & GWIN_FLG_VISIBLE)) {
gh->flags &= ~GWIN_FLG_VISIBLE;
#if GWIN_NEED_WINDOWMANAGER
_GWINwm->vmt->Visible(gh);
#endif
_gwm_redraw(gh, 0);
}
}
}
@ -212,22 +218,12 @@ void gwinSetEnabled(GHandle gh, bool_t enabled) {
if (enabled) {
if (!(gh->flags & GWIN_FLG_ENABLED)) {
gh->flags |= GWIN_FLG_ENABLED;
if ((gh->flags & GWIN_FLG_VISIBLE) && gh->vmt->Redraw) {
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
gh->vmt->Redraw(gh);
}
_gwm_redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
}
} else {
if ((gh->flags & GWIN_FLG_ENABLED)) {
gh->flags &= ~GWIN_FLG_ENABLED;
if ((gh->flags & GWIN_FLG_VISIBLE) && gh->vmt->Redraw) {
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
gh->vmt->Redraw(gh);
}
_gwm_redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
}
}
}
@ -237,28 +233,15 @@ bool_t gwinGetEnabled(GHandle gh) {
}
void gwinMove(GHandle gh, coord_t x, coord_t y) {
#if GWIN_NEED_WINDOWMANAGER
_GWINwm->vmt->Redim(gh, x, y, gh->width, gh->height);
#else
_gwm_redim(gh, x, y, gh->width, gh->height);
#endif
_gwm_redim(gh, x, y, gh->width, gh->height);
}
void gwinResize(GHandle gh, coord_t width, coord_t height) {
#if GWIN_NEED_WINDOWMANAGER
_GWINwm->vmt->Redim(gh, gh->x, gh->y, width, height);
#else
_gwm_redim(gh, gh->x, gh->y, width, height);
#endif
_gwm_redim(gh, gh->x, gh->y, width, height);
}
void gwinRedraw(GHandle gh) {
#if GWIN_NEED_WINDOWMANAGER
gwinRaise(gh);
#else
if ((gh->flags & GWIN_FLG_VISIBLE))
_gwm_vis(gh);
#endif
_gwm_redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
}
#if GDISP_NEED_TEXT

View File

@ -27,7 +27,7 @@ static void WM_Init(void);
static void WM_DeInit(void);
static bool_t WM_Add(GHandle gh, const GWindowInit *pInit);
static void WM_Delete(GHandle gh);
static void WM_Visible(GHandle gh);
static void WM_Redraw(GHandle gh, int flags);
static void WM_Redim(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h);
static void WM_Raise(GHandle gh);
static void WM_MinMax(GHandle gh, GWindowMinMax minmax);
@ -37,7 +37,7 @@ static const gwmVMT GNullWindowManagerVMT = {
WM_DeInit,
WM_Add,
WM_Delete,
WM_Visible,
WM_Redraw,
WM_Redim,
WM_Raise,
WM_MinMax,
@ -86,6 +86,19 @@ GWindowMinMax gwinGetMinMax(GHandle gh) {
return GWIN_NORMAL;
}
void gwinRedrawDisplay(GDisplay *g, bool_t preserve) {
const gfxQueueASyncItem * qi;
GHandle gh;
for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
gh = QItem2GWindow(qi);
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));
}
}
/*-----------------------------------------------
* Window Manager Routines
*-----------------------------------------------*/
@ -116,28 +129,38 @@ static bool_t WM_Add(GHandle gh, const GWindowInit *pInit) {
}
static void WM_Delete(GHandle gh) {
// Make the window invisible and clear the area underneath
if ((gh->flags & GWIN_FLG_VISIBLE)) {
gh->flags &= ~GWIN_FLG_VISIBLE;
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor());
}
// Remove it from the queue
gfxQueueASyncRemove(&_GWINList, &gh->wmq);
}
static void WM_Visible(GHandle gh) {
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
static void WM_Redraw(GHandle gh, int flags) {
if ((gh->flags & GWIN_FLG_VISIBLE)) {
if (gh->vmt->Redraw)
if (gh->vmt->Redraw) {
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
gh->vmt->Redraw(gh);
else
} else if (!(flags & GWIN_WMFLG_PRESERVE)) {
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
if (gh->vmt->AfterClear)
gh->vmt->AfterClear(gh);
}
// A real window manager would also redraw the borders here
} else
// 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
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor());
}
}
static void WM_Redim(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h) {
@ -157,22 +180,19 @@ static void WM_Redim(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h) {
return;
// Clear the old area
if ((gh->flags & GWIN_FLG_VISIBLE))
if ((gh->flags & GWIN_FLG_VISIBLE)) {
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor());
}
// Set the new size
gh->x = x; gh->y = y;
gh->width = w; gh->height = h;
// Redraw the window (if possible)
if ((gh->flags & GWIN_FLG_VISIBLE)) {
if (gh->vmt->Redraw) {
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
gh->vmt->Redraw(gh);
}
}
WM_Redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
}
static void WM_MinMax(GHandle gh, GWindowMinMax minmax) {
@ -187,14 +207,7 @@ static void WM_Raise(GHandle gh) {
gfxQueueASyncPut(&_GWINList, &gh->wmq);
// Redraw the window
if ((gh->flags & GWIN_FLG_VISIBLE)) {
if (gh->vmt->Redraw) {
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
gh->vmt->Redraw(gh);
}
}
WM_Redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
}
#endif /* GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER */