Task Manager display fixed. ListView can now auto-size columns to fit content.
This commit is contained in:
parent
8550fbbbf2
commit
fa8ab9da27
9 changed files with 72 additions and 14 deletions
|
|
@ -254,7 +254,8 @@ static void buildTaskManager(void) {
|
|||
WidgetT *root = wgtInitWindow(sAc, sTmWindow);
|
||||
|
||||
// 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].width = wgtPercent(35);
|
||||
tmCols[0].align = ListViewAlignLeftE;
|
||||
|
|
|
|||
|
|
@ -2718,7 +2718,7 @@ static void pollAnsiTermWidgetsWalk(AppContextT *ctx, WidgetT *w, WindowT *win)
|
|||
static void pollKeyboard(AppContextT *ctx) {
|
||||
int32_t shiftFlags = platformKeyboardGetModifiers();
|
||||
ctx->keyModifiers = shiftFlags;
|
||||
bool shiftHeld = (shiftFlags & 0x03) != 0; // left or right shift
|
||||
bool shiftHeld = (shiftFlags & KEY_MOD_SHIFT) != 0;
|
||||
|
||||
PlatformKeyEventT evt;
|
||||
|
||||
|
|
@ -2937,7 +2937,7 @@ static void pollKeyboard(AppContextT *ctx) {
|
|||
// Alt+Space — open/close system menu
|
||||
// Enhanced INT 16h: Alt+Space returns scancode 0x39, ascii 0x20
|
||||
// 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) {
|
||||
closeSysMenu(ctx);
|
||||
} else if (ctx->stack.focusedIdx >= 0) {
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ WidgetT *sResizeListView = NULL; // ListView undergoing column resize
|
|||
int32_t sResizeCol = -1; // which column is being resized
|
||||
int32_t sResizeStartX = 0; // mouse X 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
|
||||
int32_t sDragSplitStart = 0; // mouse offset from splitter edge at drag start
|
||||
WidgetT *sDragReorder = NULL; // list/tree widget in drag-reorder mode
|
||||
|
|
@ -202,6 +203,7 @@ void widgetDestroyChildren(WidgetT *w) {
|
|||
if (sResizeListView == child) {
|
||||
sResizeListView = NULL;
|
||||
sResizeCol = -1;
|
||||
sResizeDragging = false;
|
||||
}
|
||||
|
||||
if (sDragScrollbar == child) {
|
||||
|
|
|
|||
|
|
@ -313,11 +313,25 @@ void widgetOnMouse(WindowT *win, int32_t x, int32_t y, int32_t buttons) {
|
|||
if (sResizeListView && !(buttons & MOUSE_LEFT)) {
|
||||
sResizeListView = NULL;
|
||||
sResizeCol = -1;
|
||||
sResizeDragging = false;
|
||||
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 (!sResizeDragging) {
|
||||
if (x == sResizeStartX) {
|
||||
return;
|
||||
}
|
||||
|
||||
sResizeDragging = true;
|
||||
}
|
||||
|
||||
int32_t delta = x - sResizeStartX;
|
||||
int32_t newW = sResizeOrigW + delta;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 sResizeStartX; // mouse X at start of column 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 int32_t sDragSplitStart; // mouse position at start of splitter drag
|
||||
extern WidgetT *sDragReorder; // listbox/treeview item being drag-reordered
|
||||
|
|
|
|||
|
|
@ -893,11 +893,48 @@ void widgetListViewOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy)
|
|||
int32_t border = colX + cw;
|
||||
|
||||
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;
|
||||
sResizeCol = c;
|
||||
sResizeStartX = vx;
|
||||
sResizeOrigW = cw;
|
||||
sResizeDragging = false;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -415,6 +415,7 @@ int32_t shellLoadApp(AppContextT *ctx, const char *path) {
|
|||
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);
|
||||
shellDesktopUpdate();
|
||||
return id;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -178,4 +178,7 @@ void shellExportInit(void);
|
|||
// and is the only consumer.
|
||||
void shellRegisterDesktopUpdate(void (*updateFn)(void));
|
||||
|
||||
// Notify the desktop app that app state has changed (load, reap, crash).
|
||||
void shellDesktopUpdate(void);
|
||||
|
||||
#endif // SHELL_APP_H
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@ static void (*sDesktopUpdateFn)(void) = NULL;
|
|||
// ============================================================
|
||||
|
||||
static void crashHandler(int sig);
|
||||
static void desktopUpdate(void);
|
||||
static void idleYield(void *ctx);
|
||||
static void installCrashHandler(void);
|
||||
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) {
|
||||
sDesktopUpdateFn();
|
||||
}
|
||||
|
|
@ -326,7 +325,7 @@ int main(void) {
|
|||
|
||||
sCurrentAppId = 0;
|
||||
sCrashSignal = 0;
|
||||
desktopUpdate();
|
||||
shellDesktopUpdate();
|
||||
}
|
||||
|
||||
// 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
|
||||
// main loop, not inside any callback or compositor operation.
|
||||
if (shellReapApps(&sCtx)) {
|
||||
desktopUpdate();
|
||||
shellDesktopUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue