Updates to focus.

ugfx_release_2.6
inmarket 2015-08-16 21:53:47 +10:00
parent 377fe644d1
commit 15e7342fd7
9 changed files with 261 additions and 184 deletions

View File

@ -48,13 +48,15 @@
#define GDISP_NEED_CLIP TRUE
#define GDISP_NEED_TEXT TRUE
#define GDISP_NEED_TEXT_KERNING TRUE
#define GDISP_NEED_STARTUP_LOGO TRUE
#define GDISP_NEED_MULTITHREAD TRUE
/* GDISP fonts to include */
#define GDISP_INCLUDE_FONT_UI2 TRUE
#define GDISP_INCLUDE_FONT_DEJAVUSANS16 TRUE
/* Features for the GWIN subsystem. */
#define GWIN_NEED_WINDOWMANAGER TRUE
#define GWIN_NEED_WIDGET TRUE
#define GWIN_NEED_CONSOLE TRUE
#define GWIN_NEED_TEXTEDIT TRUE
#define GWIN_NEED_BUTTON TRUE
@ -63,5 +65,9 @@
#define GINPUT_NEED_MOUSE TRUE
#define GINPUT_NEED_KEYBOARD TRUE
/* Features for the GQUEUE subsystem. */
#define GFX_USE_GQUEUE TRUE
#define GQUEUE_NEED_ASYNC TRUE
#endif /* _GFXCONF_H */

View File

@ -49,13 +49,14 @@
/* Our custom yellow style */
static const GWidgetStyle YellowWidgetStyle = {
Yellow, // window background
HTML2COLOR(0x800000), // focus
// enabled color set
{
HTML2COLOR(0x0000FF), // text
HTML2COLOR(0x404040), // edge
HTML2COLOR(0xE0E0E0), // fill
HTML2COLOR(0xE0E0E0), // progress - inactive area
HTML2COLOR(0xE0E0E0) // progress - inactive area
},
// disabled color set
@ -63,7 +64,7 @@ static const GWidgetStyle YellowWidgetStyle = {
HTML2COLOR(0xC0C0C0), // text
HTML2COLOR(0x808080), // edge
HTML2COLOR(0xE0E0E0), // fill
HTML2COLOR(0xC0E0C0), // progress - active area
HTML2COLOR(0xC0E0C0) // progress - active area
},
// pressed color set
@ -72,7 +73,7 @@ static const GWidgetStyle YellowWidgetStyle = {
HTML2COLOR(0x404040), // edge
HTML2COLOR(0x808080), // fill
HTML2COLOR(0x00E000), // progress - active area
},
}
};
/* The variables we need */

View File

@ -552,31 +552,6 @@ extern "C" {
*/
GHandle gwinGetNextWindow(GHandle gh);
/**
* @brief Set the focus to a specific widget
*
* @details The widget that is currently in focus is the widget that
* receives mouse and keyboard events.
* Passing NULL will remove the focus from any widget.
*
* @param[in] gh The widget handle. Non-widget handles will be ignored.
*
* @api
*/
void gwinSetFocus(GHandle gh);
/**
* @brief Get the widget that is currently in focus
*
* @details The widget that is currently in focus is the widget that
* receives mouse and keyboard events.
*
* @return The handle of the widget that is currently in focus. May be NULL.
*
* @api
*/
GHandle gwinGetFocus(void);
/**
* @brief Set a window or widget to flash
*

View File

@ -256,9 +256,8 @@ void _gwinDrawEnd(GHandle gh);
* @param[in] gh The window
* @param[in] how Do we wait for the lock?
*
* @note This call will delete the window. If called without the
* drawing lock 'how' must be REDRAW_WAIT. If called with the drawing
* lock 'how' must be REDRAW_INSESSION.
* @note If called without the drawing lock 'how' must be REDRAW_WAIT.
* If called with the drawing lock 'how' must be REDRAW_INSESSION.
*
* @notapi
*/
@ -322,6 +321,50 @@ bool_t _gwinWMAdd(GHandle gh, const GWindowInit *pInit);
*/
void _gwinSendEvent(GHandle gh, GEventType type);
#if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || defined(__DOXYGEN__)
/**
* @brief Move the focus off the current focus window.
*
* @notapi
*/
void _gwinMoveFocus(void);
/**
* @brief Do focus fixup's after a change of state for a window.
* @details If a focus window has become invisible or disabled then
* the focus must be taken away from it. If there is no focus
* window and this window is eligible then this window becomes
* the focus.
*
* @param[in] gh The window
*
* @note This routine does not actually do a redraw. It assumes that surrounding code
* will because of the change of state that lead to this being called.
*
* @notapi
*/
void _gwinFixFocus(GHandle gh);
/**
* @brief Draw a simple focus rectangle in the default style.
*
* @param[in] gw The widget
* @param[in] x, y The start x, y position (relative to the window)
* @param[in] cx, cy The width & height of the rectangle
*
* @note Assumes the widget is in a state where it can draw.
* @note Nothing is drawn if the window doesn't have focus.
* @note The focus rectangle may be more than one pixel thick and may
* not be a continuous line.
*
* @notapi
*/
void _gwidgetDrawFocusRect(GWidgetObject *gw, coord_t x, coord_t y, coord_t cx, coord_t cy);
#else
#define _gwinFixFocus(gh)
#define _gwidgetDrawFocusRect(gh,x,y,cx,cy)
#endif
#if GWIN_NEED_FLASHING || defined(__DOXYGEN__)
/**
@ -335,6 +378,8 @@ bool_t _gwinWMAdd(GHandle gh, const GWindowInit *pInit);
*/
const GColorSet *_gwinGetFlashedColor(GWidgetObject *gw, const GColorSet *pcol, bool_t flashOffState);
#endif
#else
#define _gwinFixFocus(gh)
#endif
#if GWIN_NEED_CONTAINERS || defined(__DOXYGEN__)

View File

@ -23,9 +23,6 @@ const int FOCUS_BORDER_THICKNESS = 3;
const int CURSOR_PADDING_LEFT = 0;
const int CURSOR_EXTRA_HEIGHT = 1;
// Some flags
#define GTEXTEDIT_FLG_BORDER (GWIN_FIRST_CONTROL_FLAG << 0)
// Macros to assist in data type conversions
#define gh2obj ((GTexteditObject *)gh)
#define gw2obj ((GTexteditObject *)gw)
@ -65,7 +62,7 @@ static void _shiftTextRight(char* buffer, size_t bufferSize, size_t index, char
#if GINPUT_NEED_KEYBOARD
static void _keyboardEvent(GWidgetObject* gw, GEventKeyboard* pke)
static void TextEditKeyboard(GWidgetObject* gw, GEventKeyboard* pke)
{
// Only react on KEYDOWN events. Ignore KEYUP events.
if (pke->keystate & GKEYSTATE_KEYUP) {
@ -116,9 +113,8 @@ static void _shiftTextRight(char* buffer, size_t bufferSize, size_t index, char
// Add a new character
else {
// Prevent buffer overflow
if (gw2obj->cursorPos >= gw2obj->bufferSize) {
if (gw2obj->cursorPos >= gw2obj->maxSize)
return;
}
// Shift everything right from the cursor by one character. This includes the '\0'. Then inser the new character.
_shiftTextRight(gw2obj->textBuffer, gw2obj->bufferSize, gw2obj->cursorPos++, pke->c[0]);
@ -152,7 +148,7 @@ static const gwidgetVMT texteditVMT = {
#endif
#if GINPUT_NEED_KEYBOARD
{
_keyboardEvent // Process keyboard key down events
TextEditKeyboard // Process keyboard key down events
},
#endif
#if GINPUT_NEED_TOGGLE
@ -174,50 +170,33 @@ static const gwidgetVMT texteditVMT = {
#endif
};
GHandle gwinGTexteditCreate(GDisplay* g, GTexteditObject* widget, GWidgetInit* pInit, size_t bufSize)
GHandle gwinGTexteditCreate(GDisplay* g, GTexteditObject* wt, GWidgetInit* pInit, size_t maxSize)
{
uint16_t flags = 0;
// Create the underlying widget
if (!(widget = (GTexteditObject*)_gwidgetCreate(g, &widget->w, pInit, &texteditVMT))) {
if (!(wt = (GTexteditObject*)_gwidgetCreate(g, &wt->w, pInit, &texteditVMT)))
return 0;
}
// Allocate the text buffer
widget->bufferSize = bufSize;
widget->textBuffer = gfxAlloc(widget->bufferSize);
if (widget->textBuffer == 0) {
wt->maxSize = maxSize;
wt->textBuffer = gfxAlloc(widget->maxSize);
if (wt->textBuffer == 0)
return 0;
}
// Initialize the text buffer
size_t i = 0;
for (i = 0; i < bufSize; i++) {
widget->textBuffer[i] = '\0';
wt->textBuffer[i] = '\0';
}
// Set text and cursor position
strncpy(widget->textBuffer, gwinGetText((GHandle)widget), widget->bufferSize); // FixMe: pInit->text leads to a segfault
widget->cursorPos = strlen(widget->textBuffer);
strncpy(wt->textBuffer, gwinGetText((GHandle)wt), wt->maxSize); // FixMe: pInit->text leads to a segfault
wt->cursorPos = strlen(wt->textBuffer);
widget->w.g.flags |= flags | GTEXTEDIT_FLG_BORDER;;
gwinSetVisible(&widget->w.g, pInit->g.show);
gwinSetVisible(&wt->w.g, pInit->g.show);
return (GHandle)widget;
}
void gwinTexteditSetBorder(GHandle gh, bool_t border)
{
// Is it a valid handle?
if (gh->vmt != (gwinVMT*)&texteditVMT) {
return;
}
if (border) {
gh2obj->w.g.flags |= GTEXTEDIT_FLG_BORDER;
} else {
gh2obj->w.g.flags &=~ GTEXTEDIT_FLG_BORDER;
}
return (GHandle)wt;
}
static void gwinTexteditDefaultDraw(GWidgetObject* gw, void* param)
@ -238,18 +217,11 @@ static void gwinTexteditDefaultDraw(GWidgetObject* gw, void* param)
gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background);
gdispGFillStringBox(gw->g.display, gw->g.x + TEXT_PADDING_LEFT, gw->g.y, gw->g.width, gw->g.height, gw->text, gw->g.font, textColor, gw->pstyle->background, justifyLeft);
// Render border (if supposed to)
if (gw2obj->w.g.flags & GTEXTEDIT_FLG_BORDER) {
gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, (gw->g.flags & GWIN_FLG_SYSENABLED) ? gw->pstyle->enabled.edge : gw->pstyle->disabled.edge);
}
// Render border (always)
gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, (gw->g.flags & GWIN_FLG_SYSENABLED) ? gw->pstyle->enabled.edge : gw->pstyle->disabled.edge);
// Render highlighted border of focused
if (gwinGetFocus() == (GHandle)gw) {
int i = 0;
for (i = 0; i < FOCUS_BORDER_THICKNESS; i++) {
gdispGDrawBox(gw->g.display, gw->g.x+i, gw->g.y+i, gw->g.width-2*i, gw->g.height-2*i, gw->pstyle->focus);
}
}
_gwidgetDrawFocusRect(gw, 0, 0, gw->g.width-1, gw->g.height-1);
// Render cursor (if focused)
if (gwinGetFocus() == (GHandle)gw) {

View File

@ -33,7 +33,7 @@ typedef struct GTexteditObject {
GWidgetObject w;
char* textBuffer;
size_t bufferSize;
size_t maxSize;
uint16_t cursorPos;
} GTexteditObject;
@ -48,28 +48,17 @@ extern "C" {
* is abstracted through the GINPUT module.
*
* @param[in] g The GDisplay on which the textedit should be displayed
* @param[in] widget The TextEdit structure to initialise. If this is NULL, the structure is dynamically allocated.
* @param[in] wt The TextEdit structure to initialise. If this is NULL, the structure is dynamically allocated.
* @param[in] pInit The initialisation parameters to use.
* @param[in] bufSize The maximum number of characters the TextEdit widget can hold.
* @param[in] maxSize The maximum number of characters the TextEdit widget can hold.
*
* @return NULL if there is no resultat drawing area, otherwise the widget handle.
* @return NULL if there is no resultant drawing area, otherwise the widget handle.
*
* @note If the initial text set is larger than maxSize then the text is truncated at maxSize characters.
* @api
*/
GHandle gwinGTexteditCreate(GDisplay* g, GTexteditObject* widget, GWidgetInit* pInit, size_t bufSize);
#define gwinTexteditCreate(w, pInit, bufSize) gwinGTexteditCreate(GDISP, w, pInit, bufSize)
/**
* @brief Border settings for the default rendering routine
*
* @note Border is enabled by default.
*
* @param[in] gh The widget handle (must be a TextEdit handle)
* @param[in] border Shall a border be rendered?
*
* @api
*/
void gwinTexteditSetBorder(GHandle gh, bool_t border);
GHandle gwinGTexteditCreate(GDisplay* g, GTexteditObject* wt, GWidgetInit* pInit, size_t maxSize);
#define gwinTexteditCreate(wt, pInit, maxSize) gwinGTexteditCreate(GDISP, wt, pInit, maxSize)
#ifdef __cplusplus
}

View File

@ -21,6 +21,11 @@
// Our listener for events for widgets
static GListener gl;
#if GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD
// Our current focus window
static GHandle _widgetInFocus;
#endif
// Our default style - a white background theme
const GWidgetStyle WhiteWidgetStyle = {
HTML2COLOR(0xFFFFFF), // window background
@ -139,6 +144,14 @@ static void gwidgetEvent(void *param, GEvent *pe) {
if (gh && (gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED)) == (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED)) {
if ((pme->buttons & GMETA_MOUSE_DOWN)) {
gh->flags |= GWIN_FLG_MOUSECAPTURE;
#if GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD
// We should try and capture the focus on this window.
// If we can't no window should have the focus
if (!gwinSetFocus(gh))
gwinSetFocus(0);
#endif
if (wvmt->MouseDown)
wvmt->MouseDown(gw, pme->x - gh->x, pme->y - gh->y);
}
@ -150,79 +163,14 @@ static void gwidgetEvent(void *param, GEvent *pe) {
case GEVENT_KEYBOARD:
// If Tab key pressed then set focus to next widget
if (pke->bytecount == 1 && pke->c[0] == GKEY_TAB) {
// Only react on KEYDOWN events. Ignore KEYUP events.
if (pke->keystate & GKEYSTATE_KEYUP)
break;
// Get the next widget
bool_t foundWidget = FALSE;
bool_t endOfListDetected = FALSE;
GHandle nextWidget = gwinGetFocus();
GHandle prevWidget = gwinGetFocus();
do {
nextWidget = gwinGetNextWindow(nextWidget);
foundWidget = TRUE;
// Begin with the first one if this is the last one
if (nextWidget == 0) {
foundWidget = FALSE;
// We go through the list twice - just to be sure
if (endOfListDetected)
break;
endOfListDetected = TRUE;
continue;
}
// Check whether this is a window or a widget
if (!gwinIsWidget(nextWidget)) {
foundWidget = FALSE;
continue;
}
// Only focus on a widget that is visible and enabled
if (!(nextWidget->flags & GWIN_FLG_SYSVISIBLE) || !(nextWidget->flags & GWIN_FLG_ENABLED)) {
foundWidget = FALSE;
continue;
}
// When using the TAB key we only focus on widgets that process keyboard events
if (((gwidgetVMT*)nextWidget->vmt)->KeyboardEvent == 0) {
foundWidget = FALSE;
continue;
}
} while (foundWidget == FALSE);
gwinSetFocus(nextWidget);
// Redraw the new and the previous focused widget because they usually render differently when
// they are not focused anymore (eg. no blinking cursor)
if (prevWidget != 0)
gwinRedraw(prevWidget);
if (nextWidget != 0)
gwinRedraw(nextWidget);
if (!(pke->keystate & GKEYSTATE_KEYUP))
_gwinMoveFocus();
break;
}
// Otherise, send keyboard events only to widget in focus
GHandle widgetInFocus = gwinGetFocus();
if (widgetInFocus != 0) {
// Make sure that it is a widget
if (!gwinIsWidget(widgetInFocus))
break;
// Make sure that the widget is enabled and visible
if (!(widgetInFocus->flags & GWIN_FLG_SYSVISIBLE) || !(widgetInFocus->flags & GWIN_FLG_ENABLED))
break;
// Check whether this widget provides a method for handling keyboard events
if (((gwidgetVMT*)widgetInFocus->vmt)->KeyboardEvent == 0)
break;
// If we got this far we can finally pass the event
((gwidgetVMT*)widgetInFocus->vmt)->KeyboardEvent((GWidgetObject*)widgetInFocus, pke);
}
// Otherwise, send keyboard events only to widget in focus
if (_widgetInFocus)
((gwidgetVMT*)_widgetInFocus->vmt)->KeyboardEvent((GWidgetObject*)_widgetInFocus, pke);
break;
#endif
@ -278,6 +226,96 @@ static void gwidgetEvent(void *param, GEvent *pe) {
#undef pde
}
#if GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD
GHandle gwinGetFocus(void) {
return _widgetInFocus;
}
bool_t gwinSetFocus(GHandle gh) {
GHandle oldFocus;
// Do we already have the focus?
if (gh == _widgetInFocus)
return TRUE;
// The new window must be NULLL or a visible enabled widget with a keyboard handler
if (!gh || ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)
&& ((gwidgetVMT*)gh->vmt)->KeyboardEvent)) {
// Move the current focus
oldFocus = _widgetInFocus;
_widgetInFocus = gh;
if (oldFocus) _gwinUpdate(oldFocus);
if (gh) _gwinUpdate(gh);
return TRUE;
}
return FALSE;
}
void _gwinMoveFocus(void) {
GHandle gh;
// Find a new focus window (one may or may not exist).
for(gh = gwinGetNextWindow(_widgetInFocus); gh && gh != _widgetInFocus; gh = gwinGetNextWindow(gh)) {
if (gwinSetFocus(gh))
return;
}
gwinSetFocus(0);
}
void _gwinFixFocus(GHandle gh) {
GHandle oldFocus;
if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)
&& ((gwidgetVMT*)gh->vmt)->KeyboardEvent) {
// We are a candidate to be able to claim the focus
// Claim the focus if no-one else has
if (!_widgetInFocus)
_widgetInFocus = gh;
return;
}
// We have lost any right to the focus
// Did we have the focus
if (gh != _widgetInFocus)
return;
// We did - we need to find a new focus window
oldFocus = _widgetInFocus;
for(gh = gwinGetNextWindow(oldFocus); gh && gh != oldFocus; gh = gwinGetNextWindow(gh)) {
// Must be a visible enabled widget with a keyboard handler
if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)
&& ((gwidgetVMT*)gh->vmt)->KeyboardEvent) {
// Grab the focus for the new window
_widgetInFocus = gh;
// This new window still needs to be marked for redraw (but don't actually do it yet).
gh->flags |= GWIN_FLG_NEEDREDRAW;
RedrawPending |= DOREDRAW_VISIBLES;
return;
}
}
// No-one has the right to the focus
_widgetInFocus = 0;
}
void _gwidgetDrawFocusRect(GWidgetObject *gw, coord_t x, coord_t y, coord_t cx, coord_t cy) {
// Don't do anything if we don't have the focus
if (&gw->g != _widgetInFocus)
return;
// Use the very simplest possible focus rectangle for now.
gdispGDrawBox(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, gw->pstyle.focus);
}
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
static GHandle FindToggleUser(uint16_t instance) {
GHandle gh;
@ -355,6 +393,10 @@ void _gwidgetDestroy(GHandle gh) {
uint16_t role, instance;
#endif
// Make the window is invisible so it is not eligible for focus
gh->flags &= ~GWIN_FLG_VISIBLE;
_gwinFixFocus(gh);
// Deallocate the text (if necessary)
if ((gh->flags & GWIN_FLG_ALLOCTXT)) {
gh->flags &= ~GWIN_FLG_ALLOCTXT;

View File

@ -356,6 +356,36 @@ bool_t gwinAttachListener(GListener *pl);
bool_t gwinAttachDial(GHandle gh, uint16_t role, uint16_t instance);
#endif
#if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || defined(__DOXYGEN__)
/**
* @brief Set the keyboard focus to a specific window
* @return Returns TRUE if the focus could be set to that window
*
* @param[in] gh The window
*
* @note Passing NULL will remove the focus from any window.
* @note Only visible enabled widgets are capable of getting the focus.
*
* @api
*/
bool_t gwinSetFocus(GHandle gh);
/**
* @brief Get the widget that is currently in focus
*
* @details The widget that is currently in focus is the widget that
* receives mouse and keyboard events.
*
* @return The handle of the widget that is currently in focus. May be NULL.
*
* @api
*/
GHandle gwinGetFocus(void);
#else
#define gwinGetFocus() (0)
#define gwinSetFocus(gh) (FALSE)
#endif
#ifdef __cplusplus
}
#endif

View File

@ -162,7 +162,6 @@
extern const GWindowManager GNullWindowManager;
GWindowManager * _GWINwm;
bool_t _gwinFlashState;
static GHandle _widgetInFocus;
static gfxSem gwinsem;
static gfxQueueASync _GWINList;
#if GWIN_NEED_FLASHING
@ -333,14 +332,23 @@ void _gwinUpdate(GHandle gh) {
if (!gh->parent || (gh->parent->flags & GWIN_FLG_SYSVISIBLE)) {
// We have been made visible
gh->flags |= (GWIN_FLG_SYSVISIBLE|GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW);
// Do we want to grab the focus
_gwinFixFocus(gh);
RedrawPending |= DOREDRAW_VISIBLES;
}
break;
case (GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE):
if (!gh->parent || (gh->parent->flags & GWIN_FLG_SYSVISIBLE))
break;
// Parent has been made invisible
gh->flags &= ~GWIN_FLG_SYSVISIBLE;
// No focus for us anymore
_gwinFixFocus(gh);
break;
case GWIN_FLG_SYSVISIBLE:
// We have been made invisible
@ -348,6 +356,10 @@ void _gwinUpdate(GHandle gh) {
if (!gh->parent || (gh->parent->flags & GWIN_FLG_SYSVISIBLE)) {
// The parent is visible so we must clear the area we took
gh->flags |= (GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW);
// No focus for us anymore
_gwinFixFocus(gh);
RedrawPending |= DOREDRAW_INVISIBLES;
}
break;
@ -457,6 +469,10 @@ void gwinRedraw(GHandle gh) {
if (visible) {
if (!(gh->flags & GWIN_FLG_VISIBLE)) {
gh->flags |= (GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE|GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW);
// Do we want to grab the focus
_gwinFixFocus(gh);
RedrawPending |= DOREDRAW_VISIBLES;
TriggerRedraw();
}
@ -464,6 +480,10 @@ void gwinRedraw(GHandle gh) {
if ((gh->flags & GWIN_FLG_VISIBLE)) {
gh->flags &= ~(GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE);
gh->flags |= (GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW);
// No focus for us anymore
_gwinFixFocus(gh);
RedrawPending |= DOREDRAW_INVISIBLES;
TriggerRedraw();
}
@ -484,6 +504,10 @@ void gwinRedraw(GHandle gh) {
for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
if ((gh->flags & (GWIN_FLG_SYSENABLED|GWIN_FLG_ENABLED)) == GWIN_FLG_ENABLED && (!gh->parent || (gh->parent->flags & GWIN_FLG_SYSENABLED))) {
gh->flags |= GWIN_FLG_SYSENABLED; // Fix it
// Do we want to grab the focus
_gwinFixFocus(gh);
_gwinUpdate(gh);
}
}
@ -497,6 +521,10 @@ void gwinRedraw(GHandle gh) {
for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
if ((gh->flags & GWIN_FLG_SYSENABLED) && (!(gh->flags & GWIN_FLG_ENABLED) || (gh->parent && !(gh->parent->flags & GWIN_FLG_SYSENABLED)))) {
gh->flags &= ~GWIN_FLG_SYSENABLED; // Fix it
// No focus for us anymore
_gwinFixFocus(gh);
_gwinUpdate(gh);
}
}
@ -508,11 +536,19 @@ void gwinRedraw(GHandle gh) {
if (enabled) {
if (!(gh->flags & GWIN_FLG_ENABLED)) {
gh->flags |= (GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED);
// Do we want to grab the focus
_gwinFixFocus(gh);
_gwinUpdate(gh);
}
} else {
if ((gh->flags & GWIN_FLG_ENABLED)) {
gh->flags &= ~(GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED);
// No focus for us anymore
_gwinFixFocus(gh);
_gwinUpdate(gh);
}
}
@ -573,25 +609,6 @@ GHandle gwinGetNextWindow(GHandle gh) {
return gh ? (GHandle)gfxQueueASyncNext(&gh->wmq) : (GHandle)gfxQueueASyncPeek(&_GWINList);
}
void gwinSetFocus(GHandle gh) {
// Passing NULL removes the focus from any widget
if (gh == 0) {
_widgetInFocus = 0;
return;
}
// Only accept widgets
if (!gwinIsWidget(gh)) {
return;
}
_widgetInFocus = gh;
}
GHandle gwinGetFocus(void) {
return _widgetInFocus;
}
#if GWIN_NEED_FLASHING
static void FlashTimerFn(void *param) {
GHandle gh;