GWIN: Make sure invisible windows are redrawn before visible windows.
Redrawing compile options made visible for the user project.
This commit is contained in:
parent
1edc0a2d5a
commit
bc3ebd6ae9
@ -4,6 +4,7 @@
|
||||
|
||||
*** Changes After 2.1 ***
|
||||
FEATURE: Added nested containers demo
|
||||
FEATURE: Revised GWIN redraw strategy
|
||||
|
||||
|
||||
*** Release 2.1 ***
|
||||
|
@ -134,6 +134,8 @@
|
||||
//#define GFX_USE_GWIN FALSE
|
||||
|
||||
//#define GWIN_NEED_WINDOWMANAGER FALSE
|
||||
// #define GWIN_REDRAW_IMMEDIATE FALSE
|
||||
// #define GWIN_REDRAW_SINGLEOP FALSE
|
||||
|
||||
//#define GWIN_NEED_CONSOLE FALSE
|
||||
// #define GWIN_CONSOLE_USE_HISTORY FALSE
|
||||
|
@ -194,6 +194,14 @@ GHandle _gwindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit
|
||||
*/
|
||||
void _gwinUpdate(GHandle gh);
|
||||
|
||||
/**
|
||||
* @brief How to flush the redraws
|
||||
* @notes REDRAW_WAIT - Wait for a drawing session to be available
|
||||
* @notes REDRAW_NOWAIT - Do nothing if the drawing session is not available
|
||||
* @note REDRAW_INSESSION - We are already in a drawing session
|
||||
*/
|
||||
typedef enum GRedrawMethod { REDRAW_WAIT, REDRAW_NOWAIT, REDRAW_INSESSION } GRedrawMethod;
|
||||
|
||||
/**
|
||||
* @brief Flush any pending redraws in the system.
|
||||
*
|
||||
@ -209,7 +217,7 @@ void _gwinUpdate(GHandle gh);
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void _gwinFlushRedraws(bool_t doWait);
|
||||
void _gwinFlushRedraws(GRedrawMethod how);
|
||||
|
||||
/**
|
||||
* @brief Obtain a drawing session
|
||||
|
147
src/gwin/gwm.c
147
src/gwin/gwm.c
@ -36,8 +36,8 @@
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void _gwinFlushRedraws(bool_t doWait) {
|
||||
(void) doWait;
|
||||
void _gwinFlushRedraws(GRedrawMethod how) {
|
||||
(void) how;
|
||||
|
||||
// We are always flushed
|
||||
}
|
||||
@ -147,9 +147,6 @@
|
||||
|
||||
#if GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER
|
||||
|
||||
// Do we redraw all windows at once?
|
||||
#define GWIN_LONG_REDRAW TRUE
|
||||
|
||||
#include "src/gwin/class_gwin.h"
|
||||
|
||||
/*-----------------------------------------------
|
||||
@ -158,15 +155,18 @@
|
||||
|
||||
// The default window manager
|
||||
extern const GWindowManager GNullWindowManager;
|
||||
GWindowManager * _GWINwm;
|
||||
GWindowManager * _GWINwm;
|
||||
|
||||
static gfxSem gwinsem;
|
||||
static gfxQueueASync _GWINList;
|
||||
static volatile bool_t RedrawPending;
|
||||
#if GFX_USE_GTIMER
|
||||
static GTimer RedrawTimer;
|
||||
static void RedrawTimerFn(void *param);
|
||||
static gfxSem gwinsem;
|
||||
static gfxQueueASync _GWINList;
|
||||
#if !GWIN_REDRAW_IMMEDIATE
|
||||
static GTimer RedrawTimer;
|
||||
static void RedrawTimerFn(void *param);
|
||||
#endif
|
||||
static volatile uint8_t RedrawPending;
|
||||
#define DOREDRAW_INVISIBLES 0x01
|
||||
#define DOREDRAW_VISIBLES 0x02
|
||||
|
||||
|
||||
/*-----------------------------------------------
|
||||
* Window Routines
|
||||
@ -176,7 +176,7 @@ void _gwmInit(void)
|
||||
{
|
||||
gfxSemInit(&gwinsem, 1, 1);
|
||||
gfxQueueASyncInit(&_GWINList);
|
||||
#if GFX_USE_GTIMER
|
||||
#if !GWIN_REDRAW_IMMEDIATE
|
||||
gtimerInit(&RedrawTimer);
|
||||
gtimerStart(&RedrawTimer, RedrawTimerFn, 0, TRUE, TIME_INFINITE);
|
||||
#endif
|
||||
@ -192,25 +192,25 @@ void _gwmDeinit(void)
|
||||
gwinDestroy(gh);
|
||||
|
||||
_GWINwm->vmt->DeInit();
|
||||
#if GFX_USE_GTIMER
|
||||
#if !GWIN_REDRAW_IMMEDIATE
|
||||
gtimerDeinit(&RedrawTimer);
|
||||
#endif
|
||||
gfxQueueASyncDeinit(&_GWINList);
|
||||
gfxSemDestroy(&gwinsem);
|
||||
}
|
||||
|
||||
#if GFX_USE_GTIMER
|
||||
#if GWIN_REDRAW_IMMEDIATE
|
||||
#define TriggerRedraw(void) _gwinFlushRedraws(REDRAW_NOWAIT);
|
||||
#else
|
||||
#define TriggerRedraw() gtimerJab(&RedrawTimer);
|
||||
|
||||
static void RedrawTimerFn(void *param) {
|
||||
(void) param;
|
||||
_gwinFlushRedraws(FALSE);
|
||||
_gwinFlushRedraws(REDRAW_NOWAIT);
|
||||
}
|
||||
#else
|
||||
#define TriggerRedraw(void) _gwinFlushRedraws(FALSE);
|
||||
#endif
|
||||
|
||||
void _gwinFlushRedraws(bool_t doWait) {
|
||||
void _gwinFlushRedraws(GRedrawMethod how) {
|
||||
GHandle gh;
|
||||
|
||||
// Do we really need to do anything?
|
||||
@ -218,19 +218,46 @@ void _gwinFlushRedraws(bool_t doWait) {
|
||||
return;
|
||||
|
||||
// Obtain the drawing lock
|
||||
if (doWait)
|
||||
if (how == REDRAW_WAIT)
|
||||
gfxSemWait(&gwinsem, TIME_INFINITE);
|
||||
else if (!gfxSemWait(&gwinsem, TIME_IMMEDIATE))
|
||||
else if (how == REDRAW_NOWAIT && !gfxSemWait(&gwinsem, TIME_IMMEDIATE))
|
||||
// Someone is drawing - They will do the redraw when they are finished
|
||||
return;
|
||||
|
||||
// Look for something to redraw
|
||||
while(RedrawPending) {
|
||||
// Catch any new redraw requests from here on
|
||||
RedrawPending = FALSE;
|
||||
// Do loss of visibility first
|
||||
while ((RedrawPending & DOREDRAW_INVISIBLES)) {
|
||||
RedrawPending &= ~DOREDRAW_INVISIBLES; // Catch new requests
|
||||
|
||||
for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
|
||||
if (!(gh->flags & GWIN_FLG_NEEDREDRAW))
|
||||
if ((gh->flags & (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) != GWIN_FLG_NEEDREDRAW)
|
||||
continue;
|
||||
|
||||
// Do the redraw
|
||||
#if GDISP_NEED_CLIP
|
||||
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
|
||||
_GWINwm->vmt->Redraw(gh);
|
||||
gdispGUnsetClip(gh->display);
|
||||
#else
|
||||
_GWINwm->vmt->Redraw(gh);
|
||||
#endif
|
||||
|
||||
// Postpone further redraws
|
||||
#if !GWIN_REDRAW_IMMEDIATE && !GWIN_REDRAW_SINGLEOP
|
||||
if (how == REDRAW_NOWAIT) {
|
||||
RedrawPending |= DOREDRAW_INVISIBLES;
|
||||
TriggerRedraw();
|
||||
goto releaselock;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Do the visible windows next
|
||||
while ((RedrawPending & DOREDRAW_VISIBLES)) {
|
||||
RedrawPending &= ~DOREDRAW_VISIBLES; // Catch new requests
|
||||
|
||||
for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
|
||||
if ((gh->flags & (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) != (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE))
|
||||
continue;
|
||||
|
||||
// Do the redraw
|
||||
@ -243,23 +270,28 @@ void _gwinFlushRedraws(bool_t doWait) {
|
||||
#endif
|
||||
|
||||
// Postpone further redraws (if there are any and the options are set right)
|
||||
#if GFX_USE_GTIMER && !GWIN_LONG_REDRAW
|
||||
if (!doWait) {
|
||||
#if !GWIN_REDRAW_IMMEDIATE && !GWIN_REDRAW_SINGLEOP
|
||||
if (how == REDRAW_NOWAIT) {
|
||||
while((gh = gwinGetNextWindow(gh))) {
|
||||
if ((gh->flags & GWIN_FLG_NEEDREDRAW)) {
|
||||
gtimerJab(&RedrawTimer);
|
||||
RedrawPending = TRUE;
|
||||
if ((gh->flags & (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) {
|
||||
RedrawPending |= DOREDRAW_VISIBLES;
|
||||
TriggerRedraw();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
goto releaselock;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if !GWIN_REDRAW_IMMEDIATE && !GWIN_REDRAW_SINGLEOP
|
||||
releaselock:
|
||||
#endif
|
||||
|
||||
// Release the lock
|
||||
gfxSemSignal(&gwinsem);
|
||||
if (how == REDRAW_WAIT || how == REDRAW_NOWAIT)
|
||||
gfxSemSignal(&gwinsem);
|
||||
}
|
||||
|
||||
void _gwinUpdate(GHandle gh) {
|
||||
@ -269,7 +301,7 @@ void _gwinUpdate(GHandle gh) {
|
||||
|
||||
// Mark for redraw
|
||||
gh->flags |= GWIN_FLG_NEEDREDRAW;
|
||||
RedrawPending = TRUE;
|
||||
RedrawPending |= DOREDRAW_VISIBLES;
|
||||
|
||||
// Asynchronous redraw
|
||||
TriggerRedraw();
|
||||
@ -304,22 +336,7 @@ void _gwinDrawEnd(GHandle gh) {
|
||||
#endif
|
||||
|
||||
// Look for something to redraw
|
||||
while(RedrawPending) {
|
||||
RedrawPending = FALSE;
|
||||
for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
|
||||
if (!(gh->flags & GWIN_FLG_NEEDREDRAW))
|
||||
continue;
|
||||
|
||||
// Do the redraw
|
||||
#if GDISP_NEED_CLIP
|
||||
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
|
||||
_GWINwm->vmt->Redraw(gh);
|
||||
gdispGUnsetClip(gh->display);
|
||||
#else
|
||||
_GWINwm->vmt->Redraw(gh);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
_gwinFlushRedraws(REDRAW_INSESSION);
|
||||
|
||||
// Release the lock
|
||||
gfxSemSignal(&gwinsem);
|
||||
@ -365,10 +382,10 @@ void gwinRedraw(GHandle gh) {
|
||||
|
||||
// Mark for redraw
|
||||
gh->flags |= GWIN_FLG_NEEDREDRAW;
|
||||
RedrawPending = TRUE;
|
||||
RedrawPending |= DOREDRAW_VISIBLES;
|
||||
|
||||
// Synchronous redraw
|
||||
_gwinFlushRedraws(TRUE);
|
||||
_gwinFlushRedraws(REDRAW_WAIT);
|
||||
}
|
||||
|
||||
#if GWIN_NEED_CONTAINERS
|
||||
@ -386,7 +403,7 @@ void gwinRedraw(GHandle gh) {
|
||||
}
|
||||
|
||||
// Mark for redraw
|
||||
RedrawPending = TRUE;
|
||||
RedrawPending |= DOREDRAW_VISIBLES;
|
||||
TriggerRedraw();
|
||||
}
|
||||
} else {
|
||||
@ -404,7 +421,7 @@ void gwinRedraw(GHandle gh) {
|
||||
}
|
||||
|
||||
// Mark for redraw - no need to redraw children
|
||||
RedrawPending = TRUE;
|
||||
RedrawPending |= DOREDRAW_INVISIBLES;
|
||||
TriggerRedraw();
|
||||
}
|
||||
}
|
||||
@ -414,14 +431,14 @@ void gwinRedraw(GHandle gh) {
|
||||
if (visible) {
|
||||
if (!(gh->flags & GWIN_FLG_VISIBLE)) {
|
||||
gh->flags |= (GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE|GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW);
|
||||
RedrawPending = TRUE;
|
||||
RedrawPending |= DOREDRAW_VISIBLES;
|
||||
TriggerRedraw();
|
||||
}
|
||||
} else {
|
||||
if ((gh->flags & GWIN_FLG_VISIBLE)) {
|
||||
gh->flags &= ~(GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE);
|
||||
gh->flags |= (GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW);
|
||||
RedrawPending = TRUE;
|
||||
RedrawPending |= DOREDRAW_INVISIBLES;
|
||||
TriggerRedraw();
|
||||
}
|
||||
}
|
||||
@ -441,14 +458,9 @@ void gwinRedraw(GHandle gh) {
|
||||
for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
|
||||
if ((gh->flags & (GWIN_FLG_SYSENABLED|GWIN_FLG_ENABLED)) == GWIN_FLG_ENABLED && (!gh->parent || (gh->parent->flags & GWIN_FLG_SYSENABLED))) {
|
||||
gh->flags |= GWIN_FLG_SYSENABLED; // Fix it
|
||||
if ((gh->flags & GWIN_FLG_SYSVISIBLE)) { // Mark for redraw
|
||||
gh->flags |= GWIN_FLG_NEEDREDRAW;
|
||||
RedrawPending = TRUE;
|
||||
}
|
||||
_gwinUpdate(gh);
|
||||
}
|
||||
}
|
||||
if (RedrawPending)
|
||||
TriggerRedraw();
|
||||
}
|
||||
} else {
|
||||
gh->flags &= ~GWIN_FLG_ENABLED;
|
||||
@ -459,14 +471,9 @@ void gwinRedraw(GHandle gh) {
|
||||
for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
|
||||
if ((gh->flags & GWIN_FLG_SYSENABLED) && (!(gh->flags & GWIN_FLG_ENABLED) || (gh->parent && !(gh->parent->flags & GWIN_FLG_SYSENABLED)))) {
|
||||
gh->flags &= ~GWIN_FLG_SYSENABLED; // Fix it
|
||||
if ((gh->flags & GWIN_FLG_SYSVISIBLE)) { // Mark for redraw
|
||||
gh->flags |= GWIN_FLG_NEEDREDRAW;
|
||||
RedrawPending = TRUE;
|
||||
}
|
||||
_gwinUpdate(gh);
|
||||
}
|
||||
}
|
||||
if (RedrawPending)
|
||||
TriggerRedraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -701,7 +708,7 @@ static void WM_Size(GHandle gh, coord_t w, coord_t h) {
|
||||
} else {
|
||||
// We need to make this window invisible and ensure that has been drawn
|
||||
gwinSetVisible(gh, FALSE);
|
||||
_gwinFlushRedraws(TRUE);
|
||||
_gwinFlushRedraws(REDRAW_WAIT);
|
||||
|
||||
// Resize
|
||||
gh->width = w; gh->height = h;
|
||||
@ -771,7 +778,7 @@ static void WM_Move(GHandle gh, coord_t x, coord_t y) {
|
||||
if ((gh->flags & GWIN_FLG_SYSVISIBLE)) {
|
||||
// We need to make this window invisible and ensure that has been drawn
|
||||
gwinSetVisible(gh, FALSE);
|
||||
_gwinFlushRedraws(TRUE);
|
||||
_gwinFlushRedraws(REDRAW_WAIT);
|
||||
|
||||
// Do the move
|
||||
v = gh->x; gh->x = x; x = v;
|
||||
|
@ -136,6 +136,33 @@
|
||||
#ifndef GWIN_FLAT_STYLING
|
||||
#define GWIN_FLAT_STYLING FALSE
|
||||
#endif
|
||||
/**
|
||||
* @brief Don't use a timer for redrawing windows
|
||||
* @details Defaults to FALSE
|
||||
* @note Normally windows and widgets are redrawn on a timer. Setting this
|
||||
* option causes them to be redrawn immediately. Note that this can
|
||||
* cause extended blocking times on events and saves little code.
|
||||
* @note If GWIN_NEED_WINDOWMANAGER is FALSE then this setting is ignored
|
||||
* as redrawing always occurs immediately.
|
||||
*/
|
||||
#ifndef GWIN_REDRAW_IMMEDIATE
|
||||
#define GWIN_REDRAW_IMMEDIATE FALSE
|
||||
#endif
|
||||
/**
|
||||
* @brief Redraw all windows in a single operation
|
||||
* @details Defaults to FALSE
|
||||
* @note Windows are normally redraw one per gtimer cycle.
|
||||
* Setting this option causes all windows to be redrawn in
|
||||
* a single gtimer cycle. Note that this can
|
||||
* cause extended blocking times on the timer thread but may
|
||||
* speed up redraw slightly.
|
||||
* @note This is only relevant if GWIN_REDRAW_IMMEDIATE is FALSE.
|
||||
* Everything always gets redrawn in a single operation if
|
||||
* GWIN_REDRAW_IMMEDIATE is TRUE.
|
||||
*/
|
||||
#ifndef GWIN_REDRAW_SINGLEOP
|
||||
#define GWIN_REDRAW_SINGLEOP FALSE
|
||||
#endif
|
||||
/**
|
||||
* @brief Buttons should not insist the mouse is over the button on mouse release
|
||||
* @details Defaults to FALSE
|
||||
|
@ -91,6 +91,13 @@
|
||||
#define GFX_USE_GQUEUE TRUE
|
||||
#define GQUEUE_NEED_ASYNC TRUE
|
||||
#endif
|
||||
#if !GFX_USE_GTIMER
|
||||
#if GFX_DISPLAY_RULE_WARNINGS
|
||||
#warning "GWIN: GFX_USE_GTIMER is required if GWIN_NEED_WINDOWMANAGER is TRUE. It has been turned on for you."
|
||||
#endif
|
||||
#undef GFX_USE_GTIMER
|
||||
#define GFX_USE_GTIMER TRUE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Rules for individual objects
|
||||
@ -116,13 +123,6 @@
|
||||
#error "GWIN: GDISP_NEED_TEXT is required if GWIN_NEED_CONSOLE is TRUE."
|
||||
#endif
|
||||
#endif
|
||||
#if GWIN_NEED_PROGRESSBAR
|
||||
#if GWIN_PROGRESSBAR_AUTO
|
||||
#if !GFX_USE_GTIMER
|
||||
#error "GWIN: GFX_USE_GTIMER is required if GWIN_PROGRESSBAR_AUTO is TRUE."
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* _GWIN_RULES_H */
|
||||
|
Loading…
Reference in New Issue
Block a user