Compare commits

...

2 commits

Author SHA1 Message Date
90c6ab68e3 Added layout debugging. 2026-03-09 23:03:44 -05:00
9407544ede Cleaning up project layout. 2026-03-09 22:55:00 -05:00
10 changed files with 165 additions and 40 deletions

2
.gitignore vendored
View file

@ -1,5 +1,7 @@
dosbench/ dosbench/
bin/ bin/
obj/ obj/
lib/
*.~ *.~
.gitignore~
DVX_GUI_DESIGN.md DVX_GUI_DESIGN.md

View file

@ -1,15 +1,17 @@
# DV/X GUI Makefile for DJGPP cross-compilation # DV/X GUI Library Makefile for DJGPP cross-compilation
DJGPP_PREFIX = $(HOME)/djgpp/djgpp DJGPP_PREFIX = $(HOME)/djgpp/djgpp
CC = $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-gcc CC = $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-gcc
DJGPP_LIBPATH = $(HOME)/claude/windriver/tools/lib
AR = LD_LIBRARY_PATH=$(DJGPP_LIBPATH) $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-ar
RANLIB = LD_LIBRARY_PATH=$(DJGPP_LIBPATH) $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-ranlib
CFLAGS = -O2 -Wall -Wextra -march=i486 -mtune=i586 CFLAGS = -O2 -Wall -Wextra -march=i486 -mtune=i586
LDFLAGS = -lm
OBJDIR = ../obj OBJDIR = ../obj/dvx
WOBJDIR = ../obj/widgets WOBJDIR = ../obj/dvx/widgets
BINDIR = ../bin LIBDIR = ../lib
SRCS = dvxVideo.c dvxDraw.c dvxComp.c dvxWm.c dvxIcon.c dvxImageWrite.c dvxApp.c demo.c SRCS = dvxVideo.c dvxDraw.c dvxComp.c dvxWm.c dvxIcon.c dvxImageWrite.c dvxApp.c
WSRCS = widgets/widgetCore.c \ WSRCS = widgets/widgetCore.c \
widgets/widgetLayout.c \ widgets/widgetLayout.c \
@ -37,14 +39,15 @@ WSRCS = widgets/widgetCore.c \
OBJS = $(patsubst %.c,$(OBJDIR)/%.o,$(SRCS)) OBJS = $(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
WOBJS = $(patsubst widgets/%.c,$(WOBJDIR)/%.o,$(WSRCS)) WOBJS = $(patsubst widgets/%.c,$(WOBJDIR)/%.o,$(WSRCS))
TARGET = $(BINDIR)/demo.exe TARGET = $(LIBDIR)/libdvx.a
.PHONY: all clean .PHONY: all clean
all: $(TARGET) all: $(TARGET)
$(TARGET): $(OBJS) $(WOBJS) | $(BINDIR) $(TARGET): $(OBJS) $(WOBJS) | $(LIBDIR)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(WOBJS) $(AR) rcs $@ $(OBJS) $(WOBJS)
$(RANLIB) $@
$(OBJDIR)/%.o: %.c | $(OBJDIR) $(OBJDIR)/%.o: %.c | $(OBJDIR)
$(CC) $(CFLAGS) -c -o $@ $< $(CC) $(CFLAGS) -c -o $@ $<
@ -58,18 +61,17 @@ $(OBJDIR):
$(WOBJDIR): $(WOBJDIR):
mkdir -p $(WOBJDIR) mkdir -p $(WOBJDIR)
$(BINDIR): $(LIBDIR):
mkdir -p $(BINDIR) mkdir -p $(LIBDIR)
# Dependencies # Dependencies
$(OBJDIR)/dvxVideo.o: dvxVideo.c dvxVideo.h dvxTypes.h dvxPalette.h $(OBJDIR)/dvxVideo.o: dvxVideo.c dvxVideo.h dvxTypes.h dvxPalette.h
$(OBJDIR)/dvxDraw.o: dvxDraw.c dvxDraw.h dvxTypes.h $(OBJDIR)/dvxDraw.o: dvxDraw.c dvxDraw.h dvxTypes.h
$(OBJDIR)/dvxComp.o: dvxComp.c dvxComp.h dvxTypes.h $(OBJDIR)/dvxComp.o: dvxComp.c dvxComp.h dvxTypes.h
$(OBJDIR)/dvxWm.o: dvxWm.c dvxWm.h dvxTypes.h dvxDraw.h dvxComp.h dvxVideo.h thirdparty/stb_image.h $(OBJDIR)/dvxWm.o: dvxWm.c dvxWm.h dvxTypes.h dvxDraw.h dvxComp.h dvxVideo.h thirdparty/stb_image.h
$(OBJDIR)/dvxIcon.o: dvxIcon.c thirdparty/stb_image.h $(OBJDIR)/dvxIcon.o: dvxIcon.c thirdparty/stb_image.h
$(OBJDIR)/dvxImageWrite.o: dvxImageWrite.c thirdparty/stb_image_write.h $(OBJDIR)/dvxImageWrite.o: dvxImageWrite.c thirdparty/stb_image_write.h
$(OBJDIR)/dvxApp.o: dvxApp.c dvxApp.h dvxTypes.h dvxVideo.h dvxDraw.h dvxComp.h dvxWm.h dvxFont.h dvxCursor.h $(OBJDIR)/dvxApp.o: dvxApp.c dvxApp.h dvxTypes.h dvxVideo.h dvxDraw.h dvxComp.h dvxWm.h dvxFont.h dvxCursor.h
$(OBJDIR)/demo.o: demo.c dvxApp.h dvxWidget.h
# Widget file dependencies # Widget file dependencies
WIDGET_DEPS = widgets/widgetInternal.h dvxWidget.h dvxTypes.h dvxApp.h dvxDraw.h dvxWm.h dvxVideo.h WIDGET_DEPS = widgets/widgetInternal.h dvxWidget.h dvxTypes.h dvxApp.h dvxDraw.h dvxWm.h dvxVideo.h
@ -98,4 +100,4 @@ $(WOBJDIR)/widgetToolbar.o: widgets/widgetToolbar.c $(WIDGET_DEPS)
$(WOBJDIR)/widgetTreeView.o: widgets/widgetTreeView.c $(WIDGET_DEPS) $(WOBJDIR)/widgetTreeView.o: widgets/widgetTreeView.c $(WIDGET_DEPS)
clean: clean:
rm -rf $(OBJDIR) $(BINDIR) rm -rf $(OBJDIR) $(LIBDIR)

View file

@ -54,7 +54,10 @@ static void compositeAndFlush(AppContextT *ctx) {
// 1. Draw desktop background // 1. Draw desktop background
rectFill(d, ops, dr->x, dr->y, dr->w, dr->h, ctx->colors.desktop); 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++) { for (int32_t j = 0; j < ws->count; j++) {
WindowT *win = ws->windows[j]; WindowT *win = ws->windows[j];
@ -77,10 +80,7 @@ static void compositeAndFlush(AppContextT *ctx) {
} }
} }
// 2b. Draw minimized window icons // 4. Draw popup menu if active
wmDrawMinimizedIcons(d, ops, &ctx->colors, ws, dr);
// 3. Draw popup menu if active
if (ctx->popup.active) { if (ctx->popup.active) {
// Draw popup dropdown // Draw popup dropdown
RectT popRect = { RectT popRect = {
@ -484,25 +484,40 @@ void dvxQuit(AppContextT *ctx) {
// ============================================================ // ============================================================
void dvxRun(AppContextT *ctx) { void dvxRun(AppContextT *ctx) {
while (ctx->running) { while (dvxUpdate(ctx)) {
pollMouse(ctx); // dvxUpdate returns false when the GUI wants to exit
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;
} }
} }
// ============================================================
// 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 // dvxShutdown
// ============================================================ // ============================================================

View file

@ -48,6 +48,10 @@ void dvxShutdown(AppContextT *ctx);
// Run the main event loop (returns when ctx->running is set to false) // Run the main event loop (returns when ctx->running is set to false)
void dvxRun(AppContextT *ctx); 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 // Create a window
WindowT *dvxCreateWindow(AppContextT *ctx, const char *title, WindowT *dvxCreateWindow(AppContextT *ctx, const char *title,
int32_t x, int32_t y, int32_t w, int32_t h, int32_t x, int32_t y, int32_t w, int32_t h,

View file

@ -446,6 +446,13 @@ void wgtListBoxSetItems(WidgetT *w, const char **items, int32_t count);
int32_t wgtListBoxGetSelected(const WidgetT *w); int32_t wgtListBoxGetSelected(const WidgetT *w);
void wgtListBoxSetSelected(WidgetT *w, int32_t idx); 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) // Layout (called internally; available for manual trigger)
// ============================================================ // ============================================================

View file

@ -6,10 +6,11 @@
// Global state for drag and popup tracking // Global state for drag and popup tracking
// ============================================================ // ============================================================
WidgetT *sOpenPopup = NULL; bool sDebugLayout = false;
WidgetT *sDragSlider = NULL; WidgetT *sOpenPopup = NULL;
WidgetT *sDragSlider = NULL;
WidgetT *sDrawingCanvas = NULL; WidgetT *sDrawingCanvas = NULL;
int32_t sDragOffset = 0; int32_t sDragOffset = 0;
// ============================================================ // ============================================================

View file

@ -42,6 +42,7 @@
// Shared state (defined in widgetCore.c) // Shared state (defined in widgetCore.c)
// ============================================================ // ============================================================
extern bool sDebugLayout;
extern WidgetT *sOpenPopup; extern WidgetT *sOpenPopup;
extern WidgetT *sDragSlider; extern WidgetT *sDragSlider;
extern WidgetT *sDrawingCanvas; extern WidgetT *sDrawingCanvas;

View file

@ -3,6 +3,40 @@
#include "widgetInternal.h" #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 // widgetPaintOne
// ============================================================ // ============================================================
@ -80,6 +114,9 @@ void widgetPaintOne(WidgetT *w, DisplayT *d, const BlitOpsT *ops,
case WidgetTabControlE: case WidgetTabControlE:
widgetTabControlPaint(w, d, ops, font, colors); widgetTabControlPaint(w, d, ops, font, colors);
if (sDebugLayout) {
debugContainerBorder(w, d, ops);
}
return; // handles its own children return; // handles its own children
case WidgetStatusBarE: case WidgetStatusBarE:
@ -92,6 +129,9 @@ void widgetPaintOne(WidgetT *w, DisplayT *d, const BlitOpsT *ops,
case WidgetTreeViewE: case WidgetTreeViewE:
widgetTreeViewPaint(w, d, ops, font, colors); widgetTreeViewPaint(w, d, ops, font, colors);
if (sDebugLayout) {
debugContainerBorder(w, d, ops);
}
return; // handles its own children return; // handles its own children
default: default:
@ -102,6 +142,11 @@ void widgetPaintOne(WidgetT *w, DisplayT *d, const BlitOpsT *ops,
for (WidgetT *c = w->firstChild; c; c = c->nextSibling) { for (WidgetT *c = w->firstChild; c; c = c->nextSibling) {
widgetPaintOne(c, d, ops, font, colors); 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 // wgtSetEnabled
// ============================================================ // ============================================================

39
dvxdemo/Makefile Normal file
View file

@ -0,0 +1,39 @@
# DV/X GUI Demo Makefile for DJGPP cross-compilation
DJGPP_PREFIX = $(HOME)/djgpp/djgpp
CC = $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-gcc
CFLAGS = -O2 -Wall -Wextra -march=i486 -mtune=i586 -I../dvx
LDFLAGS = -L../lib -ldvx -lm
OBJDIR = ../obj/dvxdemo
BINDIR = ../bin
LIBDIR = ../lib
SRCS = demo.c
OBJS = $(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
TARGET = $(BINDIR)/demo.exe
.PHONY: all clean lib
all: lib $(TARGET)
lib:
$(MAKE) -C ../dvx
$(TARGET): $(OBJS) $(LIBDIR)/libdvx.a | $(BINDIR)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LDFLAGS)
$(OBJDIR)/%.o: %.c | $(OBJDIR)
$(CC) $(CFLAGS) -c -o $@ $<
$(OBJDIR):
mkdir -p $(OBJDIR)
$(BINDIR):
mkdir -p $(BINDIR)
# Dependencies
$(OBJDIR)/demo.o: demo.c ../dvx/dvxApp.h ../dvx/dvxWidget.h
clean:
rm -rf $(OBJDIR) $(BINDIR)