diff --git a/roo_e/src/gui/gui.c b/roo_e/src/gui/gui.c index d931c40..e20748d 100644 --- a/roo_e/src/gui/gui.c +++ b/roo_e/src/gui/gui.c @@ -70,22 +70,14 @@ static void guiDeleteListProcess(void) { void guiEventsDo(void) { EventT event = { 0 }; -#ifndef NEW_RENDERER - // Paint desktop. - surfaceSet(__guiBackBuffer); - surfaceClear(GUI_CYAN); -#endif - // Read mouse & keyboard. platformEventGet(&event); // Handle GUI window manager and widgets. wmUpdate(&event); -#ifdef NEW_RENDERER // Draw. wmRender(); -#endif // Paint mouse pointer. surfaceSet(__guiBackBuffer); diff --git a/roo_e/src/gui/wmwindow.c b/roo_e/src/gui/wmwindow.c index 45fa1eb..cc20eb6 100644 --- a/roo_e/src/gui/wmwindow.c +++ b/roo_e/src/gui/wmwindow.c @@ -257,6 +257,9 @@ WindowT *windowCreate(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *titl visibleSize.x = win->bounds.x2 - win->bounds.x + 1; visibleSize.y = win->bounds.y2 - win->bounds.y + 1; + // Create icon surface. + win->icon = surfaceCreate(ICON_SIZE, ICON_SIZE); + // If the window is resizable, we need to get two more arguments for the content size. if (win->flags & WIN_RESIZE) { va_start(args, flags); @@ -313,6 +316,8 @@ static void windowDestroy(struct WidgetS *widget, ...) { arrfree(window->base.children); // Free cached surface. if (window->cached) surfaceDestroy(&window->cached); + // Free icon surface. + surfaceDestroy(&window->icon); // Delete the window. DEL(window); // Fixup focus. @@ -531,22 +536,20 @@ static void windowPaint(struct WidgetS *widget, ...) { if (mode == WINDOW_PAINT_ICONS) { // Are we minimized? if (w->flags & WIN_IS_ICON) { - // Draw iconized version of contents. There are too many counters here but it's the only way it worked reliably. - yi = (surfaceHeightGet(w->scroll->area) - 1) / ICON_SIZE; - xi = (surfaceWidthGet(w->scroll->area) - 1) / ICON_SIZE; - py = videoDisplayHeightGet() - ICON_SIZE; + // Render icon into window's icon surface. + surfaceSet(w->icon); + yi = (surfaceHeightGet(w->scroll->area) - 1) / ICON_SIZE; // Y Sample increment. + xi = (surfaceWidthGet(w->scroll->area) - 1) / ICON_SIZE; // X Sample increment. y = 0; x = 0; for (yc=0; ycscroll->area, x, y)); + surfacePixelSet(xc, yc, surfacePixelGet(w->scroll->area, x, y)); } - py++; } - _iconCount++; + surfaceBox(0, 0, ICON_SIZE - 1, ICON_SIZE - 1, GUI_BLACK); } } else { // WINDOW_PAINT_ICONS // Are we not minimized? @@ -558,10 +561,6 @@ static void windowPaint(struct WidgetS *widget, ...) { } // Did a widget or the window chrome need redrawn? if (x || widgetChildrenDirty(widget)) windowCache(w, x); - // By now we have a valid cached window. Blit it. -#ifndef NEW_RENDERER - surfaceBlit(w->base.r.x, w->base.r.y, 0, 0, w->base.r.w, w->base.r.h, w->cached); -#endif } } } @@ -662,23 +661,41 @@ static WidgetT *windowWidgetFinder(WidgetT *widget, uint16_t x, uint16_t y, int1 void wmRender(void) { + uint8_t found; + uint8_t pass; int16_t i; int16_t j; int16_t k; int16_t x2; int16_t y2; + WidgetT *widget = NULL; WindowT *win = NULL; WindowT *win2 = NULL; - RectT *rect; + RectT *rect = NULL; RectT **rects = NULL; DamageListT **damageList = NULL; DamageListT *damageItem = NULL; - uint8_t found; // ***TODO*** We still calculate the desktop in the damage list below. // There's some odd off-by-one when rendering that needs fixed. For now // we just draw the desktop and then window contents. + // Update all minimized windows. + surfaceSet(__guiBackBuffer); + for (i=0; ireg->paint(widget, WINDOW_PAINT_ICONS); + } + + // Update all windows. + for (i=0; ireg->paint(widget, WINDOW_PAINT_NORMAL); + } + + // This is global so we can click on them later. + _iconCount = 0; + // Draw the desktop. surfaceSet(__guiBackBuffer); surfaceClear(GUI_CYAN); @@ -699,133 +716,152 @@ void wmRender(void) { // // Finally do the same as the remaining windows with the entire screen. - // Iterate over all windows, top to bottom. - for (i=arrlen(_windowList)-1; i>=-1; i--) { + // Make two passes over the window list. First for regular windows, + // second for iconized windows. + for (pass=0; pass<2; pass++) { - // New rectangle. - NEW(RectT, rect); + // Iterate over all windows, top to bottom. + for (i=arrlen(_windowList)-1; i>=0-pass; i--) { - // Are we comparing the desktop? - if (i == -1) { - // 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; - rect->y2 = win->base.r.y + win->base.r.h; - } + // Is this the desktop? + win = (i == -1) ? NULL : (WindowT *)_windowList[i]; - // Clip to screen bounds. - if (rect->x < 0) rect->x = 0; - if (rect->y < 0) rect->y = 0; - if (rect->x2 > videoDisplayWidthGet() - 1) rect->x2 = videoDisplayWidthGet() - 1; - if (rect->y2 > videoDisplayHeightGet() - 1) rect->y2 = videoDisplayHeightGet() - 1; + // Skip windows depending on pass and window state. + if ((pass == 0) && (win->flags & WIN_IS_ICON)) continue; + if ((pass == 1) && (win != NULL) && !(win->flags & WIN_IS_ICON)) continue; - // Add this window to the rectangle list. - arrput(rects, rect); + // New rectangle. + NEW(RectT, rect); - // Iterate over all the other windows to slice this window. - for (j=arrlen(_windowList)-1; j>=0; j--) { - win2 = (WindowT *)_windowList[j]; - if (win != win2) { - - // Get win2 extents. - x2 = win2->base.r.x + win2->base.r.w; - y2 = win2->base.r.y + win2->base.r.h; - - // 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); - } - } - } - } // Other windows. - - // Add rectangles to the damage list. Clear rectangle list. - while (arrlen(rects) > 0) { - found = 0; - - // Is this the top window? - if (i != arrlen(_windowList)) { - // 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; - } + // Are we comparing the desktop? + if (win == NULL) { + // Yes. Fake a window. + rect->x = 0; + rect->y = 0; + rect->x2 = videoDisplayWidthGet() - 1; + rect->y2 = videoDisplayHeightGet() - 1; + } else { + // Get this window. + if (win->flags & WIN_IS_ICON) { + rect->x = _iconCount * (ICON_SIZE + 1); + rect->y = videoDisplayHeightGet() - ICON_SIZE; + rect->x2 = rect->x + ICON_SIZE; + rect->y2 = rect->y + ICON_SIZE; + _iconCount++; + } else { + rect->x = win->base.r.x; + rect->y = win->base.r.y; + rect->x2 = win->base.r.x + win->base.r.w; + rect->y2 = win->base.r.y + win->base.r.h; } } - // Do we have this section of the screen yet? - if (!found) { - // Nope! Add it. - NEW(DamageListT, damageItem); - damageItem->rect.x = rects[0]->x; - damageItem->rect.y = rects[0]->y; - damageItem->rect.x2 = rects[0]->x2; - damageItem->rect.y2 = rects[0]->y2; - damageItem->window = win; - arrput(damageList, damageItem); + // Clip to screen bounds. + if (rect->x < 0) rect->x = 0; + if (rect->y < 0) rect->y = 0; + if (rect->x2 > videoDisplayWidthGet() - 1) rect->x2 = videoDisplayWidthGet() - 1; + if (rect->y2 > videoDisplayHeightGet() - 1) rect->y2 = videoDisplayHeightGet() - 1; + + // Add this window to the rectangle list. + arrput(rects, rect); + + // Iterate over all the other windows to slice this window. + for (j=arrlen(_windowList)-1; j>=0; j--) { + win2 = (WindowT *)_windowList[j]; + if (win != win2) { + + // Get win2 extents. + x2 = win2->base.r.x + win2->base.r.w; + y2 = win2->base.r.y + win2->base.r.h; + + // 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); + } + } + } + } // Other windows. + + // Add rectangles to the damage list. Clear rectangle list. + while (arrlen(rects) > 0) { + found = 0; + + // Is this the top window? + if (i != arrlen(_windowList)) { + // 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); + damageItem->rect.x = rects[0]->x; + damageItem->rect.y = rects[0]->y; + damageItem->rect.x2 = rects[0]->x2; + damageItem->rect.y2 = rects[0]->y2; + damageItem->window = win; + arrput(damageList, damageItem); + } + + // Delete this rect. + DEL(rects[0]); + arrdel(rects, 0); } + arrfree(rects); - // Delete this rect. - DEL(rects[0]); - arrdel(rects, 0); - } - arrfree(rects); + } // Window list. - } // Window list. + } // Pass. // Merge adjacent damage areas. // For areas to be adjacent they need matching X coordinates with a @@ -906,13 +942,22 @@ void wmRender(void) { */ if (damageList[k]->window != NULL) { - // Window content. - surfaceBlit( - damageList[k]->rect.x, damageList[k]->rect.y, - damageList[k]->rect.x - damageList[k]->window->base.r.x, damageList[k]->rect.y - damageList[k]->window->base.r.y, - damageList[k]->rect.x2 - damageList[k]->rect.x, - damageList[k]->rect.y2 - damageList[k]->rect.y, - damageList[k]->window->cached); + // Icon or Window? + if (damageList[k]->window->flags & WIN_IS_ICON) { + // Icon. + surfaceBlit( + damageList[k]->rect.x, damageList[k]->rect.y, + 0, 0, + ICON_SIZE, ICON_SIZE, + damageList[k]->window->icon); + } else { + // Window content. + surfaceBlit( + damageList[k]->rect.x, damageList[k]->rect.y, + damageList[k]->rect.x - damageList[k]->window->base.r.x, damageList[k]->rect.y - damageList[k]->window->base.r.y, + damageList[k]->rect.x2 - damageList[k]->rect.x, damageList[k]->rect.y2 - damageList[k]->rect.y, + damageList[k]->window->cached); + } } else { // Desktop. //surfaceBoxFilled(damageList[k]->rect.x, damageList[k]->rect.y, damageList[k]->rect.x2, damageList[k]->rect.y2, GUI_CYAN); @@ -974,21 +1019,6 @@ void wmUpdate(EventT *event) { // Mouse is always the default pointer unless something changes it for this frame. guiMousePointerSet(MOUSE_POINTER); - // Paint all minimized windows. - surfaceSet(__guiBackBuffer); - _iconCount = 0; - for (i=0; ireg->paint(widget, WINDOW_PAINT_ICONS); - } - - // Paint all windows. - for (i=0; ireg->paint(widget, WINDOW_PAINT_NORMAL); - } - // Get top window. win = _windowTop; diff --git a/roo_e/src/gui/wmwindow.h b/roo_e/src/gui/wmwindow.h index a1794f4..1a6b5fa 100644 --- a/roo_e/src/gui/wmwindow.h +++ b/roo_e/src/gui/wmwindow.h @@ -66,6 +66,7 @@ typedef struct WindowS { PointT restoreOffset; // Scroll position if they restore from maximized. RectT bounds; // Window contents in screen space. Does not include titlebar or window chrome. SurfaceT *cached; // Once rendered, keep a cached copy for faster redrawing. + SurfaceT *icon; // Needed for damaged region drawing. } WindowT; diff --git a/roo_e/src/os.h b/roo_e/src/os.h index d2d15a7..5ce4428 100644 --- a/roo_e/src/os.h +++ b/roo_e/src/os.h @@ -29,8 +29,6 @@ #define MEMORY_CHECK_ENABLED -#define NEW_RENDERER - #include #include