aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2014-05-21 13:02:00 +1000
committerinmarket <andrewh@inmarket.com.au>2014-05-21 13:02:00 +1000
commit34e23320b4c69f5e409f25431603d901abfc4740 (patch)
tree2959d9c395b5364243a267229779e8afd8ee094d
parent7afe4e78b7ffd2150f7eba51d6613422ccc7abe5 (diff)
downloaduGFX-34e23320b4c69f5e409f25431603d901abfc4740.tar.gz
uGFX-34e23320b4c69f5e409f25431603d901abfc4740.tar.bz2
uGFX-34e23320b4c69f5e409f25431603d901abfc4740.zip
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.
-rw-r--r--src/gwin/button.c8
-rw-r--r--src/gwin/checkbox.c6
-rw-r--r--src/gwin/class_gwin.h117
-rw-r--r--src/gwin/console.c93
-rw-r--r--src/gwin/gcontainer.c40
-rw-r--r--src/gwin/gimage.c25
-rw-r--r--src/gwin/graph.c9
-rw-r--r--src/gwin/gwidget.c16
-rw-r--r--src/gwin/gwin.c401
-rw-r--r--src/gwin/gwm.c711
-rw-r--r--src/gwin/list.c22
-rw-r--r--src/gwin/progressbar.c6
-rw-r--r--src/gwin/radio.c4
-rw-r--r--src/gwin/slider.c10
14 files changed, 832 insertions, 636 deletions
diff --git a/src/gwin/button.c b/src/gwin/button.c
index af837486..d489ecb0 100644
--- a/src/gwin/button.c
+++ b/src/gwin/button.c
@@ -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);
}
diff --git a/src/gwin/checkbox.c b/src/gwin/checkbox.c
index 22e249ad..f162d8fc 100644
--- a/src/gwin/checkbox.c
+++ b/src/gwin/checkbox.c
@@ -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);
}
diff --git a/src/gwin/class_gwin.h b/src/gwin/class_gwin.h
index ceac3b3a..0aee1ae8 100644
--- a/src/gwin/class_gwin.h
+++ b/src/gwin/class_gwin.h
@@ -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
diff --git a/src/gwin/console.c b/src/gwin/console.c
index fa93c79d..0380fd61 100644
--- a/src/gwin/console.c
+++ b/src/gwin/console.c
@@ -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
+ // Save the char
+ putCharInBuffer(gcw, c);
// 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
- putCharInBuffer(gcw, c);
+ if (DrawStart(gh)) {
- #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
+ // 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);
diff --git a/src/gwin/gcontainer.c b/src/gwin/gcontainer.c
index 998433b4..46e89032 100644
--- a/src/gwin/gcontainer.c
+++ b/src/gwin/gcontainer.c
@@ -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;
diff --git a/src/gwin/gimage.c b/src/gwin/gimage.c
index a4f477e9..d5ca2c38 100644
--- a/src/gwin/gimage.c
+++ b/src/gwin/gimage.c
@@ -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;
}
diff --git a/src/gwin/graph.c b/src/gwin/graph.c
index 8f7223e1..4fcfad37 100644
--- a/src/gwin/graph.c
+++ b/src/gwin/graph.c
@@ -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
}
diff --git a/src/gwin/gwidget.c b/src/gwin/gwidget.c
index ccfbd26e..8ccb47fc 100644
--- a/src/gwin/gwidget.c
+++ b/src/gwin/gwidget.c
@@ -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) {
diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c
index 2e4144a7..e1625b13 100644
--- a/src/gwin/gwin.c
+++ b/src/gwin/gwin.c
@@ -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
diff --git a/src/gwin/gwm.c b/src/gwin/gwm.c
index 1c96d1c9..ffea4afd 100644
--- a/src/gwin/gwm.c
+++ b/src/gwin/gwm.c
@@ -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"
/*-----------------------------------------------
* Data
*-----------------------------------------------*/
-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_Redraw(GHandle gh, int flags);
-static void WM_Size(GHandle gh, coord_t w, coord_t h);
-static void WM_Move(GHandle gh, coord_t x, coord_t y);
-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,
- WM_Redraw,
- WM_Size,
- WM_Move,
- WM_Raise,
- WM_MinMax,
-};
-
-static const GWindowManager GNullWindowManager = {
- &GNullWindowManagerVMT,
-};
+// The default window manager
+extern const GWindowManager GNullWindowManager;
+GWindowManager * _GWINwm;
+static gfxSem gwinsem;
static gfxQueueASync _GWINList;
-GWindowManager * _GWINwm;
+static volatile bool_t RedrawPending;
#if GFX_USE_GTIMER
static GTimer RedrawTimer;
- static GDisplay * RedrawDisplay;
- static bool_t RedrawPreserve;
- static void _gwinRedrawDisplay(void * param);
+ static void RedrawTimerFn(void *param);
#endif
/*-----------------------------------------------
@@ -64,18 +174,178 @@ GWindowManager * _GWINwm;
void _gwmInit(void)
{
+ gfxSemInit(&gwinsem, 1, 1);
gfxQueueASyncInit(&_GWINList);
- _GWINwm = (GWindowManager *)&GNullWindowManager;
- _GWINwm->vmt->Init();
#if GFX_USE_GTIMER
gtimerInit(&RedrawTimer);
- gtimerStart(&RedrawTimer, _gwinRedrawDisplay, 0, TRUE, TIME_INFINITE);
+ gtimerStart(&RedrawTimer, RedrawTimerFn, 0, TRUE, TIME_INFINITE);
#endif
+ _GWINwm = (GWindowManager *)&GNullWindowManager;
+ _GWINwm->vmt->Init();
}
void _gwmDeinit(void)
{
- /* ToDo */
+ GHandle gh;
+
+ while((gh = gwinGetNextWindow(0)))
+ gwinDestroy(gh);
+
+ _GWINwm->vmt->DeInit();
+ #if GFX_USE_GTIMER
+ gtimerDeinit(&RedrawTimer);
+ #endif
+ gfxQueueASyncDeinit(&_GWINList);
+ gfxSemDestroy(&gwinsem);
+}
+
+#if GFX_USE_GTIMER
+ #define TriggerRedraw() gtimerJab(&RedrawTimer);
+
+ static void RedrawTimerFn(void *param) {
+ (void) param;
+ _gwinFlushRedraws(FALSE);
+ }
+#else
+ #define TriggerRedraw(void) _gwinFlushRedraws(FALSE);
+#endif
+
+void _gwinFlushRedraws(bool_t doWait) {
+ GHandle gh;
+
+ // Do we really need to do anything?
+ if (!RedrawPending)
+ return;
+
+ // Obtain the drawing lock
+ if (doWait)
+ gfxSemWait(&gwinsem, TIME_INFINITE);
+ else if (!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;
+
+ 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
+
+ // Postpone further redraws (if there are any and the options are set right)
+ #if GFX_USE_GTIMER && !GWIN_LONG_REDRAW
+ if (!doWait) {
+ while((gh = gwinGetNextWindow(gh))) {
+ if ((gh->flags & GWIN_FLG_NEEDREDRAW)) {
+ gtimerJab(&RedrawTimer);
+ RedrawPending = TRUE;
+ break;
+ }
+ }
+ break;
+ }
+ #endif
+ }
+ }
+
+ // Release the lock
+ gfxSemSignal(&gwinsem);
+}
+
+void _gwinUpdate(GHandle gh) {
+ // Only redraw if visible
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
+ return;
+
+ // Mark for redraw
+ gh->flags |= GWIN_FLG_NEEDREDRAW;
+ RedrawPending = TRUE;
+
+ // Asynchronous redraw
+ TriggerRedraw();
+}
+
+bool_t _gwinDrawStart(GHandle gh) {
+ // This test should occur inside the lock. We do this
+ // here as well as an early out (more efficient).
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
+ return FALSE;
+
+ // Obtain the drawing lock
+ gfxSemWait(&gwinsem, TIME_INFINITE);
+
+ // Re-test visibility as we may have waited a while
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE)) {
+ _gwinDrawEnd(gh);
+ return FALSE;
+ }
+
+ // OK - we are ready to draw.
+ #if GDISP_NEED_CLIP
+ gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
+ #endif
+ return TRUE;
+}
+
+void _gwinDrawEnd(GHandle gh) {
+ // Ensure there is no clip set
+ #if GDISP_NEED_CLIP
+ gdispGUnsetClip(gh->display);
+ #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
+ }
+ }
+
+ // Release the lock
+ gfxSemSignal(&gwinsem);
+}
+
+bool_t _gwinWMAdd(GHandle gh, const GWindowInit *pInit) {
+ #if GWIN_NEED_CONTAINERS
+ // Save the parent
+ gh->parent = pInit->parent;
+
+ // Ensure the display is consistent with any parents
+ if (gh->parent && (!(gh->parent->flags & GWIN_FLG_CONTAINER) || gh->display != gh->parent->display))
+ return FALSE;
+ #endif
+
+ // Add to the window manager
+ if (!_GWINwm->vmt->Add(gh, pInit))
+ return FALSE;
+
+ #if GWIN_NEED_CONTAINERS
+ // Notify the parent it has been added
+ if (gh->parent && ((gcontainerVMT *)gh->parent->vmt)->NotifyAdd)
+ ((gcontainerVMT *)gh->parent->vmt)->NotifyAdd(gh->parent, gh);
+ #endif
+
+ return TRUE;
}
void gwinSetWindowManager(struct GWindowManager *gwm) {
@@ -88,6 +358,142 @@ void gwinSetWindowManager(struct GWindowManager *gwm) {
}
}
+void gwinRedraw(GHandle gh) {
+ // Only redraw if visible
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
+ return;
+
+ // Mark for redraw
+ gh->flags |= GWIN_FLG_NEEDREDRAW;
+ RedrawPending = TRUE;
+
+ // Synchronous redraw
+ _gwinFlushRedraws(TRUE);
+}
+
+#if GWIN_NEED_CONTAINERS
+ void gwinSetVisible(GHandle gh, bool_t visible) {
+ if (visible) {
+ // Mark us as visible
+ gh->flags |= GWIN_FLG_VISIBLE;
+
+ // Do we want to be added to the display
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE) && (!gh->parent || (gh->parent->flags & GWIN_FLG_SYSVISIBLE))) {
+ // Check each window's visibility is consistent with its parents
+ for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
+ if ((gh->flags & (GWIN_FLG_SYSVISIBLE|GWIN_FLG_VISIBLE)) == GWIN_FLG_VISIBLE && (!gh->parent || (gh->parent->flags & GWIN_FLG_SYSVISIBLE)))
+ gh->flags |= (GWIN_FLG_SYSVISIBLE|GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW); // Fix it and mark for redraw
+ }
+
+ // Mark for redraw
+ RedrawPending = TRUE;
+ TriggerRedraw();
+ }
+ } else {
+ // Mark us as not visible
+ gh->flags &= ~GWIN_FLG_VISIBLE;
+
+ // Do we need to be removed from the display
+ if ((gh->flags & GWIN_FLG_SYSVISIBLE)) {
+ gh->flags |= (GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW);
+
+ // Check each window's visibility is consistent with its parents
+ for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
+ if ((gh->flags & GWIN_FLG_SYSVISIBLE) && (!(gh->flags & GWIN_FLG_VISIBLE) || (gh->parent && !(gh->parent->flags & GWIN_FLG_SYSVISIBLE))))
+ gh->flags &= ~GWIN_FLG_SYSVISIBLE; // Fix it
+ }
+
+ // Mark for redraw - no need to redraw children
+ RedrawPending = TRUE;
+ TriggerRedraw();
+ }
+ }
+ }
+#else
+ 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_NEEDREDRAW|GWIN_FLG_BGREDRAW);
+ RedrawPending = TRUE;
+ 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;
+ TriggerRedraw();
+ }
+ }
+ }
+#endif
+
+#if GWIN_NEED_CONTAINERS
+ // These two sub-functions set/clear system enable recursively.
+ void gwinSetEnabled(GHandle gh, bool_t enabled) {
+ if (enabled) {
+ // Mark us as enabled
+ gh->flags |= GWIN_FLG_ENABLED;
+
+ // Do we change our real enabled state
+ if (!(gh->flags & GWIN_FLG_SYSENABLED) && (!gh->parent || (gh->parent->flags & GWIN_FLG_SYSENABLED))) {
+ // Check each window's enabled state is consistent with its parents
+ 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;
+ }
+ }
+ }
+ if (RedrawPending)
+ TriggerRedraw();
+ }
+ } else {
+ gh->flags &= ~GWIN_FLG_ENABLED;
+
+ // Do we need to change our real enabled state
+ if ((gh->flags & GWIN_FLG_SYSENABLED)) {
+ // Check each window's visibility is consistent with its parents
+ 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;
+ }
+ }
+ }
+ if (RedrawPending)
+ TriggerRedraw();
+ }
+ }
+ }
+#else
+ 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);
+ }
+ }
+ }
+#endif
+
+void gwinMove(GHandle gh, coord_t x, coord_t y) {
+ _GWINwm->vmt->Move(gh, x, y);
+}
+
+void gwinResize(GHandle gh, coord_t width, coord_t height) {
+ _GWINwm->vmt->Size(gh, width, height);
+}
+
void gwinSetMinMax(GHandle gh, GWindowMinMax minmax) {
_GWINwm->vmt->MinMax(gh, minmax);
}
@@ -105,31 +511,73 @@ GWindowMinMax gwinGetMinMax(GHandle gh) {
}
void gwinRedrawDisplay(GDisplay *g, bool_t preserve) {
- #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
-
- GHandle gh;
+ GHandle gh;
for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
- 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));
+
+ // Skip if it is for a different display
+ if (g && gh->display != g)
+ continue;
+
+ #if GWIN_NEED_CONTAINERS
+ // Skip if it is not a top level window (parents internally take care of their children)
+ if (gh->parent)
+ continue;
+ #endif
+
+ // Only visible windows are to be redrawn
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
+ continue;
+
+ if (!preserve)
+ gh->flags |= GWIN_FLG_BGREDRAW;
+
+ _gwinUpdate(gh);
}
}
+GHandle gwinGetNextWindow(GHandle gh) {
+ return gh ? (GHandle)gfxQueueASyncNext(&gh->wmq) : (GHandle)gfxQueueASyncPeek(&_GWINList);
+}
+
/*-----------------------------------------------
* "Null" Window Manager Routines
*-----------------------------------------------*/
+// This is a parent reveal operation
+#define GWIN_FLG_PARENTREVEAL (GWIN_FIRST_WM_FLAG << 0)
+
+// Minimum dimensions
+#define MIN_WIN_WIDTH 3
+#define MIN_WIN_HEIGHT 3
+
+
+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_Redraw(GHandle gh);
+static void WM_Size(GHandle gh, coord_t w, coord_t h);
+static void WM_Move(GHandle gh, coord_t x, coord_t y);
+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,
+ WM_Redraw,
+ WM_Size,
+ WM_Move,
+ WM_Raise,
+ WM_MinMax,
+};
+
+const GWindowManager GNullWindowManager = {
+ &GNullWindowManagerVMT,
+};
+
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
@@ -163,47 +611,55 @@ static void WM_Delete(GHandle gh) {
gfxQueueASyncRemove(&_GWINList, &gh->wmq);
}
-static void WM_Redraw(GHandle gh, int flags) {
+static void WM_Redraw(GHandle gh) {
#if GWIN_NEED_CONTAINERS
redo_redraw:
#endif
if ((gh->flags & GWIN_FLG_SYSVISIBLE)) {
- if (gh->vmt->Redraw) {
- #if GDISP_NEED_CLIP
- if (!(flags & GWIN_WMFLG_KEEPCLIP))
- gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
- #endif
+ if (gh->vmt->Redraw)
gh->vmt->Redraw(gh);
- } else if (!(flags & GWIN_WMFLG_PRESERVE)) {
- #if GDISP_NEED_CLIP
- if (!(flags & GWIN_WMFLG_KEEPCLIP))
- gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
- #endif
+ else if ((gh->flags & GWIN_FLG_BGREDRAW)) {
+ // We can't redraw but we want full coverage so just clear the area
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
- if (gh->vmt->AfterClear)
+
+ // Only do an after clear if this is not a parent reveal
+ if (!(gh->flags & GWIN_FLG_PARENTREVEAL) && gh->vmt->AfterClear)
gh->vmt->AfterClear(gh);
}
- // A real window manager would also redraw the borders here
+ // A real window manager would also redraw frame borders here for top level windows
+ // For non-top level windows their parent is responsible for any borders
- // A real window manager would then redraw any higher z-order windows
- // if (!(flags & GWIN_WMFLG_NOZORDER))
- // ...
+ // Redraw is done
+ gh->flags &= ~(GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW|GWIN_FLG_PARENTREVEAL);
- } else if (!(flags & GWIN_WMFLG_NOBGCLEAR)) {
- #if GDISP_NEED_CLIP
- 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;
+ // If this is container but not a parent reveal, mark any visible children for redraw
+ // We redraw our children here as we have overwritten them in redrawing the parent
+ // as GDISP/GWIN doesn't yet support complex clipping regions.
+ if ((gh->flags & (GWIN_FLG_CONTAINER|GWIN_FLG_PARENTREVEAL)) == GWIN_FLG_CONTAINER) {
+ for(gh = gwinGetFirstChild(gh); gh; gh = gwinGetSibling(gh))
+ _gwinUpdate(gh);
}
#endif
- gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor());
+ } else {
+ if ((gh->flags & GWIN_FLG_BGREDRAW)) {
+ #if GWIN_NEED_CONTAINERS
+ if (gh->parent) {
+ // Child redraw is done
+ gh->flags &= ~(GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW|GWIN_FLG_PARENTREVEAL);
+
+ // Get the parent to redraw the area
+ gh = gh->parent;
+ gh->flags |= (GWIN_FLG_BGREDRAW|GWIN_FLG_PARENTREVEAL);
+ goto redo_redraw;
+ }
+ #endif
+ gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor());
+ }
+
+ // Redraw is done
+ gh->flags &= ~(GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW|GWIN_FLG_PARENTREVEAL);
}
}
@@ -234,15 +690,49 @@ static void WM_Size(GHandle gh, coord_t w, coord_t h) {
if (gh->width == w && gh->height == h)
return;
- // Clear the old area and then redraw
+ // Set the new size and 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);
+ if (w >= gh->width && h >= gh->height) {
+
+ // The new size is larger - just redraw
+ gh->width = w; gh->height = h;
+ _gwinUpdate(gh);
+
+ } else {
+ // We need to make this window invisible and ensure that has been drawn
+ gwinSetVisible(gh, FALSE);
+ _gwinFlushRedraws(TRUE);
+
+ // Resize
+ gh->width = w; gh->height = h;
+
+ #if GWIN_NEED_CONTAINERS
+ // Any children outside the new area need to be moved
+ if ((gh->flags & GWIN_FLG_CONTAINER)) {
+ GHandle child;
+
+ // Move to their old relative location. THe WM_Move() will adjust as necessary
+ for(child = gwinGetFirstChild(gh); child; child = gwinGetSibling(child))
+ WM_Move(gh, child->x-gh->x-((const gcontainerVMT *)gh->parent->vmt)->LeftBorder(gh->parent), child->y-gh->y-((const gcontainerVMT *)gh->parent->vmt)->TopBorder(gh->parent));
+ }
+ #endif
+
+ // Mark it visible again in its new location
+ gwinSetVisible(gh, TRUE);
+ }
} else {
gh->width = w; gh->height = h;
+
+ #if GWIN_NEED_CONTAINERS
+ // Any children outside the new area need to be moved
+ if ((gh->flags & GWIN_FLG_CONTAINER)) {
+ GHandle child;
+
+ // Move to their old relative location. THe WM_Move() will adjust as necessary
+ for(child = gwinGetFirstChild(gh); child; child = gwinGetSibling(child))
+ WM_Move(gh, child->x-gh->x-((const gcontainerVMT *)gh->parent->vmt)->LeftBorder(gh->parent), child->y-gh->y-((const gcontainerVMT *)gh->parent->vmt)->TopBorder(gh->parent));
+ }
+ #endif
}
}
@@ -279,13 +769,40 @@ static void WM_Move(GHandle gh, coord_t x, coord_t y) {
// 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);
+ // We need to make this window invisible and ensure that has been drawn
+ gwinSetVisible(gh, FALSE);
+ _gwinFlushRedraws(TRUE);
+
+ // Do the move
+ v = gh->x; gh->x = x; x = v;
+ v = gh->y; gh->y = y; y = v;
+
+ #if GWIN_NEED_CONTAINERS
+ // Any children need to be moved
+ if ((gh->flags & GWIN_FLG_CONTAINER)) {
+ GHandle child;
+
+ // Move to their old relative location. THe WM_Move() will adjust as necessary
+ for(child = gwinGetFirstChild(gh); child; child = gwinGetSibling(child))
+ WM_Move(gh, child->x-x-((const gcontainerVMT *)gh->parent->vmt)->LeftBorder(gh->parent), child->y-y-((const gcontainerVMT *)gh->parent->vmt)->TopBorder(gh->parent));
+ }
+ #endif
+
+ gwinSetVisible(gh, TRUE);
} else {
- gh->x = x; gh->y = y;
+ v = gh->x; gh->x = x; x = v;
+ v = gh->y; gh->y = y; y = v;
+
+ #if GWIN_NEED_CONTAINERS
+ // Any children need to be moved
+ if ((gh->flags & GWIN_FLG_CONTAINER)) {
+ GHandle child;
+
+ // Move to their old relative location. THe WM_Move() will adjust as necessary
+ for(child = gwinGetFirstChild(gh); child; child = gwinGetSibling(child))
+ WM_Move(gh, child->x-x-((const gcontainerVMT *)gh->parent->vmt)->LeftBorder(gh->parent), child->y-y-((const gcontainerVMT *)gh->parent->vmt)->TopBorder(gh->parent));
+ }
+ #endif
}
}
@@ -302,11 +819,7 @@ static void WM_Raise(GHandle gh) {
gfxQueueASyncPut(&_GWINList, &gh->wmq);
// Redraw the window
- WM_Redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
-}
-
-GHandle gwinGetNextWindow(GHandle gh) {
- return gh ? (GHandle)gfxQueueASyncNext(&gh->wmq) : (GHandle)gfxQueueASyncPeek(&_GWINList);
+ _gwinUpdate(gh);
}
#endif /* GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER */
diff --git a/src/gwin/list.c b/src/gwin/list.c
index 2024d411..c2a857e3 100644
--- a/src/gwin/list.c
+++ b/src/gwin/list.c
@@ -102,7 +102,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param);
}
}
- _gwidgetUpdate(&gw->g);
+ _gwinUpdate(&gw->g);
sendListEvent(gw, item);
}
@@ -131,14 +131,14 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param);
gw2obj->top -= iheight;
if (gw2obj->top < 0)
gw2obj->top = 0;
- _gwidgetUpdate(&gw->g);
+ _gwinUpdate(&gw->g);
}
} else if (y >= gw->g.height - 2*ARROW) {
if (gw2obj->top < gw2obj->cnt * iheight - pgsz) {
gw2obj->top += iheight;
if (gw2obj->top > gw2obj->cnt * iheight - pgsz)
gw2obj->top = gw2obj->cnt * iheight - pgsz;
- _gwidgetUpdate(&gw->g);
+ _gwinUpdate(&gw->g);
}
} else if (y < gw->g.height/2) {
if (gw2obj->top > 0) {
@@ -146,7 +146,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param);
gw2obj->top -= pgsz;
else
gw2obj->top = 0;
- _gwidgetUpdate(&gw->g);
+ _gwinUpdate(&gw->g);
}
} else {
if (gw2obj->top < gw2obj->cnt * iheight - pgsz) {
@@ -154,7 +154,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param);
gw2obj->top += pgsz;
else
gw2obj->top = gw2obj->cnt * iheight - pgsz;
- _gwidgetUpdate(&gw->g);
+ _gwinUpdate(&gw->g);
}
}
return;
@@ -192,7 +192,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param);
gw2obj->top = 0;
gw2obj->last_mouse_y = y;
if (oldtop != gw2obj->top)
- _gwidgetUpdate(&gw->g);
+ _gwinUpdate(&gw->g);
}
}
#endif
@@ -213,7 +213,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param);
if (qix) {
qi2li->flags &=~ GLIST_FLG_SELECTED;
qix2li->flags |= GLIST_FLG_SELECTED;
- _gwidgetUpdate(&gw->g);
+ _gwinUpdate(&gw->g);
}
break;
}
@@ -230,7 +230,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param);
if (qix) {
qi2li->flags &=~ GLIST_FLG_SELECTED;
qix2li->flags |= GLIST_FLG_SELECTED;
- _gwidgetUpdate(&gw->g);
+ _gwinUpdate(&gw->g);
}
break;
}
@@ -383,7 +383,7 @@ int gwinListAddItem(GHandle gh, const char* item_name, bool_t useAlloc) {
// increment the total amount of entries in the list widget
gh2obj->cnt++;
- _gwidgetUpdate(gh);
+ _gwinUpdate(gh);
// return the position in the list (-1 because we start with index 0)
return gh2obj->cnt-1;
@@ -481,7 +481,7 @@ void gwinListDeleteAll(GHandle gh) {
gh->flags &= ~GLIST_FLG_HASIMAGES;
gh2obj->cnt = 0;
gh2obj->top = 0;
- _gwidgetUpdate(gh);
+ _gwinUpdate(gh);
}
void gwinListItemDelete(GHandle gh, int item) {
@@ -502,7 +502,7 @@ void gwinListItemDelete(GHandle gh, int item) {
gfxFree((void *)qi);
if (gh2obj->top >= item && gh2obj->top)
gh2obj->top--;
- _gwidgetUpdate(gh);
+ _gwinUpdate(gh);
break;
}
}
diff --git a/src/gwin/progressbar.c b/src/gwin/progressbar.c
index c1f9a113..90be6e43 100644
--- a/src/gwin/progressbar.c
+++ b/src/gwin/progressbar.c
@@ -123,7 +123,7 @@ void gwinProgressbarSetPosition(GHandle gh, int pos) {
}
ResetDisplayPos(gsw);
- _gwidgetUpdate(gh);
+ _gwinUpdate(gh);
#undef gsw
}
@@ -154,7 +154,7 @@ void gwinProgressbarIncrement(GHandle gh) {
gsw->pos = gsw->max;
ResetDisplayPos(gsw);
- _gwidgetUpdate(gh);
+ _gwinUpdate(gh);
#undef gsw
}
@@ -173,7 +173,7 @@ void gwinProgressbarDecrement(GHandle gh) {
gsw->pos -= gsw->res;
ResetDisplayPos(gsw);
- _gwidgetUpdate(gh);
+ _gwinUpdate(gh);
#undef gsw
}
diff --git a/src/gwin/radio.c b/src/gwin/radio.c
index 9928e32c..af7b877d 100644
--- a/src/gwin/radio.c
+++ b/src/gwin/radio.c
@@ -128,10 +128,10 @@ void gwinRadioPress(GHandle gh) {
if ((gx = gwinRadioGetActive(((GRadioObject *)gh)->group))) {
gx->flags &= ~GRADIO_FLG_PRESSED;
- _gwidgetUpdate(gx);
+ _gwinUpdate(gx);
}
gh->flags |= GRADIO_FLG_PRESSED;
- _gwidgetUpdate(gh);
+ _gwinUpdate(gh);
SendRadioEvent((GWidgetObject *)gh);
}
diff --git a/src/gwin/slider.c b/src/gwin/slider.c
index e066f798..b488f823 100644
--- a/src/gwin/slider.c
+++ b/src/gwin/slider.c
@@ -69,7 +69,7 @@ static void ResetDisplayPos(GSliderObject *gsw) {
if (x < 0 || x >= gh->width || y < 0 || y >= gh->height) {
// No - restore the slider
ResetDisplayPos(gsw);
- _gwidgetUpdate(gh);
+ _gwinUpdate(gh);
return;
}
#endif
@@ -92,7 +92,7 @@ static void ResetDisplayPos(GSliderObject *gsw) {
}
ResetDisplayPos(gsw);
- _gwidgetUpdate(gh);
+ _gwinUpdate(gh);
// Generate the event
SendSliderEvent(gw);
@@ -122,7 +122,7 @@ static void ResetDisplayPos(GSliderObject *gsw) {
}
// Update the display
- _gwidgetUpdate(&gw->g);
+ _gwinUpdate(&gw->g);
#undef gsw
}
#endif
@@ -164,7 +164,7 @@ static void ResetDisplayPos(GSliderObject *gsw) {
gsw->pos = (uint16_t)((uint32_t)value*(gsw->max-gsw->min)/max + gsw->min);
ResetDisplayPos(gsw);
- _gwidgetUpdate((GHandle)gw);
+ _gwinUpdate((GHandle)gw);
// Generate the event
SendSliderEvent(gw);
@@ -267,7 +267,7 @@ void gwinSliderSetPosition(GHandle gh, int pos) {
else gsw->pos = pos;
}
ResetDisplayPos(gsw);
- _gwidgetUpdate(gh);
+ _gwinUpdate(gh);
#undef gsw
}