aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2015-08-16 21:53:47 +1000
committerinmarket <andrewh@inmarket.com.au>2015-08-16 21:53:47 +1000
commit15e7342fd7b21b76a565561a3caafee394e70c88 (patch)
treeaeb6898cfdbcb875f4b109d202f2b4560df42021 /src
parent377fe644d1233e955dfd05e40fa9d335447de325 (diff)
downloaduGFX-15e7342fd7b21b76a565561a3caafee394e70c88.tar.gz
uGFX-15e7342fd7b21b76a565561a3caafee394e70c88.tar.bz2
uGFX-15e7342fd7b21b76a565561a3caafee394e70c88.zip
Updates to focus.
Diffstat (limited to 'src')
-rw-r--r--src/gwin/gwin.h25
-rw-r--r--src/gwin/gwin_class.h51
-rw-r--r--src/gwin/gwin_textedit.c60
-rw-r--r--src/gwin/gwin_textedit.h25
-rw-r--r--src/gwin/gwin_widget.c182
-rw-r--r--src/gwin/gwin_widget.h30
-rw-r--r--src/gwin/gwin_wm.c57
7 files changed, 250 insertions, 180 deletions
diff --git a/src/gwin/gwin.h b/src/gwin/gwin.h
index 4b29f1ee..cc0d44f1 100644
--- a/src/gwin/gwin.h
+++ b/src/gwin/gwin.h
@@ -553,31 +553,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
*
* @param[in] gh The window handle
diff --git a/src/gwin/gwin_class.h b/src/gwin/gwin_class.h
index 03d2d506..ad6df423 100644
--- a/src/gwin/gwin_class.h
+++ b/src/gwin/gwin_class.h
@@ -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__)
diff --git a/src/gwin/gwin_textedit.c b/src/gwin/gwin_textedit.c
index 99708a0a..5ea8936a 100644
--- a/src/gwin/gwin_textedit.c
+++ b/src/gwin/gwin_textedit.c
@@ -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);
-
- return (GHandle)widget;
-}
-
-void gwinTexteditSetBorder(GHandle gh, bool_t border)
-{
- // Is it a valid handle?
- if (gh->vmt != (gwinVMT*)&texteditVMT) {
- return;
- }
+ gwinSetVisible(&wt->w.g, pInit->g.show);
- 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) {
diff --git a/src/gwin/gwin_textedit.h b/src/gwin/gwin_textedit.h
index 5b0cea85..f83233b4 100644
--- a/src/gwin/gwin_textedit.h
+++ b/src/gwin/gwin_textedit.h
@@ -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
}
diff --git a/src/gwin/gwin_widget.c b/src/gwin/gwin_widget.c
index 47e60e82..6ef148a6 100644
--- a/src/gwin/gwin_widget.c
+++ b/src/gwin/gwin_widget.c
@@ -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;
diff --git a/src/gwin/gwin_widget.h b/src/gwin/gwin_widget.h
index 3aa1b9f1..5239b6b8 100644
--- a/src/gwin/gwin_widget.h
+++ b/src/gwin/gwin_widget.h
@@ -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
diff --git a/src/gwin/gwin_wm.c b/src/gwin/gwin_wm.c
index 52f7a1aa..41fc385d 100644
--- a/src/gwin/gwin_wm.c
+++ b/src/gwin/gwin_wm.c
@@ -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;