From 90c6ab68e3247323daf572005730da1f72bc6d6e Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Mon, 9 Mar 2026 23:03:44 -0500 Subject: [PATCH] Added layout debugging. --- dvx/dvxApp.c | 55 +++++++++++++++++++++++------------- dvx/dvxApp.h | 4 +++ dvx/dvxWidget.h | 7 +++++ dvx/widgets/widgetCore.c | 7 +++-- dvx/widgets/widgetInternal.h | 1 + dvx/widgets/widgetOps.c | 54 +++++++++++++++++++++++++++++++++++ 6 files changed, 105 insertions(+), 23 deletions(-) diff --git a/dvx/dvxApp.c b/dvx/dvxApp.c index 3d9650e..0bcf566 100644 --- a/dvx/dvxApp.c +++ b/dvx/dvxApp.c @@ -54,7 +54,10 @@ static void compositeAndFlush(AppContextT *ctx) { // 1. Draw desktop background rectFill(d, ops, dr->x, dr->y, dr->w, dr->h, ctx->colors.desktop); - // 2. Walk window stack bottom-to-top + // 2. Draw minimized window icons (under all windows) + wmDrawMinimizedIcons(d, ops, &ctx->colors, ws, dr); + + // 3. Walk window stack bottom-to-top for (int32_t j = 0; j < ws->count; j++) { WindowT *win = ws->windows[j]; @@ -77,10 +80,7 @@ static void compositeAndFlush(AppContextT *ctx) { } } - // 2b. Draw minimized window icons - wmDrawMinimizedIcons(d, ops, &ctx->colors, ws, dr); - - // 3. Draw popup menu if active + // 4. Draw popup menu if active if (ctx->popup.active) { // Draw popup dropdown RectT popRect = { @@ -484,25 +484,40 @@ void dvxQuit(AppContextT *ctx) { // ============================================================ void dvxRun(AppContextT *ctx) { - while (ctx->running) { - pollMouse(ctx); - pollKeyboard(ctx); - dispatchEvents(ctx); - - if (ctx->dirty.count > 0) { - compositeAndFlush(ctx); - } else { - // Nothing to do — yield timeslice - __dpmi_yield(); - } - - ctx->prevMouseX = ctx->mouseX; - ctx->prevMouseY = ctx->mouseY; - ctx->prevMouseButtons = ctx->mouseButtons; + while (dvxUpdate(ctx)) { + // dvxUpdate returns false when the GUI wants to exit } } +// ============================================================ +// dvxUpdate +// ============================================================ + +bool dvxUpdate(AppContextT *ctx) { + if (!ctx->running) { + return false; + } + + pollMouse(ctx); + pollKeyboard(ctx); + dispatchEvents(ctx); + + if (ctx->dirty.count > 0) { + compositeAndFlush(ctx); + } else { + // Nothing to do — yield timeslice + __dpmi_yield(); + } + + ctx->prevMouseX = ctx->mouseX; + ctx->prevMouseY = ctx->mouseY; + ctx->prevMouseButtons = ctx->mouseButtons; + + return ctx->running; +} + + // ============================================================ // dvxShutdown // ============================================================ diff --git a/dvx/dvxApp.h b/dvx/dvxApp.h index 6c8931d..5277a60 100644 --- a/dvx/dvxApp.h +++ b/dvx/dvxApp.h @@ -48,6 +48,10 @@ void dvxShutdown(AppContextT *ctx); // Run the main event loop (returns when ctx->running is set to false) void dvxRun(AppContextT *ctx); +// Process one iteration of the event loop. +// Returns true if the GUI is still running, false if it wants to exit. +bool dvxUpdate(AppContextT *ctx); + // Create a window WindowT *dvxCreateWindow(AppContextT *ctx, const char *title, int32_t x, int32_t y, int32_t w, int32_t h, diff --git a/dvx/dvxWidget.h b/dvx/dvxWidget.h index f1f7251..8f0314c 100644 --- a/dvx/dvxWidget.h +++ b/dvx/dvxWidget.h @@ -446,6 +446,13 @@ void wgtListBoxSetItems(WidgetT *w, const char **items, int32_t count); int32_t wgtListBoxGetSelected(const WidgetT *w); void wgtListBoxSetSelected(WidgetT *w, int32_t idx); +// ============================================================ +// Debug +// ============================================================ + +// Draw borders around layout containers in ugly colors +void wgtSetDebugLayout(bool enabled); + // ============================================================ // Layout (called internally; available for manual trigger) // ============================================================ diff --git a/dvx/widgets/widgetCore.c b/dvx/widgets/widgetCore.c index b89783a..6ae1ba5 100644 --- a/dvx/widgets/widgetCore.c +++ b/dvx/widgets/widgetCore.c @@ -6,10 +6,11 @@ // Global state for drag and popup tracking // ============================================================ -WidgetT *sOpenPopup = NULL; -WidgetT *sDragSlider = NULL; +bool sDebugLayout = false; +WidgetT *sOpenPopup = NULL; +WidgetT *sDragSlider = NULL; WidgetT *sDrawingCanvas = NULL; -int32_t sDragOffset = 0; +int32_t sDragOffset = 0; // ============================================================ diff --git a/dvx/widgets/widgetInternal.h b/dvx/widgets/widgetInternal.h index 948e10c..b3f7c34 100644 --- a/dvx/widgets/widgetInternal.h +++ b/dvx/widgets/widgetInternal.h @@ -42,6 +42,7 @@ // Shared state (defined in widgetCore.c) // ============================================================ +extern bool sDebugLayout; extern WidgetT *sOpenPopup; extern WidgetT *sDragSlider; extern WidgetT *sDrawingCanvas; diff --git a/dvx/widgets/widgetOps.c b/dvx/widgets/widgetOps.c index e9d8227..fa5a710 100644 --- a/dvx/widgets/widgetOps.c +++ b/dvx/widgets/widgetOps.c @@ -3,6 +3,40 @@ #include "widgetInternal.h" +// ============================================================ +// debugContainerBorder +// ============================================================ +// +// Draw a 1px border in a garish neon color derived from the widget +// pointer so every container gets a distinct, ugly color. + +static void debugContainerBorder(WidgetT *w, DisplayT *d, const BlitOpsT *ops) { + static const uint8_t palette[][3] = { + {255, 0, 255}, // magenta + { 0, 255, 0}, // lime + {255, 255, 0}, // yellow + { 0, 255, 255}, // cyan + {255, 128, 0}, // orange + {128, 0, 255}, // purple + {255, 0, 128}, // hot pink + { 0, 128, 255}, // sky blue + {128, 255, 0}, // chartreuse + {255, 64, 64}, // salmon + { 64, 255, 128}, // mint + {255, 128, 255}, // orchid + }; + + uint32_t h = (uint32_t)(uintptr_t)w * 2654435761u; + int32_t idx = (int32_t)((h >> 16) % 12); + uint32_t color = packColor(d, palette[idx][0], palette[idx][1], palette[idx][2]); + + drawHLine(d, ops, w->x, w->y, w->w, color); + drawHLine(d, ops, w->x, w->y + w->h - 1, w->w, color); + drawVLine(d, ops, w->x, w->y, w->h, color); + drawVLine(d, ops, w->x + w->w - 1, w->y, w->h, color); +} + + // ============================================================ // widgetPaintOne // ============================================================ @@ -80,6 +114,9 @@ void widgetPaintOne(WidgetT *w, DisplayT *d, const BlitOpsT *ops, case WidgetTabControlE: widgetTabControlPaint(w, d, ops, font, colors); + if (sDebugLayout) { + debugContainerBorder(w, d, ops); + } return; // handles its own children case WidgetStatusBarE: @@ -92,6 +129,9 @@ void widgetPaintOne(WidgetT *w, DisplayT *d, const BlitOpsT *ops, case WidgetTreeViewE: widgetTreeViewPaint(w, d, ops, font, colors); + if (sDebugLayout) { + debugContainerBorder(w, d, ops); + } return; // handles its own children default: @@ -102,6 +142,11 @@ void widgetPaintOne(WidgetT *w, DisplayT *d, const BlitOpsT *ops, for (WidgetT *c = w->firstChild; c; c = c->nextSibling) { widgetPaintOne(c, d, ops, font, colors); } + + // Debug: draw container borders on top of children + if (sDebugLayout && w->firstChild) { + debugContainerBorder(w, d, ops); + } } @@ -310,6 +355,15 @@ void wgtPaint(WidgetT *root, DisplayT *d, const BlitOpsT *ops, } +// ============================================================ +// wgtSetDebugLayout +// ============================================================ + +void wgtSetDebugLayout(bool enabled) { + sDebugLayout = enabled; +} + + // ============================================================ // wgtSetEnabled // ============================================================