GWIN: Make sure invisible windows are redrawn before visible windows.

Redrawing compile options made visible for the user project.
ugfx_release_2.6
inmarket 2014-05-22 09:35:36 +10:00
parent 1edc0a2d5a
commit bc3ebd6ae9
6 changed files with 123 additions and 78 deletions

View File

@ -4,6 +4,7 @@
*** Changes After 2.1 *** *** Changes After 2.1 ***
FEATURE: Added nested containers demo FEATURE: Added nested containers demo
FEATURE: Revised GWIN redraw strategy
*** Release 2.1 *** *** Release 2.1 ***

View File

@ -134,6 +134,8 @@
//#define GFX_USE_GWIN FALSE //#define GFX_USE_GWIN FALSE
//#define GWIN_NEED_WINDOWMANAGER FALSE //#define GWIN_NEED_WINDOWMANAGER FALSE
// #define GWIN_REDRAW_IMMEDIATE FALSE
// #define GWIN_REDRAW_SINGLEOP FALSE
//#define GWIN_NEED_CONSOLE FALSE //#define GWIN_NEED_CONSOLE FALSE
// #define GWIN_CONSOLE_USE_HISTORY FALSE // #define GWIN_CONSOLE_USE_HISTORY FALSE

View File

@ -194,6 +194,14 @@ GHandle _gwindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit
*/ */
void _gwinUpdate(GHandle gh); 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. * @brief Flush any pending redraws in the system.
* *
@ -209,7 +217,7 @@ void _gwinUpdate(GHandle gh);
* *
* @notapi * @notapi
*/ */
void _gwinFlushRedraws(bool_t doWait); void _gwinFlushRedraws(GRedrawMethod how);
/** /**
* @brief Obtain a drawing session * @brief Obtain a drawing session

View File

@ -36,8 +36,8 @@
return TRUE; return TRUE;
} }
void _gwinFlushRedraws(bool_t doWait) { void _gwinFlushRedraws(GRedrawMethod how) {
(void) doWait; (void) how;
// We are always flushed // We are always flushed
} }
@ -147,9 +147,6 @@
#if GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER #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" #include "src/gwin/class_gwin.h"
/*----------------------------------------------- /*-----------------------------------------------
@ -158,15 +155,18 @@
// The default window manager // The default window manager
extern const GWindowManager GNullWindowManager; extern const GWindowManager GNullWindowManager;
GWindowManager * _GWINwm; GWindowManager * _GWINwm;
static gfxSem gwinsem; static gfxSem gwinsem;
static gfxQueueASync _GWINList; static gfxQueueASync _GWINList;
static volatile bool_t RedrawPending; #if !GWIN_REDRAW_IMMEDIATE
#if GFX_USE_GTIMER static GTimer RedrawTimer;
static GTimer RedrawTimer; static void RedrawTimerFn(void *param);
static void RedrawTimerFn(void *param);
#endif #endif
static volatile uint8_t RedrawPending;
#define DOREDRAW_INVISIBLES 0x01
#define DOREDRAW_VISIBLES 0x02
/*----------------------------------------------- /*-----------------------------------------------
* Window Routines * Window Routines
@ -176,7 +176,7 @@ void _gwmInit(void)
{ {
gfxSemInit(&gwinsem, 1, 1); gfxSemInit(&gwinsem, 1, 1);
gfxQueueASyncInit(&_GWINList); gfxQueueASyncInit(&_GWINList);
#if GFX_USE_GTIMER #if !GWIN_REDRAW_IMMEDIATE
gtimerInit(&RedrawTimer); gtimerInit(&RedrawTimer);
gtimerStart(&RedrawTimer, RedrawTimerFn, 0, TRUE, TIME_INFINITE); gtimerStart(&RedrawTimer, RedrawTimerFn, 0, TRUE, TIME_INFINITE);
#endif #endif
@ -192,25 +192,25 @@ void _gwmDeinit(void)
gwinDestroy(gh); gwinDestroy(gh);
_GWINwm->vmt->DeInit(); _GWINwm->vmt->DeInit();
#if GFX_USE_GTIMER #if !GWIN_REDRAW_IMMEDIATE
gtimerDeinit(&RedrawTimer); gtimerDeinit(&RedrawTimer);
#endif #endif
gfxQueueASyncDeinit(&_GWINList); gfxQueueASyncDeinit(&_GWINList);
gfxSemDestroy(&gwinsem); gfxSemDestroy(&gwinsem);
} }
#if GFX_USE_GTIMER #if GWIN_REDRAW_IMMEDIATE
#define TriggerRedraw(void) _gwinFlushRedraws(REDRAW_NOWAIT);
#else
#define TriggerRedraw() gtimerJab(&RedrawTimer); #define TriggerRedraw() gtimerJab(&RedrawTimer);
static void RedrawTimerFn(void *param) { static void RedrawTimerFn(void *param) {
(void) param; (void) param;
_gwinFlushRedraws(FALSE); _gwinFlushRedraws(REDRAW_NOWAIT);
} }
#else
#define TriggerRedraw(void) _gwinFlushRedraws(FALSE);
#endif #endif
void _gwinFlushRedraws(bool_t doWait) { void _gwinFlushRedraws(GRedrawMethod how) {
GHandle gh; GHandle gh;
// Do we really need to do anything? // Do we really need to do anything?
@ -218,19 +218,46 @@ void _gwinFlushRedraws(bool_t doWait) {
return; return;
// Obtain the drawing lock // Obtain the drawing lock
if (doWait) if (how == REDRAW_WAIT)
gfxSemWait(&gwinsem, TIME_INFINITE); 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 // Someone is drawing - They will do the redraw when they are finished
return; return;
// Look for something to redraw // Do loss of visibility first
while(RedrawPending) { while ((RedrawPending & DOREDRAW_INVISIBLES)) {
// Catch any new redraw requests from here on RedrawPending &= ~DOREDRAW_INVISIBLES; // Catch new requests
RedrawPending = FALSE;
for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) { 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; continue;
// Do the redraw // Do the redraw
@ -243,23 +270,28 @@ void _gwinFlushRedraws(bool_t doWait) {
#endif #endif
// Postpone further redraws (if there are any and the options are set right) // Postpone further redraws (if there are any and the options are set right)
#if GFX_USE_GTIMER && !GWIN_LONG_REDRAW #if !GWIN_REDRAW_IMMEDIATE && !GWIN_REDRAW_SINGLEOP
if (!doWait) { if (how == REDRAW_NOWAIT) {
while((gh = gwinGetNextWindow(gh))) { while((gh = gwinGetNextWindow(gh))) {
if ((gh->flags & GWIN_FLG_NEEDREDRAW)) { if ((gh->flags & (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) {
gtimerJab(&RedrawTimer); RedrawPending |= DOREDRAW_VISIBLES;
RedrawPending = TRUE; TriggerRedraw();
break; break;
} }
} }
break; goto releaselock;
} }
#endif #endif
} }
} }
#if !GWIN_REDRAW_IMMEDIATE && !GWIN_REDRAW_SINGLEOP
releaselock:
#endif
// Release the lock // Release the lock
gfxSemSignal(&gwinsem); if (how == REDRAW_WAIT || how == REDRAW_NOWAIT)
gfxSemSignal(&gwinsem);
} }
void _gwinUpdate(GHandle gh) { void _gwinUpdate(GHandle gh) {
@ -269,7 +301,7 @@ void _gwinUpdate(GHandle gh) {
// Mark for redraw // Mark for redraw
gh->flags |= GWIN_FLG_NEEDREDRAW; gh->flags |= GWIN_FLG_NEEDREDRAW;
RedrawPending = TRUE; RedrawPending |= DOREDRAW_VISIBLES;
// Asynchronous redraw // Asynchronous redraw
TriggerRedraw(); TriggerRedraw();
@ -304,22 +336,7 @@ void _gwinDrawEnd(GHandle gh) {
#endif #endif
// Look for something to redraw // Look for something to redraw
while(RedrawPending) { _gwinFlushRedraws(REDRAW_INSESSION);
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
}
}
// Release the lock // Release the lock
gfxSemSignal(&gwinsem); gfxSemSignal(&gwinsem);
@ -365,10 +382,10 @@ void gwinRedraw(GHandle gh) {
// Mark for redraw // Mark for redraw
gh->flags |= GWIN_FLG_NEEDREDRAW; gh->flags |= GWIN_FLG_NEEDREDRAW;
RedrawPending = TRUE; RedrawPending |= DOREDRAW_VISIBLES;
// Synchronous redraw // Synchronous redraw
_gwinFlushRedraws(TRUE); _gwinFlushRedraws(REDRAW_WAIT);
} }
#if GWIN_NEED_CONTAINERS #if GWIN_NEED_CONTAINERS
@ -386,7 +403,7 @@ void gwinRedraw(GHandle gh) {
} }
// Mark for redraw // Mark for redraw
RedrawPending = TRUE; RedrawPending |= DOREDRAW_VISIBLES;
TriggerRedraw(); TriggerRedraw();
} }
} else { } else {
@ -404,7 +421,7 @@ void gwinRedraw(GHandle gh) {
} }
// Mark for redraw - no need to redraw children // Mark for redraw - no need to redraw children
RedrawPending = TRUE; RedrawPending |= DOREDRAW_INVISIBLES;
TriggerRedraw(); TriggerRedraw();
} }
} }
@ -414,14 +431,14 @@ void gwinRedraw(GHandle gh) {
if (visible) { if (visible) {
if (!(gh->flags & GWIN_FLG_VISIBLE)) { if (!(gh->flags & GWIN_FLG_VISIBLE)) {
gh->flags |= (GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE|GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW); gh->flags |= (GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE|GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW);
RedrawPending = TRUE; RedrawPending |= DOREDRAW_VISIBLES;
TriggerRedraw(); TriggerRedraw();
} }
} else { } else {
if ((gh->flags & GWIN_FLG_VISIBLE)) { if ((gh->flags & GWIN_FLG_VISIBLE)) {
gh->flags &= ~(GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE); gh->flags &= ~(GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE);
gh->flags |= (GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW); gh->flags |= (GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW);
RedrawPending = TRUE; RedrawPending |= DOREDRAW_INVISIBLES;
TriggerRedraw(); TriggerRedraw();
} }
} }
@ -441,14 +458,9 @@ void gwinRedraw(GHandle gh) {
for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(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))) { 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 gh->flags |= GWIN_FLG_SYSENABLED; // Fix it
if ((gh->flags & GWIN_FLG_SYSVISIBLE)) { // Mark for redraw _gwinUpdate(gh);
gh->flags |= GWIN_FLG_NEEDREDRAW;
RedrawPending = TRUE;
}
} }
} }
if (RedrawPending)
TriggerRedraw();
} }
} else { } else {
gh->flags &= ~GWIN_FLG_ENABLED; gh->flags &= ~GWIN_FLG_ENABLED;
@ -459,14 +471,9 @@ void gwinRedraw(GHandle gh) {
for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(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)))) { 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 gh->flags &= ~GWIN_FLG_SYSENABLED; // Fix it
if ((gh->flags & GWIN_FLG_SYSVISIBLE)) { // Mark for redraw _gwinUpdate(gh);
gh->flags |= GWIN_FLG_NEEDREDRAW;
RedrawPending = TRUE;
}
} }
} }
if (RedrawPending)
TriggerRedraw();
} }
} }
} }
@ -701,7 +708,7 @@ static void WM_Size(GHandle gh, coord_t w, coord_t h) {
} else { } else {
// We need to make this window invisible and ensure that has been drawn // We need to make this window invisible and ensure that has been drawn
gwinSetVisible(gh, FALSE); gwinSetVisible(gh, FALSE);
_gwinFlushRedraws(TRUE); _gwinFlushRedraws(REDRAW_WAIT);
// Resize // Resize
gh->width = w; gh->height = h; 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)) { if ((gh->flags & GWIN_FLG_SYSVISIBLE)) {
// We need to make this window invisible and ensure that has been drawn // We need to make this window invisible and ensure that has been drawn
gwinSetVisible(gh, FALSE); gwinSetVisible(gh, FALSE);
_gwinFlushRedraws(TRUE); _gwinFlushRedraws(REDRAW_WAIT);
// Do the move // Do the move
v = gh->x; gh->x = x; x = v; v = gh->x; gh->x = x; x = v;

View File

@ -136,6 +136,33 @@
#ifndef GWIN_FLAT_STYLING #ifndef GWIN_FLAT_STYLING
#define GWIN_FLAT_STYLING FALSE #define GWIN_FLAT_STYLING FALSE
#endif #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 * @brief Buttons should not insist the mouse is over the button on mouse release
* @details Defaults to FALSE * @details Defaults to FALSE

View File

@ -91,6 +91,13 @@
#define GFX_USE_GQUEUE TRUE #define GFX_USE_GQUEUE TRUE
#define GQUEUE_NEED_ASYNC TRUE #define GQUEUE_NEED_ASYNC TRUE
#endif #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 #endif
// Rules for individual objects // Rules for individual objects
@ -116,13 +123,6 @@
#error "GWIN: GDISP_NEED_TEXT is required if GWIN_NEED_CONSOLE is TRUE." #error "GWIN: GDISP_NEED_TEXT is required if GWIN_NEED_CONSOLE is TRUE."
#endif #endif
#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
#endif /* _GWIN_RULES_H */ #endif /* _GWIN_RULES_H */