Significant changes to the window redrawing methodology.

Move and Resize should probably work for containers now
Still to be tested - nested containers, progressbar timers while redrawing its container, move/resize on containers.
ugfx_release_2.6
inmarket 2014-05-21 13:02:00 +10:00
parent 7afe4e78b7
commit 34e23320b4
14 changed files with 834 additions and 638 deletions

View File

@ -50,14 +50,14 @@ static void SendButtonEvent(GWidgetObject *gw) {
static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y) {
(void) x; (void) y;
gw->g.flags |= GBUTTON_FLG_PRESSED;
_gwidgetUpdate((GHandle)gw);
_gwinUpdate((GHandle)gw);
}
// A mouse up has occurred (it may or may not be over the button)
static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y) {
(void) x; (void) y;
gw->g.flags &= ~GBUTTON_FLG_PRESSED;
_gwidgetUpdate((GHandle)gw);
_gwinUpdate((GHandle)gw);
#if !GWIN_BUTTON_LAZY_RELEASE
// If the mouse up was not over the button then cancel the event
@ -74,14 +74,14 @@ static void SendButtonEvent(GWidgetObject *gw) {
static void ToggleOff(GWidgetObject *gw, uint16_t role) {
(void) role;
gw->g.flags &= ~GBUTTON_FLG_PRESSED;
_gwidgetUpdate((GHandle)gw);
_gwinUpdate((GHandle)gw);
}
// A toggle on has occurred
static void ToggleOn(GWidgetObject *gw, uint16_t role) {
(void) role;
gw->g.flags |= GBUTTON_FLG_PRESSED;
_gwidgetUpdate((GHandle)gw);
_gwinUpdate((GHandle)gw);
// Trigger the event on button down (different than for mouse/touch)
SendButtonEvent(gw);
}

View File

@ -43,7 +43,7 @@ static void SendCheckboxEvent(GWidgetObject *gw) {
static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y) {
(void) x; (void) y;
gw->g.flags ^= GCHECKBOX_FLG_CHECKED;
_gwidgetUpdate((GHandle)gw);
_gwinUpdate((GHandle)gw);
SendCheckboxEvent(gw);
}
#endif
@ -52,7 +52,7 @@ static void SendCheckboxEvent(GWidgetObject *gw) {
static void ToggleOn(GWidgetObject *gw, uint16_t role) {
(void) role;
gw->g.flags ^= GCHECKBOX_FLG_CHECKED;
_gwidgetUpdate((GHandle)gw);
_gwinUpdate((GHandle)gw);
SendCheckboxEvent(gw);
}
@ -125,7 +125,7 @@ void gwinCheckboxCheck(GHandle gh, bool_t isChecked) {
if (!(gh->flags & GCHECKBOX_FLG_CHECKED)) return;
gh->flags &= ~GCHECKBOX_FLG_CHECKED;
}
_gwidgetUpdate(gh);
_gwinUpdate(gh);
SendCheckboxEvent((GWidgetObject *)gh);
}

View File

@ -34,12 +34,14 @@
#define GWIN_FLG_SYSENABLED 0x00000800 // @< The window is enabled after parents are tested
#define GWIN_FLG_DYNAMIC 0x00001000 // @< The GWIN structure is allocated
#define GWIN_FLG_ALLOCTXT 0x00002000 // @< The text/label is allocated
#define GWIN_FLG_MOUSECAPTURE 0x00004000 // @< The window has captured the mouse
#define GWIN_FLG_NEEDREDRAW 0x00004000 // @< Redraw is needed but has been delayed
#define GWIN_FLG_BGREDRAW 0x00008000 // @< On redraw, if not visible redraw the revealed under-side
#define GWIN_FLG_SUPERMASK 0x000F0000 // @< The bit mask to leave just the window superclass type
#define GWIN_FLG_WIDGET 0x00010000 // @< This is a widget
#define GWIN_FLG_CONTAINER 0x00020000 // @< This is a container
#define GWIN_FLG_MINIMIZED 0x00100000 // @< The window is minimized
#define GWIN_FLG_MAXIMIZED 0x00200000 // @< The window is maximized
#define GWIN_FLG_MOUSECAPTURE 0x00400000 // @< The window has captured the mouse
#define GWIN_FIRST_WM_FLAG 0x01000000 // @< 8 bits free for the window manager to use
/** @} */
@ -131,17 +133,6 @@ 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_KEEPCLIP 0x0004 // @< Don't modify the preset clipping area
#define GWIN_WMFLG_NOZORDER 0x0008 // @< Don't redraw higher z-order windows that overlap
/** @} */
#if GWIN_NEED_WINDOWMANAGER || defined(__DOXYGEN__)
// @note There is only ever one instance of each GWindowManager type
typedef struct GWindowManager {
@ -157,7 +148,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 (*Redraw) (GHandle gh, int visflags); // @< A window needs to be redraw (or undrawn)
void (*Redraw) (GHandle gh); // @< A window needs to be redraw (or undrawn)
void (*Size) (GHandle gh, coord_t w, coord_t h); // @< A window wants to be resized
void (*Move) (GHandle gh, coord_t x, coord_t y); // @< A window wants to be moved
void (*Raise) (GHandle gh); // @< A window wants to be on top
@ -190,6 +181,62 @@ extern "C" {
*/
GHandle _gwindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit, const gwinVMT *vmt, uint32_t flags);
/**
* @brief Redraw the window after a status change.
*
* @param[in] gh The widget to redraw
*
* @note Mark a window for redraw.
* @note The window will get redrawn at some later time.
* @note This call is designed to be fast and non-blocking
*
* @notapi
*/
void _gwinUpdate(GHandle gh);
/**
* @brief Flush any pending redraws in the system.
*
* @param[in] doWait Do we wait for the lock?
*
* @note This call will attempt to flush any pending redraws
* in the system. The doWait parameter tells this call
* how to handle someone already holding the drawing lock.
* If doWait is TRUE it waits to obtain the lock. If FALSE
* and the drawing lock is free then the redraw is done
* immediately. If the drawing lock was taken it will postpone the flush
* on the basis that someone else will do it for us later.
*
* @notapi
*/
void _gwinFlushRedraws(bool_t doWait);
/**
* @brief Obtain a drawing session
* @return TRUE if the drawing session was obtained, FALSE if the window is not visible
*
* @param[in] gh The window
*
* @note This function blocks until a drawing session is available if the window is visible
*/
bool_t _gwinDrawStart(GHandle gh);
/**
* @brief Release a drawing session
*
* @param[in] gh The window
*/
void _gwinDrawEnd(GHandle gh);
/**
* @brief Add a window to the window manager and set its position and size
* @return TRUE if successful
*
* @param[in] gh The window
* @param[in] pInit The window init structure
*/
bool_t _gwinWMAdd(GHandle gh, const GWindowInit *pInit);
#if GWIN_NEED_WIDGET || defined(__DOXYGEN__)
/**
* @brief Initialise (and allocate if necessary) the base Widget object
@ -220,24 +267,12 @@ GHandle _gwindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit
* @param[in] gh The widget to redraw
*
* @note Do not use this routine to update a widget after a status change.
* Use @p _gwidgetUpdate() instead. The difference is that this routine
* does not set the clip region. This routine should only be used in the
* Use @p _gwinUpdate() instead. This routine should only be used in the
* VMT.
*
* @notapi
*/
void _gwidgetRedraw(GHandle gh);
/**
* @brief Redraw the Widget object after a widget status change.
*
* @param[in] gh The widget to redraw
*
* @note Use this routine to update a widget after a status change.
*
* @notapi
*/
void _gwidgetUpdate(GHandle gh);
#endif
#if GWIN_NEED_CONTAINERS || defined(__DOXYGEN__)
@ -270,38 +305,12 @@ GHandle _gwindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit
* @param[in] gh The container to redraw
*
* @note Do not use this routine to update a container after a status change.
* Use @p _gcontainerUpdate() instead. The difference is that this routine
* does not set the clip region. This routine should only be used in the
* Use @p _gwinUpdate() instead. This routine should only be used in the
* VMT.
*
* @notapi
*/
void _gcontainerRedraw(GHandle gh);
/**
* @brief Redraw the Container object after a container status change.
*
* @param[in] gh The container to redraw
*
* @note Use this routine to update a container after a status change.
*
* @notapi
*/
void _gcontainerUpdate(GHandle gh);
/**
* @brief Apply the specified action to a window and its children.
* @note The action is applied to the parent first and then its children.
* @note This routine is built to keep stack usage from recursing to a minimum.
*
* @param[in] gh The window to recurse through
* @param[in] fn The function to apply. If it returns TRUE any children it has should also have the function applied
*
* @notapi
*/
void _gwinRecurse(GHandle gh, bool_t (*fn)(GHandle gh));
#else
#define _gwinRecurse(gh, fn) fn(gh)
#define _gcontainerRedraw _gwidgetRedraw
#endif
#ifdef __cplusplus

View File

@ -399,6 +399,18 @@ GHandle gwinGConsoleCreate(GDisplay *g, GConsoleObject *gc, const GWindowInit *p
}
#endif
/*
* We can get into gwinPutChar() 2 ways -
* 1. when the user calls us, and
* 2. when the redraw uses us to redraw the display.
* When called by option 2 we MUST not try to obtain a draw session
* as we already have one.
*
* We use these macro's below to make sure we do that safely
*/
#define DrawStart(gh) ((gh->flags & GCONSOLE_FLG_NOSTORE) || _gwinDrawStart(gh))
#define DrawEnd(gh) { if (!(gh->flags & GCONSOLE_FLG_NOSTORE)) _gwinDrawEnd(gh); }
void gwinPutChar(GHandle gh, char c) {
#define gcw ((GConsoleObject *)gh)
uint8_t width, fy;
@ -406,16 +418,8 @@ void gwinPutChar(GHandle gh, char c) {
if (gh->vmt != &consoleVMT || !gh->font)
return;
// only render new character if the console is visible
if (!gwinGetVisible(gh))
return;
fy = gdispGetFontMetric(gh->font, fontHeight);
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
#if GWIN_CONSOLE_ESCSEQ
/**
* Handle escape sequences
@ -444,7 +448,10 @@ void gwinPutChar(GHandle gh, char c) {
case 'J':
// Clear the console and reset the cursor
clearBuffer(gcw);
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
if (DrawStart(gh)) {
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
DrawEnd(gh);
}
gcw->cx = 0;
gcw->cy = 0;
gcw->startattr = gcw->currattr;
@ -469,8 +476,10 @@ void gwinPutChar(GHandle gh, char c) {
case '\n':
// clear to the end of the line
#if GWIN_CONSOLE_USE_CLEAR_LINES
if (gcw->cx == 0 && gcw->cy+fy < gh->height)
if (gcw->cx == 0 && gcw->cy+fy < gh->height && DrawStart(gh)) {
gdispGFillArea(gh->display, gh->x, gh->y + gcw->cy, gh->width, fy, gh->bgcolor);
DrawEnd(gh);
}
#endif
// update the cursor
gcw->cx = 0;
@ -513,14 +522,20 @@ void gwinPutChar(GHandle gh, char c) {
if (gcw->buffer) {
// Scroll the buffer and then redraw using the buffer
scrollBuffer(gcw);
HistoryRedraw(gh);
if (DrawStart(gh)) {
HistoryRedraw(gh);
DrawEnd(gh);
}
} else
#endif
#if GDISP_NEED_SCROLL
{
// Scroll the console using hardware
scrollBuffer(gcw);
gdispGVerticalScroll(gh->display, gh->x, gh->y, gh->width, gh->height, fy, gh->bgcolor);
if (DrawStart(gh)) {
gdispGVerticalScroll(gh->display, gh->x, gh->y, gh->width, gh->height, fy, gh->bgcolor);
DrawEnd(gh);
}
// Set the cursor to the start of the last line
gcw->cx = 0;
@ -530,7 +545,10 @@ void gwinPutChar(GHandle gh, char c) {
{
// Clear the console and reset the cursor
clearBuffer(gcw);
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
if (DrawStart(gh)) {
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
DrawEnd(gh);
}
gcw->cx = 0;
gcw->cy = 0;
#if GWIN_CONSOLE_ESCSEQ
@ -540,30 +558,37 @@ void gwinPutChar(GHandle gh, char c) {
#endif
}
// If we are at the beginning of a new line clear the line
#if GWIN_CONSOLE_USE_CLEAR_LINES
if (gcw->cx == 0)
gdispGFillArea(gh->display, gh->x, gh->y + gcw->cy, gh->width, fy, gh->bgcolor);
#endif
// Draw the character
#if GWIN_CONSOLE_USE_FILLED_CHARS
gdispGFillChar(gh->display, gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, ESCPrintColor(gcw), gh->bgcolor);
#else
gdispGDrawChar(gh->display, gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, ESCPrintColor(gcw));
#endif
// Save the char
putCharInBuffer(gcw, c);
#if GWIN_CONSOLE_ESCSEQ
// Draw the underline
if ((gcw->currattr & ESC_UNDERLINE))
gdispGDrawLine(gh->display, gh->x + gcw->cx, gh->y + gcw->cy + fy - gdispGetFontMetric(gh->font, fontDescendersHeight),
gh->x + gcw->cx + width + gdispGetFontMetric(gh->font, fontCharPadding), gh->y + gcw->cy + fy - gdispGetFontMetric(gh->font, fontDescendersHeight),
ESCPrintColor(gcw));
// Bold (very crude)
if ((gcw->currattr & ESC_BOLD))
gdispGDrawChar(gh->display, gh->x + gcw->cx + 1, gh->y + gcw->cy, c, gh->font, ESCPrintColor(gcw));
#endif
// Draw the character
if (DrawStart(gh)) {
// If we are at the beginning of a new line clear the line
#if GWIN_CONSOLE_USE_CLEAR_LINES
if (gcw->cx == 0)
gdispGFillArea(gh->display, gh->x, gh->y + gcw->cy, gh->width, fy, gh->bgcolor);
#endif
#if GWIN_CONSOLE_USE_FILLED_CHARS
gdispGFillChar(gh->display, gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, ESCPrintColor(gcw), gh->bgcolor);
#else
gdispGDrawChar(gh->display, gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, ESCPrintColor(gcw));
#endif
#if GWIN_CONSOLE_ESCSEQ
// Draw the underline
if ((gcw->currattr & ESC_UNDERLINE))
gdispGDrawLine(gh->display, gh->x + gcw->cx, gh->y + gcw->cy + fy - gdispGetFontMetric(gh->font, fontDescendersHeight),
gh->x + gcw->cx + width + gdispGetFontMetric(gh->font, fontCharPadding), gh->y + gcw->cy + fy - gdispGetFontMetric(gh->font, fontDescendersHeight),
ESCPrintColor(gcw));
// Bold (very crude)
if ((gcw->currattr & ESC_BOLD))
gdispGDrawChar(gh->display, gh->x + gcw->cx + 1, gh->y + gcw->cy, c, gh->font, ESCPrintColor(gcw));
#endif
DrawEnd(gh);
}
// Update the cursor
gcw->cx += width + gdispGetFontMetric(gh->font, fontCharPadding);

View File

@ -41,46 +41,6 @@ void _gcontainerDestroy(GHandle gh) {
_gwidgetDestroy(gh);
}
void _gcontainerRedraw(GHandle gh) {
GHandle child;
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
((GWidgetObject *)gh)->fnDraw((GWidgetObject *)gh, ((GWidgetObject *)gh)->fnParam);
for(child = gwinGetFirstChild(gh); child; child = gwinGetSibling(child))
gwinRedraw(child);
}
void _gcontainerUpdate(GHandle gh) {
GHandle child;
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
((GWidgetObject *)gh)->fnDraw((GWidgetObject *)gh, ((GWidgetObject *)gh)->fnParam);
for(child = gwinGetFirstChild(gh); child; child = gwinGetSibling(child))
gwinRedraw(child);
}
void _gwinRecurse(GHandle gh, bool_t (*fn)(GHandle gh)) {
if (fn(gh) && (gh->flags & GWIN_FLG_CONTAINER)) {
// Apply to this windows children
for(gh = gwinGetFirstChild(gh); gh; gh = gwinGetSibling(gh)) {
// Only recurse when we have to. Otherwise apply it directly
if ((gh->flags & GWIN_FLG_CONTAINER))
_gwinRecurse(gh, fn);
else
fn(gh);
}
}
}
GHandle gwinGetFirstChild(GHandle gh) {
GHandle child;

View File

@ -24,22 +24,8 @@ static void _destroy(GWindowObject *gh) {
}
#if GWIN_NEED_IMAGE_ANIMATION
static void _redraw(GHandle gh);
static void _timer(void *param) {
#define gh ((GHandle)param)
// We need to re-test the visibility in case it has been made invisible since the last frame.
if ((gh->flags & GWIN_FLG_SYSVISIBLE)) {
// Setting the clip here shouldn't be necessary if the redraw doesn't overdraw
// but we put it in for safety anyway
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
_redraw(gh);
}
#undef gh
_gwinUpdate((GHandle)param);
}
#endif
@ -160,14 +146,7 @@ bool_t gwinImageOpenGFile(GHandle gh, GFILE *f) {
if ((gdispImageOpenGFile(&widget(gh)->image, f) & GDISP_IMAGE_ERR_UNRECOVERABLE))
return FALSE;
if ((gh->flags & GWIN_FLG_SYSVISIBLE)) {
// Setting the clip here shouldn't be necessary if the redraw doesn't overdraw
// but we put it in for safety anyway
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
_redraw(gh);
}
_gwinUpdate(gh);
return TRUE;
}

View File

@ -208,7 +208,7 @@ void gwinGraphDrawAxis(GHandle gh) {
#define gg ((GGraphObject *)gh)
coord_t i, xmin, ymin, xmax, ymax;
if (gh->vmt != &graphVMT)
if (gh->vmt != &graphVMT || !_gwinDrawStart(gh))
return;
xmin = -gg->xorigin;
@ -262,6 +262,7 @@ void gwinGraphDrawAxis(GHandle gh) {
}
}
_gwinDrawEnd(gh);
#undef gg
}
@ -275,7 +276,7 @@ void gwinGraphStartSet(GHandle gh) {
void gwinGraphDrawPoint(GHandle gh, coord_t x, coord_t y) {
#define gg ((GGraphObject *)gh)
if (gh->vmt != &graphVMT)
if (gh->vmt != &graphVMT || !_gwinDrawStart(gh))
return;
if ((gh->flags & GGRAPH_FLG_CONNECTPOINTS)) {
@ -295,6 +296,7 @@ void gwinGraphDrawPoint(GHandle gh, coord_t x, coord_t y) {
// Draw this point.
pointto(gg, x, y, &gg->style.point);
_gwinDrawEnd(gh);
#undef gg
}
@ -303,7 +305,7 @@ void gwinGraphDrawPoints(GHandle gh, const point *points, unsigned count) {
unsigned i;
const point *p;
if (gh->vmt != &graphVMT)
if (gh->vmt != &graphVMT || !_gwinDrawStart(gh))
return;
// Draw the connecting lines
@ -329,6 +331,7 @@ void gwinGraphDrawPoints(GHandle gh, const point *points, unsigned count) {
for(p = points, i = 0; i < count; p++, i++)
pointto(gg, p->x, p->y, &gg->style.point);
_gwinDrawEnd(gh);
#undef gg
}

View File

@ -292,16 +292,6 @@ void _gwidgetRedraw(GHandle gh) {
gw->fnDraw(gw, gw->fnParam);
}
void _gwidgetUpdate(GHandle gh) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
gw->fnDraw(gw, gw->fnParam);
}
void gwinWidgetClearInit(GWidgetInit *pwi) {
char *p;
unsigned len;
@ -364,7 +354,7 @@ void gwinSetText(GHandle gh, const char *text, bool_t useAlloc) {
gw->text = (const char *)str;
} else
gw->text = text;
_gwidgetUpdate(gh);
_gwinUpdate(gh);
}
const char *gwinGetText(GHandle gh) {
@ -380,7 +370,7 @@ void gwinSetStyle(GHandle gh, const GWidgetStyle *pstyle) {
gw->pstyle = pstyle ? pstyle : defaultStyle;
gh->bgcolor = pstyle->background;
gh->color = pstyle->enabled.text;
_gwidgetUpdate(gh);
_gwinUpdate(gh);
}
const GWidgetStyle *gwinGetStyle(GHandle gh) {
@ -396,7 +386,7 @@ void gwinSetCustomDraw(GHandle gh, CustomWidgetDrawFunction fn, void *param) {
gw->fnDraw = fn ? fn : wvmt->DefaultDraw;
gw->fnParam = param;
_gwidgetUpdate(gh);
_gwinUpdate(gh);
}
bool_t gwinAttachListener(GListener *pl) {

View File

@ -11,10 +11,6 @@
#include "src/gwin/class_gwin.h"
// Needed if there is no window manager
#define MIN_WIN_WIDTH 1
#define MIN_WIN_HEIGHT 1
/*-----------------------------------------------
* Data
*-----------------------------------------------*/
@ -37,64 +33,15 @@ static color_t defaultBgColor = Black;
* Helper Routines
*-----------------------------------------------*/
#if GWIN_NEED_WINDOWMANAGER
#define _gwm_redraw(gh, flags) _GWINwm->vmt->Redraw(gh, flags)
#define _gwm_move(gh,x,y) _GWINwm->vmt->Move(gh,x,y);
#define _gwm_resize(gh,w,h) _GWINwm->vmt->Size(gh,w,h);
#else
static void _gwm_redraw(GHandle gh, int flags) {
if ((gh->flags & GWIN_FLG_SYSVISIBLE)) {
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
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, defaultBgColor);
}
}
static void _gwm_resize(GHandle gh, coord_t width, coord_t height) {
gh->width = width; gh->height = height;
if (gh->width < MIN_WIN_WIDTH) { gh->width = MIN_WIN_WIDTH; }
if (gh->height < MIN_WIN_HEIGHT) { gh->height = MIN_WIN_HEIGHT; }
if (gh->x+gh->width > gdispGetWidth()) gh->width = gdispGetWidth() - gh->x;
if (gh->y+gh->height > gdispGetHeight()) gh->height = gdispGetHeight() - gh->y;
_gwm_redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
}
static void _gwm_move(GHandle gh, coord_t x, coord_t y) {
gh->x = x; gh->y = y;
if (gh->x < 0) gh->x = 0;
if (gh->y < 0) gh->y = 0;
if (gh->x > gdispGetWidth()-MIN_WIN_WIDTH) gh->x = gdispGetWidth()-MIN_WIN_WIDTH;
if (gh->y > gdispGetHeight()-MIN_WIN_HEIGHT) gh->y = gdispGetHeight()-MIN_WIN_HEIGHT;
if (gh->x+gh->width > gdispGetWidth()) gh->width = gdispGetWidth() - gh->x;
if (gh->y+gh->height > gdispGetHeight()) gh->height = gdispGetHeight() - gh->y;
_gwm_redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
}
#endif
/*-----------------------------------------------
* Class Routines
*-----------------------------------------------*/
void _gwinInit(void)
{
#if GWIN_NEED_WINDOWMANAGER
extern void _gwmInit(void);
extern void _gwmInit(void);
_gwmInit();
#endif
_gwmInit();
#if GWIN_NEED_WIDGET
extern void _gwidgetInit(void);
@ -109,6 +56,8 @@ void _gwinInit(void)
void _gwinDeinit(void)
{
extern void _gwmDeinit(void);
#if GWIN_NEED_CONTAINERS
extern void _gcontainerDeinit(void);
@ -119,11 +68,8 @@ void _gwinDeinit(void)
_gwidgetDeinit();
#endif
#if GWIN_NEED_WINDOWMANAGER
extern void _gwmDeinit(void);
_gwmDeinit();
#endif
_gwmDeinit();
}
// Internal routine for use by GWIN components only
@ -146,35 +92,11 @@ GHandle _gwindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit
pgw->font = defaultFont;
#endif
#if GWIN_NEED_CONTAINERS
if (pInit->parent) {
if (!(pInit->parent->flags & GWIN_FLG_CONTAINER) || pgw->display != pInit->parent->display) {
if ((pgw->flags & GWIN_FLG_DYNAMIC))
gfxFree(pgw);
return 0;
}
pgw->parent = pInit->parent;
} else
pgw->parent = 0;
#endif
#if GWIN_NEED_WINDOWMANAGER
if (!_GWINwm->vmt->Add(pgw, pInit)) {
if ((pgw->flags & GWIN_FLG_DYNAMIC))
gfxFree(pgw);
return 0;
}
#else
pgw->x = pgw->y = pgw->width = pgw->height = 0;
_gwm_move(pgw, pInit->x, pInit->y);
_gwm_resize(pgw, pInit->width, pInit->height);
#endif
#if GWIN_NEED_CONTAINERS
// Notify the parent it has been added
if (pgw->parent && ((gcontainerVMT *)pgw->parent->vmt)->NotifyAdd)
((gcontainerVMT *)pgw->parent->vmt)->NotifyAdd(pgw->parent, pgw);
#endif
if (!_gwinWMAdd(pgw, pInit)) {
if ((pgw->flags & GWIN_FLG_DYNAMIC))
gfxFree(pgw);
return 0;
}
return (GHandle)pgw;
}
@ -264,126 +186,14 @@ const char *gwinGetClassName(GHandle gh) {
return gh->vmt->classname;
}
#if GWIN_NEED_CONTAINERS
// These two sub-functions set/clear system visibility recursively.
static bool_t setSysVisFlag(GHandle gh) {
// If we are now visible and our parent is visible
if ((gh->flags & GWIN_FLG_VISIBLE) && (!gh->parent || (gh->parent->flags & GWIN_FLG_SYSVISIBLE))) {
gh->flags |= GWIN_FLG_SYSVISIBLE;
return TRUE;
}
return FALSE;
}
static bool_t clrSysVisFlag(GHandle gh) {
// If we are now not visible but our parent is visible
if (!(gh->flags & GWIN_FLG_VISIBLE) || (gh->parent && !(gh->parent->flags & GWIN_FLG_SYSVISIBLE))) {
gh->flags &= ~GWIN_FLG_SYSVISIBLE;
return TRUE;
}
return FALSE;
}
void gwinSetVisible(GHandle gh, bool_t visible) {
if (visible) {
if (!(gh->flags & GWIN_FLG_VISIBLE)) {
gh->flags |= GWIN_FLG_VISIBLE;
_gwinRecurse(gh, setSysVisFlag);
_gwm_redraw(gh, 0);
}
} else {
if ((gh->flags & GWIN_FLG_VISIBLE)) {
gh->flags &= ~GWIN_FLG_VISIBLE;
_gwinRecurse(gh, clrSysVisFlag);
_gwm_redraw(gh, 0);
}
}
}
#else
void gwinSetVisible(GHandle gh, bool_t visible) {
if (visible) {
if (!(gh->flags & GWIN_FLG_VISIBLE)) {
gh->flags |= (GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE);
_gwm_redraw(gh, 0);
}
} else {
if ((gh->flags & GWIN_FLG_VISIBLE)) {
gh->flags &= ~(GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE);
_gwm_redraw(gh, 0);
}
}
}
#endif
bool_t gwinGetVisible(GHandle gh) {
return (gh->flags & GWIN_FLG_SYSVISIBLE) ? TRUE : FALSE;
}
#if GWIN_NEED_CONTAINERS
// These two sub-functions set/clear system enable recursively.
static bool_t setSysEnaFlag(GHandle gh) {
// If we are now enabled and our parent is enabled
if ((gh->flags & GWIN_FLG_ENABLED) && (!gh->parent || (gh->parent->flags & GWIN_FLG_SYSENABLED))) {
gh->flags |= GWIN_FLG_SYSENABLED;
return TRUE;
}
return FALSE;
}
static bool_t clrSysEnaFlag(GHandle gh) {
// If we are now not enabled but our parent is enabled
if (!(gh->flags & GWIN_FLG_ENABLED) || (gh->parent && !(gh->parent->flags & GWIN_FLG_SYSENABLED))) {
gh->flags &= ~GWIN_FLG_SYSENABLED;
return TRUE;
}
return FALSE;
}
void gwinSetEnabled(GHandle gh, bool_t enabled) {
if (enabled) {
if (!(gh->flags & GWIN_FLG_ENABLED)) {
gh->flags |= GWIN_FLG_ENABLED;
_gwinRecurse(gh, setSysEnaFlag);
if ((gh->flags & GWIN_FLG_SYSVISIBLE))
_gwm_redraw(gh, GWIN_WMFLG_PRESERVE);
}
} else {
if ((gh->flags & GWIN_FLG_ENABLED)) {
gh->flags &= ~GWIN_FLG_ENABLED;
_gwinRecurse(gh, clrSysEnaFlag);
if ((gh->flags & GWIN_FLG_SYSVISIBLE))
_gwm_redraw(gh, GWIN_WMFLG_PRESERVE);
}
}
}
#else
void gwinSetEnabled(GHandle gh, bool_t enabled) {
if (enabled) {
if (!(gh->flags & GWIN_FLG_ENABLED)) {
gh->flags |= (GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED);
_gwm_redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
}
} else {
if ((gh->flags & GWIN_FLG_ENABLED)) {
gh->flags &= ~(GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED);
_gwm_redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
}
}
}
#endif
bool_t gwinGetEnabled(GHandle gh) {
return (gh->flags & GWIN_FLG_SYSENABLED) ? TRUE : FALSE;
}
void gwinMove(GHandle gh, coord_t x, coord_t y) {
_gwm_move(gh, x, y);
}
void gwinResize(GHandle gh, coord_t width, coord_t height) {
_gwm_resize(gh, width, height);
}
void gwinRedraw(GHandle gh) {
_gwm_redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
}
#if GDISP_NEED_TEXT
void gwinSetFont(GHandle gh, font_t font) {
gh->font = font;
@ -396,247 +206,154 @@ void gwinClear(GHandle gh) {
* still call the AfterClear() routine as some widgets will
* need this to clear internal buffers or similar
*/
if (!(gh->flags & GWIN_FLG_SYSVISIBLE)) {
if (gh->vmt->AfterClear)
gh->vmt->AfterClear(gh);
} else {
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (_gwinDrawStart(gh)) {
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
if (gh->vmt->AfterClear)
gh->vmt->AfterClear(gh);
_gwinDrawEnd(gh);
}
#if GWIN_NEED_CONTAINERS
for (gh = gwinGetFirstChild(gh); gh; gh = gwinGetSibling(gh))
gwinRedraw(gh);
#endif
if (gh->vmt->AfterClear)
gh->vmt->AfterClear(gh);
}
void gwinDrawPixel(GHandle gh, coord_t x, coord_t y) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (!_gwinDrawStart(gh)) return;
gdispGDrawPixel(gh->display, gh->x+x, gh->y+y, gh->color);
_gwinDrawEnd(gh);
}
void gwinDrawLine(GHandle gh, coord_t x0, coord_t y0, coord_t x1, coord_t y1) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (!_gwinDrawStart(gh)) return;
gdispGDrawLine(gh->display, gh->x+x0, gh->y+y0, gh->x+x1, gh->y+y1, gh->color);
_gwinDrawEnd(gh);
}
void gwinDrawBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (!_gwinDrawStart(gh)) return;
gdispGDrawBox(gh->display, gh->x+x, gh->y+y, cx, cy, gh->color);
_gwinDrawEnd(gh);
}
void gwinFillArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (!_gwinDrawStart(gh)) return;
gdispGFillArea(gh->display, gh->x+x, gh->y+y, cx, cy, gh->color);
_gwinDrawEnd(gh);
}
void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (!_gwinDrawStart(gh)) return;
gdispGBlitArea(gh->display, gh->x+x, gh->y+y, cx, cy, srcx, srcy, srccx, buffer);
_gwinDrawEnd(gh);
}
#if GDISP_NEED_CIRCLE
void gwinDrawCircle(GHandle gh, coord_t x, coord_t y, coord_t radius) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (!_gwinDrawStart(gh)) return;
gdispGDrawCircle(gh->display, gh->x+x, gh->y+y, radius, gh->color);
_gwinDrawEnd(gh);
}
void gwinFillCircle(GHandle gh, coord_t x, coord_t y, coord_t radius) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (!_gwinDrawStart(gh)) return;
gdispGFillCircle(gh->display, gh->x+x, gh->y+y, radius, gh->color);
_gwinDrawEnd(gh);
}
#endif
#if GDISP_NEED_ELLIPSE
void gwinDrawEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (!_gwinDrawStart(gh)) return;
gdispGDrawEllipse(gh->display, gh->x+x, gh->y+y, a, b, gh->color);
_gwinDrawEnd(gh);
}
void gwinFillEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (!_gwinDrawStart(gh)) return;
gdispGFillEllipse(gh->display, gh->x+x, gh->y+y, a, b, gh->color);
_gwinDrawEnd(gh);
}
#endif
#if GDISP_NEED_ARC
void gwinDrawArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (!_gwinDrawStart(gh)) return;
gdispGDrawArc(gh->display, gh->x+x, gh->y+y, radius, startangle, endangle, gh->color);
_gwinDrawEnd(gh);
}
void gwinFillArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (!_gwinDrawStart(gh)) return;
gdispGFillArc(gh->display, gh->x+x, gh->y+y, radius, startangle, endangle, gh->color);
_gwinDrawEnd(gh);
}
#endif
#if GDISP_NEED_PIXELREAD
color_t gwinGetPixelColor(GHandle gh, coord_t x, coord_t y) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return defaultBgColor;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (!_gwinDrawStart(gh)) return;
return gdispGGetPixelColor(gh->display, gh->x+x, gh->y+y);
_gwinDrawEnd(gh);
}
#endif
#if GDISP_NEED_TEXT
void gwinDrawChar(GHandle gh, coord_t x, coord_t y, char c) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE) || !gh->font)
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (!gh->font || !_gwinDrawStart(gh)) return;
gdispGDrawChar(gh->display, gh->x+x, gh->y+y, c, gh->font, gh->color);
_gwinDrawEnd(gh);
}
void gwinFillChar(GHandle gh, coord_t x, coord_t y, char c) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE) || !gh->font)
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (!gh->font || !_gwinDrawStart(gh)) return;
gdispGFillChar(gh->display, gh->x+x, gh->y+y, c, gh->font, gh->color, gh->bgcolor);
_gwinDrawEnd(gh);
}
void gwinDrawString(GHandle gh, coord_t x, coord_t y, const char *str) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE) || !gh->font)
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (!gh->font || !_gwinDrawStart(gh)) return;
gdispGDrawString(gh->display, gh->x+x, gh->y+y, str, gh->font, gh->color);
_gwinDrawEnd(gh);
}
void gwinFillString(GHandle gh, coord_t x, coord_t y, const char *str) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE) || !gh->font)
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (!gh->font || !_gwinDrawStart(gh)) return;
gdispGFillString(gh->display, gh->x+x, gh->y+y, str, gh->font, gh->color, gh->bgcolor);
_gwinDrawEnd(gh);
}
void gwinDrawStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE) || !gh->font)
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (!gh->font || !_gwinDrawStart(gh)) return;
gdispGDrawStringBox(gh->display, gh->x+x, gh->y+y, cx, cy, str, gh->font, gh->color, justify);
_gwinDrawEnd(gh);
}
void gwinFillStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE) || !gh->font)
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (!gh->font || !_gwinDrawStart(gh)) return;
gdispGFillStringBox(gh->display, gh->x+x, gh->y+y, cx, cy, str, gh->font, gh->color, gh->bgcolor, justify);
_gwinDrawEnd(gh);
}
#endif
#if GDISP_NEED_CONVEX_POLYGON
void gwinDrawPoly(GHandle gh, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (!_gwinDrawStart(gh)) return;
gdispGDrawPoly(gh->display, tx+gh->x, ty+gh->y, pntarray, cnt, gh->color);
_gwinDrawEnd(gh);
}
void gwinFillConvexPoly(GHandle gh, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
if (!_gwinDrawStart(gh)) return;
gdispGFillConvexPoly(gh->display, tx+gh->x, ty+gh->y, pntarray, cnt, gh->color);
_gwinDrawEnd(gh);
}
#endif
#if GDISP_NEED_IMAGE
gdispImageError gwinDrawImage(GHandle gh, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return GDISP_IMAGE_ERR_OK;
gdispImageError ret;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
return gdispGImageDraw(gh->display, img, gh->x+x, gh->y+y, cx, cy, sx, sy);
if (!_gwinDrawStart(gh)) return GDISP_IMAGE_ERR_OK;
ret = gdispGImageDraw(gh->display, img, gh->x+x, gh->y+y, cx, cy, sx, sy);
_gwinDrawEnd(gh);
return ret;
}
#endif

View File

@ -7,55 +7,165 @@
#include "gfx.h"
// Used by the NULL window manager
#define MIN_WIN_WIDTH 3
#define MIN_WIN_HEIGHT 3
#if GFX_USE_GWIN && !GWIN_NEED_WINDOWMANAGER
/**
* A really nasty default implementation for the simplest of systems
*/
/*-----------------------------------------------
* The default window manager (GNullWindowManager)
*-----------------------------------------------*/
#include "src/gwin/class_gwin.h"
// Needed if there is no window manager
#define MIN_WIN_WIDTH 1
#define MIN_WIN_HEIGHT 1
static gfxMutex gmutex;
void _gwmInit(void) {
gfxMutexInit(&gmutex);
}
void _gwmDeinit(void) {
gfxMutexDestroy(&gmutex);
}
bool_t _gwinWMAdd(GHandle gh, const GWindowInit *pInit) {
gh->x = gh->y = gh->width = gh->height = 0;
gwinMove(gh, pInit->x, pInit->y);
gwinResize(gh, pInit->width, pInit->height);
return TRUE;
}
void _gwinFlushRedraws(bool_t doWait) {
(void) doWait;
// We are always flushed
}
#if GDISP_NEED_CLIP
static void getLock(GHandle gh) {
gfxMutexEnter(&gmutex);
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
}
static void exitLock(GHandle gh) {
gdispGUnsetClip(gh->display);
gfxMutexExit(&gmutex);
}
#else
#define getLock(gh) gfxMutexEnter(&gmutex)
#define exitLock(gh) gfxMutexExit(&gmutex)
#endif
void _gwinUpdate(GHandle gh) {
if ((gh->flags & GWIN_FLG_SYSVISIBLE)) {
if (gh->vmt->Redraw) {
getLock(gh);
gh->vmt->Redraw(gh);
exitLock(gh);
} else if ((gh->flags & GWIN_FLG_BGREDRAW)) {
getLock(gh);
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
exitLock(gh);
if (gh->vmt->AfterClear)
gh->vmt->AfterClear(gh);
}
} else if ((gh->flags & GWIN_FLG_BGREDRAW)) {
getLock(gh);
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor());
exitLock(gh);
}
gh->flags &= ~(GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW);
}
bool_t _gwinDrawStart(GHandle gh) {
if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return FALSE;
getLock(gh);
return TRUE;
}
void _gwinDrawEnd(GHandle gh) {
(void) gh;
exitLock(gh);
}
void gwinSetVisible(GHandle gh, bool_t visible) {
if (visible) {
if (!(gh->flags & GWIN_FLG_VISIBLE)) {
gh->flags |= (GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE|GWIN_FLG_BGREDRAW);
_gwinUpdate(gh);
}
} else {
if ((gh->flags & GWIN_FLG_VISIBLE)) {
gh->flags &= ~(GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE);
gh->flags |= GWIN_FLG_BGREDRAW;
_gwinUpdate(gh);
}
}
}
void gwinSetEnabled(GHandle gh, bool_t enabled) {
if (enabled) {
if (!(gh->flags & GWIN_FLG_ENABLED)) {
gh->flags |= (GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED);
_gwinUpdate(gh);
}
} else {
if ((gh->flags & GWIN_FLG_ENABLED)) {
gh->flags &= ~(GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED);
_gwinUpdate(gh);
}
}
}
void gwinMove(GHandle gh, coord_t x, coord_t y) {
gh->x = x; gh->y = y;
if (gh->x < 0) gh->x = 0;
if (gh->y < 0) gh->y = 0;
if (gh->x > gdispGGetWidth(gh->display)-MIN_WIN_WIDTH) gh->x = gdispGGetWidth(gh->display)-MIN_WIN_WIDTH;
if (gh->y > gdispGGetHeight(gh->display)-MIN_WIN_HEIGHT) gh->y = gdispGGetHeight(gh->display)-MIN_WIN_HEIGHT;
if (gh->x+gh->width > gdispGGetWidth(gh->display)) gh->width = gdispGGetWidth(gh->display) - gh->x;
if (gh->y+gh->height > gdispGGetHeight(gh->display)) gh->height = gdispGGetHeight(gh->display) - gh->y;
_gwinUpdate(gh);
}
void gwinResize(GHandle gh, coord_t width, coord_t height) {
gh->width = width; gh->height = height;
if (gh->width < MIN_WIN_WIDTH) { gh->width = MIN_WIN_WIDTH; }
if (gh->height < MIN_WIN_HEIGHT) { gh->height = MIN_WIN_HEIGHT; }
if (gh->x+gh->width > gdispGGetWidth(gh->display)) gh->width = gdispGGetWidth(gh->display) - gh->x;
if (gh->y+gh->height > gdispGGetHeight(gh->display)) gh->height = gdispGGetHeight(gh->display) - gh->y;
_gwinUpdate(gh);
}
void gwinRedraw(GHandle gh) {
_gwinUpdate(gh);
}
#endif
#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"
/*-----------------------------------------------