diff --git a/apps/clock/clock.c b/apps/clock/clock.c index c4a3b0c..c968a42 100644 --- a/apps/clock/clock.c +++ b/apps/clock/clock.c @@ -189,23 +189,20 @@ int32_t appMain(DxeAppContextT *ctx) { sWin->onClose = onClose; sWin->onPaint = onPaint; - // Initial paint into content buffer - RectT full = {0, 0, sWin->contentW, sWin->contentH}; - onPaint(sWin, &full); + // Initial paint — dvxInvalidateWindow calls onPaint automatically dvxInvalidateWindow(ac, sWin); // Main loop: check if the second has changed, repaint if so, then yield. // tsYield() transfers control back to the shell's task scheduler. // On a 486, time() resolution is 1 second, so we yield many times per // second between actual updates — this keeps CPU usage near zero. - // dvxInvalidateWindow marks the window dirty so the compositor will - // flush it to the LFB on the next composite pass. + // dvxInvalidateWindow marks the window dirty and calls onPaint to + // update the content buffer before the compositor flushes it. while (!sState.quit) { time_t now = time(NULL); if (now != sState.lastUpdate) { updateTime(); - onPaint(sWin, &full); dvxInvalidateWindow(ac, sWin); } diff --git a/dvx/dvxApp.c b/dvx/dvxApp.c index d5d184b..da299f2 100644 --- a/dvx/dvxApp.c +++ b/dvx/dvxApp.c @@ -1567,6 +1567,14 @@ void dvxInvalidateRect(AppContextT *ctx, WindowT *win, int32_t x, int32_t y, int // ============================================================ void dvxInvalidateWindow(AppContextT *ctx, WindowT *win) { + // Call the window's paint callback to update the content buffer + // before marking the screen dirty. This means raw-paint apps only + // need to call dvxInvalidateWindow — onPaint fires automatically. + if (win->onPaint) { + RectT fullRect = {0, 0, win->contentW, win->contentH}; + win->onPaint(win, &fullRect); + } + win->contentDirty = true; dirtyListAdd(&ctx->dirty, win->x, win->y, win->w, win->h); } diff --git a/dvx/widgets/widgetEvent.c b/dvx/widgets/widgetEvent.c index 7e63c65..a0c4ace 100644 --- a/dvx/widgets/widgetEvent.c +++ b/dvx/widgets/widgetEvent.c @@ -663,18 +663,12 @@ void widgetOnScroll(WindowT *win, ScrollbarOrientE orient, int32_t value) { (void)orient; (void)value; - // Repaint with new scroll position - if (win->onPaint) { - RectT fullRect = {0, 0, win->contentW, win->contentH}; - win->onPaint(win, &fullRect); + // Repaint with new scroll position — dvxInvalidateWindow calls onPaint + if (win->widgetRoot) { + AppContextT *ctx = wgtGetContext(win->widgetRoot); - // Dirty the window content area on screen so compositor redraws it - if (win->widgetRoot) { - AppContextT *ctx = wgtGetContext(win->widgetRoot); - - if (ctx) { - dvxInvalidateWindow(ctx, win); - } + if (ctx) { + dvxInvalidateWindow(ctx, win); } } } diff --git a/dvx/widgets/widgetOps.c b/dvx/widgets/widgetOps.c index 56d9cd1..82f382c 100644 --- a/dvx/widgets/widgetOps.c +++ b/dvx/widgets/widgetOps.c @@ -389,13 +389,8 @@ void wgtInvalidate(WidgetT *w) { widgetManageScrollbars(w->window, ctx); } - // Repaint (use win->onPaint so custom paint handlers like dialogs work) - WindowT *win = w->window; - RectT fullRect = {0, 0, win->contentW, win->contentH}; - win->onPaint(win, &fullRect); - - // Dirty the window on screen - dvxInvalidateWindow(ctx, win); + // Dirty the window — dvxInvalidateWindow calls onPaint automatically + dvxInvalidateWindow(ctx, w->window); } @@ -424,11 +419,8 @@ void wgtInvalidatePaint(WidgetT *w) { return; } - // Repaint without measure/layout (use win->onPaint so custom handlers work) - WindowT *win = w->window; - RectT fullRect = {0, 0, win->contentW, win->contentH}; - win->onPaint(win, &fullRect); - dvxInvalidateWindow(ctx, win); + // Dirty the window — dvxInvalidateWindow calls onPaint automatically + dvxInvalidateWindow(ctx, w->window); } diff --git a/dvx/widgets/widgetTextInput.c b/dvx/widgets/widgetTextInput.c index 6765b61..ff9d74f 100644 --- a/dvx/widgets/widgetTextInput.c +++ b/dvx/widgets/widgetTextInput.c @@ -319,8 +319,6 @@ void clearOtherSelections(WidgetT *except) { } if (clearSelectionOnWidget(prev) && prevWin != except->window) { - RectT fullRect = {0, 0, prevWin->contentW, prevWin->contentH}; - widgetOnPaint(prevWin, &fullRect); dvxInvalidateWindow(ctx, prevWin); } }