diff options
Diffstat (limited to 'src/gwin/gwm.c')
-rw-r--r-- | src/gwin/gwm.c | 134 |
1 files changed, 99 insertions, 35 deletions
diff --git a/src/gwin/gwm.c b/src/gwin/gwm.c index 3140b03f..c5e0f956 100644 --- a/src/gwin/gwm.c +++ b/src/gwin/gwm.c @@ -28,7 +28,8 @@ 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_Redim(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h); +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); @@ -38,7 +39,8 @@ static const gwmVMT GNullWindowManagerVMT = { WM_Add, WM_Delete, WM_Redraw, - WM_Redim, + WM_Size, + WM_Move, WM_Raise, WM_MinMax, }; @@ -47,7 +49,7 @@ static const GWindowManager GNullWindowManager = { &GNullWindowManagerVMT, }; -gfxQueueASync _GWINList; +static gfxQueueASync _GWINList; GWindowManager * _GWINwm; #if GFX_USE_GTIMER static GTimer RedrawTimer; @@ -114,11 +116,9 @@ void gwinRedrawDisplay(GDisplay *g, bool_t preserve) { (void) param; #endif - const gfxQueueASyncItem * qi; GHandle gh; - for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) { - gh = QItem2GWindow(qi); + 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) @@ -150,8 +150,11 @@ static bool_t WM_Add(GHandle gh, const GWindowInit *pInit) { // Put it on the end of the queue gfxQueueASyncPut(&_GWINList, &gh->wmq); - // Make sure the size is valid - WM_Redim(gh, pInit->x, pInit->y, pInit->width, pInit->height); + // Make sure the size/position is valid - prefer position over size. + gh->width = MIN_WIN_WIDTH; gh->height = MIN_WIN_HEIGHT; + gh->x = gh->y = 0; + WM_Move(gh, pInit->x, pInit->y); + WM_Size(gh, pInit->width, pInit->height); return TRUE; } @@ -161,15 +164,20 @@ static void WM_Delete(GHandle gh) { } static void WM_Redraw(GHandle gh, int flags) { - if ((gh->flags & GWIN_FLG_VISIBLE)) { + #if GWIN_NEED_CONTAINERS + redo_redraw: + #endif + 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); + if (!(flags & GWIN_WMFLG_KEEPCLIP)) + 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); + if (!(flags & GWIN_WMFLG_KEEPCLIP)) + 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) @@ -184,42 +192,93 @@ static void WM_Redraw(GHandle gh, int flags) { } else if (!(flags & GWIN_WMFLG_NOBGCLEAR)) { #if GDISP_NEED_CLIP - gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height); + 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; + } #endif gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor()); } } -static void WM_Redim(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h) { - // This is the simplest way of doing it - just clip the the screen - // If it won't fit on the screen move it around until it does. - if (x < 0) { w += x; x = 0; } - if (y < 0) { h += y; y = 0; } - if (x > gdispGGetWidth(gh->display)-MIN_WIN_WIDTH) x = gdispGGetWidth(gh->display)-MIN_WIN_WIDTH; - if (y > gdispGGetHeight(gh->display)-MIN_WIN_HEIGHT) y = gdispGGetHeight(gh->display)-MIN_WIN_HEIGHT; - if (w < MIN_WIN_WIDTH) { w = MIN_WIN_WIDTH; } - if (h < MIN_WIN_HEIGHT) { h = MIN_WIN_HEIGHT; } - if (x+w > gdispGGetWidth(gh->display)) w = gdispGGetWidth(gh->display) - x; - if (y+h > gdispGGetHeight(gh->display)) h = gdispGGetHeight(gh->display) - y; +static void WM_Size(GHandle gh, coord_t w, coord_t h) { + // Give it a minimum size + if (w < MIN_WIN_WIDTH) w = MIN_WIN_WIDTH; + if (h < MIN_WIN_HEIGHT) h = MIN_WIN_HEIGHT; + + #if GWIN_NEED_CONTAINERS + if (gh->parent) { + // Clip to the container + if (gh->x+w > gh->parent->x+gh->parent->width) w = gh->parent->x + gh->parent->width - gh->x; + if (gh->y+h > gh->parent->y+gh->parent->height) h = gh->parent->y + gh->parent->height - gh->y; + ((const gcontainerVMT *)gh->parent->vmt)->AdjustSize(gh, &w, &h); + } + #endif + + // Clip to the screen + if (gh->x+w > gdispGGetWidth(gh->display)) w = gdispGGetWidth(gh->display) - gh->x; + if (gh->y+h > gdispGGetHeight(gh->display)) h = gdispGGetHeight(gh->display) - gh->y; // If there has been no resize just exit - if (gh->x == x && gh->y == y && gh->width == w && gh->height == h) + if (gh->width == w && gh->height == h) return; - // Clear the old area - if ((gh->flags & GWIN_FLG_VISIBLE)) { - #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, gwinGetDefaultBgColor()); + // Clear the old area and then 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); + } else { + gh->width = w; gh->height = h; } +} + +static void WM_Move(GHandle gh, coord_t x, coord_t y) { + #if GWIN_NEED_CONTAINERS + if (gh->parent) { + // Clip to the parent + if (x < 0) x = 0; + if (y < 0) y = 0; + if (x > gh->parent->width-gh->width) x = gh->parent->width-gh->width; + if (y > gh->parent->height-gh->height) y = gh->parent->height-gh->height; + + // Allow the parent to adjust it + ((const gcontainerVMT *)gh->parent->vmt)->AdjustPosition(gh, &x, &y); + + // Convert to absolute position + x += gh->parent->x; + y += gh->parent->y; + } + #endif - // Set the new size - gh->x = x; gh->y = y; - gh->width = w; gh->height = h; + // Clip to the screen + if (x < 0) x = 0; + if (y < 0) y = 0; + if (x > gdispGGetWidth(gh->display)-gh->width) x = gdispGGetWidth(gh->display)-gh->width; + if (y > gdispGGetHeight(gh->display)-gh->height) y = gdispGGetHeight(gh->display)-gh->height; - // Redraw the window (if possible) - WM_Redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR); + // If there has been no move just exit + if (gh->x == x && gh->y == y) + return; + + // 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); + } else { + gh->x = x; gh->y = y; + } } static void WM_MinMax(GHandle gh, GWindowMinMax minmax) { @@ -230,6 +289,7 @@ static void WM_MinMax(GHandle gh, GWindowMinMax minmax) { static void WM_Raise(GHandle gh) { // Take it off the list and then put it back on top // The order of the list then reflects the z-order. + gfxQueueASyncRemove(&_GWINList, &gh->wmq); gfxQueueASyncPut(&_GWINList, &gh->wmq); @@ -237,5 +297,9 @@ static void WM_Raise(GHandle gh) { WM_Redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR); } +GHandle gwinGetNextWindow(GHandle gh) { + return gh ? (GHandle)gfxQueueASyncNext(&gh->wmq) : (GHandle)gfxQueueASyncPeek(&_GWINList); +} + #endif /* GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER */ /** @} */ |