diff --git a/roo_e/src/gui/wmwindow.c b/roo_e/src/gui/wmwindow.c index e8cba0b..82fe6cb 100644 --- a/roo_e/src/gui/wmwindow.c +++ b/roo_e/src/gui/wmwindow.c @@ -28,6 +28,12 @@ #include "font.h" +typedef struct DamageListS { + RectT rect; + SurfaceT *surface; +} DamageListT; + + uint8_t __MAGIC_WINDOW = 0; @@ -666,6 +672,8 @@ void wmStartup(void) { void wmUpdate(EventT *event) { int16_t i; + int16_t j; + int16_t k; PointT widgetLocal; int16_t x2; int16_t y2; @@ -673,6 +681,12 @@ void wmUpdate(EventT *event) { WidgetT *widget; WidgetT *widgetOver = NULL; WindowT *win = NULL; + WindowT *win2 = NULL; + RectT *rect; + RectT **rects = NULL; + DamageListT **damageList = NULL; + DamageListT *damageItem = NULL; + uint8_t found; ClickRawInputT rawEvent = { 0 }; static uint8_t resizing = 0; static PointT resizeOffset = { 0 }; @@ -915,6 +929,159 @@ void wmUpdate(EventT *event) { break; } // Left button processing. + + // Calculate visible rectangle list. + // + // Start with the top window and divide it into smaller rectangles + // using the edges of every other window. Add these to the "damage + // list". + // + // Then iterate through the remaining windows from top to bottom + // dividing them with the edges of every other window. When finished + // with each window, compare the list of new rectangles to the existing + // damage list. Add any rectangles that are not already there. + // + // Finally do the same as the remaining windows with the entire screen. + + // Iterate over all windows, top to bottom. + for (i=0; i<=arrlen(_windowList); i++) { + + // New rectangle. + NEW(RectT, rect); + + // Are we comparing the desktop? + if (i == arrlen(_windowList)) { + // Yes. Fake a window. + win = NULL; + rect->x = 0; + rect->y = 0; + rect->x2 = videoDisplayWidthGet() - 1; + rect->y2 = videoDisplayHeightGet() - 1; + } else { + // Get this window. + win = (WindowT *)_windowList[i]; + rect->x = win->base.r.x; + rect->y = win->base.r.y; + rect->x2 = win->base.r.x + win->base.r.w - 1; + rect->y2 = win->base.r.y + win->base.r.h - 1; + } + + // Add this window to the rectangle list. + arrput(rects, rect); + + // Iterate over all the other windows. + for (j=0; jbase.r.x + win2->base.r.w - 1; + y2 = win2->base.r.y + win2->base.r.h - 1; + + // Check the edges of this window against all the + // rectangles in the current rectangle list. Split + // and create new rectangles on any lines that intersect. + for (k=0; kbase.r.y > rects[k]->y) && (win2->base.r.y < rects[k]->y2)) { + NEW(RectT, rect); + rect->x = rects[k]->x; + rect->x2 = rects[k]->x2; + rect->y2 = rects[k]->y2; + rects[k]->y2 = win2->base.r.y; + rect->y = win2->base.r.y; + arrput(rects, rect); + } + // Compare Window Bottom + if ((y2 > rects[k]->y) && (y2 < rects[k]->y2)) { + NEW(RectT, rect); + rect->x = rects[k]->x; + rect->x2 = rects[k]->x2; + rect->y2 = rects[k]->y2; + rects[k]->y2 = y2; + rect->y = y2; + arrput(rects, rect); + } + // Compare Window Left + if ((win2->base.r.x > rects[k]->x) && (win2->base.r.x < rects[k]->x2)) { + NEW(RectT, rect); + rect->y = rects[k]->y; + rect->x2 = rects[k]->x2; + rect->y2 = rects[k]->y2; + rects[k]->x2 = win2->base.r.x; + rect->x = win2->base.r.x; + arrput(rects, rect); + } + // Compare Window Right + if ((x2 > rects[k]->x) && (x2 < rects[k]->x2)) { + NEW(RectT, rect); + rect->y = rects[k]->y; + rect->x2 = rects[k]->x2; + rect->y2 = rects[k]->y2; + rects[k]->x2 = x2; + rect->x = x2; + arrput(rects, rect); + } + } + + } + } + + // Add rectangles to the damage list. Clear rectangle list. + while (arrlen(rects) > 0) { + found = 0; + // Is this the top window? + if (i != 0) { + // No. Compare rectangles to existing damage list. + for (k=0; kx == damageList[k]->rect.x ) && + (rects[0]->y == damageList[k]->rect.y ) && + (rects[0]->x2 == damageList[k]->rect.x2) && + (rects[0]->y2 == damageList[k]->rect.y2)) { + // We already have this. Skip it. + found = 1; + break; + } + } + } + + // Do we have this section of the screen yet? + if (!found) { + // Nope! Add it. + NEW(DamageListT, damageItem); + //memcpy(&damageItem->rect, &rects[0], sizeof(RectT)); + damageItem->rect.x = rects[0]->x; + damageItem->rect.y = rects[0]->y; + damageItem->rect.x2 = rects[0]->x2; + damageItem->rect.y2 = rects[0]->y2; + if (win != NULL) { + damageItem->surface = win->cached; + } else { + damageItem->surface = NULL; + } + arrput(damageList, damageItem); + } + + // Delete this rect. + DEL(rects[0]); + arrdel(rects, 0); + } + arrfree(rects); + + //***DEBUG*** Draw the damage list. + surfaceSet(__guiBackBuffer); + for (k=0; krect.x, damageList[k]->rect.y, damageList[k]->rect.x2, damageList[k]->rect.y2, GUI_RED); + } + + // Delete damage list. + while (arrlen(damageList) > 0) { + DEL(damageList[0]); + arrdel(damageList, 0); + } + arrfree(damageList); + } + } // Do we have windows? }