Task Manager display fixed. ListView can now auto-size columns to fit content.

This commit is contained in:
Scott Duensing 2026-03-18 22:19:43 -05:00
parent 8550fbbbf2
commit fa8ab9da27
9 changed files with 72 additions and 14 deletions

View file

@ -254,7 +254,8 @@ static void buildTaskManager(void) {
WidgetT *root = wgtInitWindow(sAc, sTmWindow); WidgetT *root = wgtInitWindow(sAc, sTmWindow);
// ListView with Name (descriptor), File (basename), Type, Status columns. // ListView with Name (descriptor), File (basename), Type, Status columns.
ListViewColT tmCols[TM_COL_COUNT]; // Static: wgtListViewSetColumns stores a pointer, not a copy.
static ListViewColT tmCols[TM_COL_COUNT];
tmCols[0].title = "Name"; tmCols[0].title = "Name";
tmCols[0].width = wgtPercent(35); tmCols[0].width = wgtPercent(35);
tmCols[0].align = ListViewAlignLeftE; tmCols[0].align = ListViewAlignLeftE;

View file

@ -2718,7 +2718,7 @@ static void pollAnsiTermWidgetsWalk(AppContextT *ctx, WidgetT *w, WindowT *win)
static void pollKeyboard(AppContextT *ctx) { static void pollKeyboard(AppContextT *ctx) {
int32_t shiftFlags = platformKeyboardGetModifiers(); int32_t shiftFlags = platformKeyboardGetModifiers();
ctx->keyModifiers = shiftFlags; ctx->keyModifiers = shiftFlags;
bool shiftHeld = (shiftFlags & 0x03) != 0; // left or right shift bool shiftHeld = (shiftFlags & KEY_MOD_SHIFT) != 0;
PlatformKeyEventT evt; PlatformKeyEventT evt;
@ -2937,7 +2937,7 @@ static void pollKeyboard(AppContextT *ctx) {
// Alt+Space — open/close system menu // Alt+Space — open/close system menu
// Enhanced INT 16h: Alt+Space returns scancode 0x39, ascii 0x20 // Enhanced INT 16h: Alt+Space returns scancode 0x39, ascii 0x20
// Must check Alt modifier (bit 3) to distinguish from plain Space // Must check Alt modifier (bit 3) to distinguish from plain Space
if (scancode == 0x39 && ascii == 0x20 && (shiftFlags & 0x08)) { if (scancode == 0x39 && ascii == 0x20 && (shiftFlags & KEY_MOD_ALT)) {
if (ctx->sysMenu.active) { if (ctx->sysMenu.active) {
closeSysMenu(ctx); closeSysMenu(ctx);
} else if (ctx->stack.focusedIdx >= 0) { } else if (ctx->stack.focusedIdx >= 0) {

View file

@ -49,6 +49,7 @@ WidgetT *sResizeListView = NULL; // ListView undergoing column resize
int32_t sResizeCol = -1; // which column is being resized int32_t sResizeCol = -1; // which column is being resized
int32_t sResizeStartX = 0; // mouse X at resize start int32_t sResizeStartX = 0; // mouse X at resize start
int32_t sResizeOrigW = 0; // column width at resize start int32_t sResizeOrigW = 0; // column width at resize start
bool sResizeDragging = false; // true once mouse moves during column resize
WidgetT *sDragSplitter = NULL; // splitter being dragged WidgetT *sDragSplitter = NULL; // splitter being dragged
int32_t sDragSplitStart = 0; // mouse offset from splitter edge at drag start int32_t sDragSplitStart = 0; // mouse offset from splitter edge at drag start
WidgetT *sDragReorder = NULL; // list/tree widget in drag-reorder mode WidgetT *sDragReorder = NULL; // list/tree widget in drag-reorder mode
@ -202,6 +203,7 @@ void widgetDestroyChildren(WidgetT *w) {
if (sResizeListView == child) { if (sResizeListView == child) {
sResizeListView = NULL; sResizeListView = NULL;
sResizeCol = -1; sResizeCol = -1;
sResizeDragging = false;
} }
if (sDragScrollbar == child) { if (sDragScrollbar == child) {

View file

@ -313,11 +313,25 @@ void widgetOnMouse(WindowT *win, int32_t x, int32_t y, int32_t buttons) {
if (sResizeListView && !(buttons & MOUSE_LEFT)) { if (sResizeListView && !(buttons & MOUSE_LEFT)) {
sResizeListView = NULL; sResizeListView = NULL;
sResizeCol = -1; sResizeCol = -1;
sResizeDragging = false;
return; return;
} }
// Handle ListView column resize drag // Handle ListView column resize drag. The drag is deferred: on the
// initial click sResizeDragging is false and no resize happens until
// the mouse actually moves from the click point. This allows double-
// click auto-size to work (the first click sets sResizeListView but
// doesn't start dragging; the release clears it; the second click
// reaches widgetListViewOnMouse where multiClickDetect returns 2).
if (sResizeListView && (buttons & MOUSE_LEFT)) { if (sResizeListView && (buttons & MOUSE_LEFT)) {
if (!sResizeDragging) {
if (x == sResizeStartX) {
return;
}
sResizeDragging = true;
}
int32_t delta = x - sResizeStartX; int32_t delta = x - sResizeStartX;
int32_t newW = sResizeOrigW + delta; int32_t newW = sResizeOrigW + delta;

View file

@ -188,6 +188,7 @@ extern WidgetT *sResizeListView; // listview whose column is being resized
extern int32_t sResizeCol; // which column is being resized extern int32_t sResizeCol; // which column is being resized
extern int32_t sResizeStartX; // mouse X at start of column resize extern int32_t sResizeStartX; // mouse X at start of column resize
extern int32_t sResizeOrigW; // original column width at start of resize extern int32_t sResizeOrigW; // original column width at start of resize
extern bool sResizeDragging; // true once mouse has moved from click point
extern WidgetT *sDragSplitter; // splitter being dragged extern WidgetT *sDragSplitter; // splitter being dragged
extern int32_t sDragSplitStart; // mouse position at start of splitter drag extern int32_t sDragSplitStart; // mouse position at start of splitter drag
extern WidgetT *sDragReorder; // listbox/treeview item being drag-reordered extern WidgetT *sDragReorder; // listbox/treeview item being drag-reordered

View file

@ -893,11 +893,48 @@ void widgetListViewOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy)
int32_t border = colX + cw; int32_t border = colX + cw;
if (vx >= border - 3 && vx <= border + 3 && c < hit->as.listView->colCount) { if (vx >= border - 3 && vx <= border + 3 && c < hit->as.listView->colCount) {
// Start column resize drag if (multiClickDetect(vx, vy) >= 2) {
// Double-click on column border: auto-size to fit content
int32_t maxLen = (int32_t)strlen(hit->as.listView->cols[c].title);
for (int32_t r = 0; r < hit->as.listView->rowCount; r++) {
const char *cell = hit->as.listView->cellData[r * hit->as.listView->colCount + c];
if (cell) {
int32_t slen = (int32_t)strlen(cell);
if (slen > maxLen) {
maxLen = slen;
}
}
}
int32_t newW = maxLen * font->charWidth + LISTVIEW_COL_PAD;
if (newW < LISTVIEW_MIN_COL_W) {
newW = LISTVIEW_MIN_COL_W;
}
hit->as.listView->resolvedColW[c] = newW;
// Recalculate totalColW
int32_t total = 0;
for (int32_t tc = 0; tc < hit->as.listView->colCount; tc++) {
total += hit->as.listView->resolvedColW[tc];
}
hit->as.listView->totalColW = total;
wgtInvalidatePaint(hit);
} else {
// Start column resize drag (deferred until mouse moves)
sResizeListView = hit; sResizeListView = hit;
sResizeCol = c; sResizeCol = c;
sResizeStartX = vx; sResizeStartX = vx;
sResizeOrigW = cw; sResizeOrigW = cw;
sResizeDragging = false;
}
return; return;
} }

View file

@ -415,6 +415,7 @@ int32_t shellLoadApp(AppContextT *ctx, const char *path) {
app->state = AppStateRunningE; app->state = AppStateRunningE;
shellLog("Shell: loaded '%s' (id=%ld, mainLoop=%s, entry=0x%08lx, desc=0x%08lx)", app->name, (long)id, app->hasMainLoop ? "yes" : "no", (unsigned long)entry, (unsigned long)desc); shellLog("Shell: loaded '%s' (id=%ld, mainLoop=%s, entry=0x%08lx, desc=0x%08lx)", app->name, (long)id, app->hasMainLoop ? "yes" : "no", (unsigned long)entry, (unsigned long)desc);
shellDesktopUpdate();
return id; return id;
} }

View file

@ -178,4 +178,7 @@ void shellExportInit(void);
// and is the only consumer. // and is the only consumer.
void shellRegisterDesktopUpdate(void (*updateFn)(void)); void shellRegisterDesktopUpdate(void (*updateFn)(void));
// Notify the desktop app that app state has changed (load, reap, crash).
void shellDesktopUpdate(void);
#endif // SHELL_APP_H #endif // SHELL_APP_H

View file

@ -57,7 +57,6 @@ static void (*sDesktopUpdateFn)(void) = NULL;
// ============================================================ // ============================================================
static void crashHandler(int sig); static void crashHandler(int sig);
static void desktopUpdate(void);
static void idleYield(void *ctx); static void idleYield(void *ctx);
static void installCrashHandler(void); static void installCrashHandler(void);
static void logCrash(int sig); static void logCrash(int sig);
@ -89,10 +88,10 @@ static void crashHandler(int sig) {
// ============================================================ // ============================================================
// desktopUpdate — notify desktop app of state change // shellDesktopUpdate — notify desktop app of state change
// ============================================================ // ============================================================
static void desktopUpdate(void) { void shellDesktopUpdate(void) {
if (sDesktopUpdateFn) { if (sDesktopUpdateFn) {
sDesktopUpdateFn(); sDesktopUpdateFn();
} }
@ -326,7 +325,7 @@ int main(void) {
sCurrentAppId = 0; sCurrentAppId = 0;
sCrashSignal = 0; sCrashSignal = 0;
desktopUpdate(); shellDesktopUpdate();
} }
// Main loop — runs until dvxQuit() sets sCtx.running = false. // Main loop — runs until dvxQuit() sets sCtx.running = false.
@ -347,7 +346,7 @@ int main(void) {
// This is the safe point for cleanup — we're at the top of the // This is the safe point for cleanup — we're at the top of the
// main loop, not inside any callback or compositor operation. // main loop, not inside any callback or compositor operation.
if (shellReapApps(&sCtx)) { if (shellReapApps(&sCtx)) {
desktopUpdate(); shellDesktopUpdate();
} }
} }