void gwinRedrawDisplay(GDisplay *g, bool_t preserve) { GHandle gh; for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) { // 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); } }
// 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 _gwinUpdate(gh); } } } } 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 _gwinUpdate(gh); } } } } }
void _gwinRippleVisibility(void) { GHandle gh; // Check each window's visibility is consistent with its parents for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) { switch(gh->flags & (GWIN_FLG_SYSVISIBLE|GWIN_FLG_VISIBLE)) { case GWIN_FLG_VISIBLE: 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); 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; break; case GWIN_FLG_SYSVISIBLE: // We have been made invisible gh->flags &= ~GWIN_FLG_SYSVISIBLE; 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); RedrawPending |= DOREDRAW_INVISIBLES; } break; } } }
GHandle gwinRadioGetActive(uint16_t group) { GHandle gh; for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) { if (gh->vmt == (gwinVMT *)&radioVMT && ((GRadioObject *)gh)->group == group && (gh->flags & GRADIO_FLG_PRESSED)) return gh; } return 0; }
static GHandle FindDialUser(uint16_t instance) { GHandle gh; uint16_t role; for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) { if (!(gh->flags & GWIN_FLG_WIDGET)) // check if it a widget continue; for(role = 0; role < wvmt->dialroles; role++) { if (wvmt->DialGet(gw, role) == instance) return gh; } } return 0; }
void _gwinMoveFocus(void) { GHandle gh; bool_t looponce; // Find a new focus window (one may or may not exist). looponce = FALSE; for(gh = gwinGetNextWindow(_widgetInFocus); ; gh = gwinGetNextWindow(gh)) { if (!gh && !looponce) { looponce = TRUE; gh = gwinGetNextWindow(0); } if (gwinSetFocus(gh)) break; } }
void gwinSetDefaultStyle(const GWidgetStyle *pstyle, bool_t updateAll) { if (!pstyle) pstyle = &BlackWidgetStyle; if (updateAll) { GHandle gh; for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) { if ((gh->flags & GWIN_FLG_WIDGET) && ((GWidgetObject *)gh)->pstyle == defaultStyle) gwinSetStyle(gh, pstyle); else gwinRedraw(gh); } } gwinSetDefaultBgColor(pstyle->background); defaultStyle = pstyle; }
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; - FIX LATER return; } } // No-one has the right to the focus _widgetInFocus = 0; }
void _gwmDeinit(void) { GHandle gh; while((gh = gwinGetNextWindow(0))) gwinDestroy(gh); _GWINwm->vmt->DeInit(); #if !GWIN_REDRAW_IMMEDIATE gtimerDeinit(&RedrawTimer); #endif gfxQueueASyncDeinit(&_GWINList); gfxSemDestroy(&gwinsem); }
// Process an event static void gwidgetEvent(void *param, GEvent *pe) { #define pme ((GEventMouse *)pe) #define pke ((GEventKeyboard *)pe) #define pte ((GEventToggle *)pe) #define pde ((GEventDial *)pe) GHandle h; GHandle gh; #if GFX_USE_GINPUT && (GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL) uint16_t role; #endif (void) param; // Process various events switch (pe->type) { #if GFX_USE_GINPUT && GINPUT_NEED_MOUSE case GEVENT_MOUSE: case GEVENT_TOUCH: // Cycle through all windows for (gh = 0, h = gwinGetNextWindow(0); h; h = gwinGetNextWindow(h)) { // The window must be on this display and visible to be relevant if (h->display != pme->display || !(h->flags & GWIN_FLG_SYSVISIBLE)) continue; // Is the mouse currently captured by this widget? if ((h->flags & (GWIN_FLG_WIDGET|GWIN_FLG_MOUSECAPTURE)) == (GWIN_FLG_WIDGET|GWIN_FLG_MOUSECAPTURE)) { gh = h; if ((pme->buttons & GMETA_MOUSE_UP)) { gh->flags &= ~GWIN_FLG_MOUSECAPTURE; if (wvmt->MouseUp) wvmt->MouseUp(gw, pme->x - gh->x, pme->y - gh->y); } else if (wvmt->MouseMove) wvmt->MouseMove(gw, pme->x - gh->x, pme->y - gh->y); // There is only ever one captured mouse. Prevent normal mouse processing if there is a captured mouse gh = 0; break; } // Save the highest z-order window that the mouse is over if (pme->x >= h->x && pme->x < h->x + h->width && pme->y >= h->y && pme->y < h->y + h->height) gh = h; } // Process any mouse down over the highest order window if it is an enabled widget 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) || GWIN_NEED_KEYBOARD // We should try and capture the focus on this window. // If we can't then we don't change the focus gwinSetFocus(gh); #endif if (wvmt->MouseDown) wvmt->MouseDown(gw, pme->x - gh->x, pme->y - gh->y); } } break; #endif #if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD case GEVENT_KEYBOARD: // If Tab key pressed then set focus to next widget if (pke->bytecount == 1 && pke->c[0] == GKEY_TAB) { if (!(pke->keystate & GKEYSTATE_KEYUP)) _gwinMoveFocus(); break; } // Otherwise, send keyboard events only to widget in focus if (_widgetInFocus) ((gwidgetVMT*)_widgetInFocus->vmt)->KeyboardEvent((GWidgetObject*)_widgetInFocus, pke); break; #endif #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE case GEVENT_TOGGLE: // Cycle through all windows for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) { // check if it a widget that is enabled and visible if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE)) continue; for(role = 0; role < wvmt->toggleroles; role++) { if (wvmt->ToggleGet(gw, role) == pte->instance) { if (pte->on) { if (wvmt->ToggleOn) wvmt->ToggleOn(gw, role); } else { if (wvmt->ToggleOff) wvmt->ToggleOff(gw, role); } } } } break; #endif #if GFX_USE_GINPUT && GINPUT_NEED_DIAL case GEVENT_DIAL: // Cycle through all windows for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) { // check if it a widget that is enabled and visible if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE)) continue; for(role = 0; role < wvmt->dialroles; role++) { if (wvmt->DialGet(gw, role) == pte->instance) { if (wvmt->DialMove) wvmt->DialMove(gw, role, pde->value, pde->maxvalue); } } } break; #endif default: break; } #undef pme #undef pte #undef pke #undef pde }
static void WM_Redraw(GHandle gh) { #if GWIN_NEED_CONTAINERS redo_redraw: #endif if ((gh->flags & GWIN_FLG_SYSVISIBLE)) { if (gh->vmt->Redraw) gh->vmt->Redraw(gh); 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); // 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); } #if GWIN_NEED_CONTAINERS // 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 support complex clipping regions. if ((gh->flags & (GWIN_FLG_CONTAINER|GWIN_FLG_PARENTREVEAL)) == GWIN_FLG_CONTAINER) { // Container redraw is done gh->flags &= ~(GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW|GWIN_FLG_PARENTREVEAL); for(gh = gwinGetFirstChild(gh); gh; gh = gwinGetSibling(gh)) _gwinUpdate(gh); return; } #endif } else { if ((gh->flags & GWIN_FLG_BGREDRAW)) { GHandle gx; #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; // The parent is already marked for redraw - don't do it now. if ((gh->flags & GWIN_FLG_NEEDREDRAW)) return; // Use the existing clipping region and redraw now gh->flags |= (GWIN_FLG_BGREDRAW|GWIN_FLG_PARENTREVEAL); goto redo_redraw; } #endif // Clear the area to the background color gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor()); // Now loop over all windows looking for overlaps. Redraw them if they overlap the newly exposed area. for(gx = gwinGetNextWindow(0); gx; gx = gwinGetNextWindow(gx)) { if ((gx->flags & GWIN_FLG_SYSVISIBLE) && gx->display == gh->display && gx->x < gh->x+gh->width && gx->y < gh->y+gh->height && gx->x+gx->width >= gh->x && gx->y+gx->height >= gh->y) { if (gx->vmt->Redraw) gx->vmt->Redraw(gx); else // We can't redraw this window but we want full coverage so just clear the area gdispGFillArea(gx->display, gx->x, gx->y, gx->width, gx->height, gx->bgcolor); } } } } // Redraw is done gh->flags &= ~(GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW|GWIN_FLG_PARENTREVEAL); }
void _gwinFlushRedraws(GRedrawMethod how) { GHandle gh; // Do we really need to do anything? if (!RedrawPending) return; // Obtain the drawing lock if (how == REDRAW_WAIT) gfxSemWait(&gwinsem, TIME_INFINITE); else if (how == REDRAW_NOWAIT && !gfxSemWait(&gwinsem, TIME_IMMEDIATE)) // Someone is drawing - They will do the redraw when they are finished return; // Do loss of visibility first while ((RedrawPending & DOREDRAW_INVISIBLES)) { RedrawPending &= ~DOREDRAW_INVISIBLES; // Catch new requests for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) { if ((gh->flags & (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) != GWIN_FLG_NEEDREDRAW) continue; // Do the redraw #if GDISP_NEED_CLIP gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height); _GWINwm->vmt->Redraw(gh); gdispGUnsetClip(gh->display); #else _GWINwm->vmt->Redraw(gh); #endif // Postpone further redraws #if !GWIN_REDRAW_IMMEDIATE && !GWIN_REDRAW_SINGLEOP if (how == REDRAW_NOWAIT) { RedrawPending |= DOREDRAW_INVISIBLES; TriggerRedraw(); goto releaselock; } #endif } } // Do the visible windows next while ((RedrawPending & DOREDRAW_VISIBLES)) { RedrawPending &= ~DOREDRAW_VISIBLES; // Catch new requests for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) { if ((gh->flags & (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) != (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) continue; // 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 !GWIN_REDRAW_IMMEDIATE && !GWIN_REDRAW_SINGLEOP if (how == REDRAW_NOWAIT) { while((gh = gwinGetNextWindow(gh))) { if ((gh->flags & (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) { RedrawPending |= DOREDRAW_VISIBLES; TriggerRedraw(); break; } } goto releaselock; } #endif } } #if !GWIN_REDRAW_IMMEDIATE && !GWIN_REDRAW_SINGLEOP releaselock: #endif // Release the lock if (how == REDRAW_WAIT || how == REDRAW_NOWAIT) gfxSemSignal(&gwinsem); }