More optimizing.

This commit is contained in:
Scott Duensing 2026-03-14 20:27:59 -05:00
parent 54d9180d3e
commit e489f54ef0
17 changed files with 118 additions and 74 deletions

View file

@ -137,8 +137,6 @@ static void compositeAndFlush(AppContextT *ctx) {
RectT popIsect; RectT popIsect;
if (rectIntersect(dr, &popRect, &popIsect)) { if (rectIntersect(dr, &popRect, &popIsect)) {
setClipRect(d, dr->x, dr->y, dr->w, dr->h);
// Find the window and menu // Find the window and menu
for (int32_t j = 0; j < ws->count; j++) { for (int32_t j = 0; j < ws->count; j++) {
if (ws->windows[j]->id == ctx->popup.windowId) { if (ws->windows[j]->id == ctx->popup.windowId) {
@ -202,8 +200,6 @@ static void compositeAndFlush(AppContextT *ctx) {
RectT smIsect; RectT smIsect;
if (rectIntersect(dr, &smRect, &smIsect)) { if (rectIntersect(dr, &smRect, &smIsect)) {
setClipRect(d, dr->x, dr->y, dr->w, dr->h);
BevelStyleT smBevel; BevelStyleT smBevel;
smBevel.highlight = ctx->colors.windowHighlight; smBevel.highlight = ctx->colors.windowHighlight;
smBevel.shadow = ctx->colors.windowShadow; smBevel.shadow = ctx->colors.windowShadow;
@ -465,10 +461,10 @@ static void dispatchEvents(AppContextT *ctx) {
if (mx != ctx->prevMouseX || my != ctx->prevMouseY) { if (mx != ctx->prevMouseX || my != ctx->prevMouseY) {
dirtyCursorArea(ctx, ctx->prevMouseX, ctx->prevMouseY); dirtyCursorArea(ctx, ctx->prevMouseX, ctx->prevMouseY);
dirtyCursorArea(ctx, mx, my); dirtyCursorArea(ctx, mx, my);
}
// Update cursor shape based on what the mouse is hovering over // Update cursor shape based on what the mouse is hovering over
updateCursorShape(ctx); updateCursorShape(ctx);
}
// Handle active drag // Handle active drag
if (ctx->stack.dragWindow >= 0) { if (ctx->stack.dragWindow >= 0) {
@ -1380,9 +1376,16 @@ static void pollAnsiTermWidgetsWalk(AppContextT *ctx, WidgetT *w, WindowT *win)
static void pollKeyboard(AppContextT *ctx) { static void pollKeyboard(AppContextT *ctx) {
__dpmi_regs r; __dpmi_regs r;
// Check if key is available (INT 16h, enhanced function 11h) // Read shift state once per poll (INT 16h, AH=12h)
while (1) {
memset(&r, 0, sizeof(r)); memset(&r, 0, sizeof(r));
r.x.ax = 0x1200;
__dpmi_int(0x16, &r);
int32_t shiftFlags = r.x.ax & 0xFF;
bool shiftHeld = (shiftFlags & 0x03) != 0; // left or right shift
// Process buffered keys
while (1) {
// Check if key is available (INT 16h, enhanced function 11h)
r.x.ax = 0x1100; r.x.ax = 0x1100;
__dpmi_int(0x16, &r); __dpmi_int(0x16, &r);
@ -1392,7 +1395,6 @@ static void pollKeyboard(AppContextT *ctx) {
} }
// Read the key (INT 16h, enhanced function 10h) // Read the key (INT 16h, enhanced function 10h)
memset(&r, 0, sizeof(r));
r.x.ax = 0x1000; r.x.ax = 0x1000;
__dpmi_int(0x16, &r); __dpmi_int(0x16, &r);
@ -1406,13 +1408,6 @@ static void pollKeyboard(AppContextT *ctx) {
ascii = 0; ascii = 0;
} }
// Read shift state (INT 16h, AH=12h — enhanced shift flags)
memset(&r, 0, sizeof(r));
r.x.ax = 0x1200;
__dpmi_int(0x16, &r);
int32_t shiftFlags = r.x.ax & 0xFF;
bool shiftHeld = (shiftFlags & 0x03) != 0; // left or right shift
// Alt+Tab / Shift+Alt+Tab — cycle windows // Alt+Tab / Shift+Alt+Tab — cycle windows
// Alt+Tab: scancode=0xA5, ascii=0x00 // Alt+Tab: scancode=0xA5, ascii=0x00
if (ascii == 0 && scancode == 0xA5) { if (ascii == 0 && scancode == 0xA5) {

View file

@ -77,12 +77,15 @@ void dirtyListMerge(DirtyListT *dl) {
return; return;
} }
// Single-pass O(N²): for each rect, try to merge it into an
// earlier rect. When a merge succeeds the merged rect may now
// overlap others, so restart the inner scan for that slot.
for (int32_t i = 0; i < dl->count; i++) {
bool merged = true; bool merged = true;
while (merged) { while (merged) {
merged = false; merged = false;
for (int32_t i = 0; i < dl->count; i++) {
for (int32_t j = i + 1; j < dl->count; j++) { for (int32_t j = i + 1; j < dl->count; j++) {
if (rectsOverlapOrAdjacent(&dl->rects[i], &dl->rects[j], DIRTY_MERGE_GAP)) { if (rectsOverlapOrAdjacent(&dl->rects[i], &dl->rects[j], DIRTY_MERGE_GAP)) {
rectUnion(&dl->rects[i], &dl->rects[j], &dl->rects[i]); rectUnion(&dl->rects[i], &dl->rects[j], &dl->rects[i]);
@ -104,15 +107,12 @@ void dirtyListMerge(DirtyListT *dl) {
void flushRect(DisplayT *d, const RectT *r) { void flushRect(DisplayT *d, const RectT *r) {
int32_t bpp = d->format.bytesPerPixel; int32_t bpp = d->format.bytesPerPixel;
// Caller (compositeAndFlush) already clips to screen bounds
int32_t x = r->x; int32_t x = r->x;
int32_t y = r->y; int32_t y = r->y;
int32_t w = r->w; int32_t w = r->w;
int32_t h = r->h; int32_t h = r->h;
if (__builtin_expect(x < 0, 0)) { w += x; x = 0; }
if (__builtin_expect(y < 0, 0)) { h += y; y = 0; }
if (__builtin_expect(x + w > d->width, 0)) { w = d->width - x; }
if (__builtin_expect(y + h > d->height, 0)) { h = d->height - y; }
if (__builtin_expect(w <= 0 || h <= 0, 0)) { return; } if (__builtin_expect(w <= 0 || h <= 0, 0)) { return; }
int32_t rowBytes = w * bpp; int32_t rowBytes = w * bpp;

View file

@ -576,6 +576,9 @@ int32_t wgtAnsiTermRepaint(WidgetT *w, int32_t *outY, int32_t *outH);
// Mark a widget (and ancestors) for relayout and repaint // Mark a widget (and ancestors) for relayout and repaint
void wgtInvalidate(WidgetT *w); void wgtInvalidate(WidgetT *w);
// Repaint only — skip measure/layout (use for visual-only changes)
void wgtInvalidatePaint(WidgetT *w);
// Set/get widget text (label, button, textInput, etc.) // Set/get widget text (label, button, textInput, etc.)
void wgtSetText(WidgetT *w, const char *text); void wgtSetText(WidgetT *w, const char *text);
const char *wgtGetText(const WidgetT *w); const char *wgtGetText(const WidgetT *w);

View file

@ -1553,7 +1553,7 @@ void widgetAnsiTermOnKey(WidgetT *w, int32_t key, int32_t mod) {
if (ansiTermHasSelection(w)) { if (ansiTermHasSelection(w)) {
ansiTermCopySelection(w); ansiTermCopySelection(w);
ansiTermClearSelection(w); ansiTermClearSelection(w);
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -1563,7 +1563,7 @@ void widgetAnsiTermOnKey(WidgetT *w, int32_t key, int32_t mod) {
// Ctrl+V: paste from clipboard to terminal // Ctrl+V: paste from clipboard to terminal
if (key == 0x16 && (mod & KEY_MOD_CTRL)) { if (key == 0x16 && (mod & KEY_MOD_CTRL)) {
ansiTermPasteToComm(w); ansiTermPasteToComm(w);
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -1645,7 +1645,7 @@ void widgetAnsiTermOnKey(WidgetT *w, int32_t key, int32_t mod) {
w->as.ansiTerm.commWrite(w->as.ansiTerm.commCtx, buf, len); w->as.ansiTerm.commWrite(w->as.ansiTerm.commCtx, buf, len);
} }
wgtInvalidate(w); wgtInvalidatePaint(w);
} }
@ -1822,8 +1822,18 @@ void widgetAnsiTermPaint(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const Bit
// Determine if viewing live terminal or scrollback // Determine if viewing live terminal or scrollback
bool viewingLive = (w->as.ansiTerm.scrollPos == sbCount); bool viewingLive = (w->as.ansiTerm.scrollPos == sbCount);
// Render character cells row by row using bulk renderer // Render character cells row by row using bulk renderer.
// Only repaint rows marked dirty; 0xFFFFFFFF means all rows.
uint32_t dirty = w->as.ansiTerm.dirtyRows;
if (dirty == 0) {
dirty = 0xFFFFFFFF;
}
for (int32_t row = 0; row < rows; row++) { for (int32_t row = 0; row < rows; row++) {
if (row < 32 && !(dirty & (1U << row))) {
continue;
}
int32_t lineIndex = w->as.ansiTerm.scrollPos + row; int32_t lineIndex = w->as.ansiTerm.scrollPos + row;
const uint8_t *lineData = ansiTermGetLine(w, lineIndex); const uint8_t *lineData = ansiTermGetLine(w, lineIndex);
@ -1838,6 +1848,8 @@ void widgetAnsiTermPaint(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const Bit
ansiTermPaintSelRow(w, d, ops, font, row, baseX, baseY); ansiTermPaintSelRow(w, d, ops, font, row, baseX, baseY);
} }
w->as.ansiTerm.dirtyRows = 0;
// Draw scrollbar // Draw scrollbar
int32_t sbX = baseX + cols * cellW; int32_t sbX = baseX + cols * cellW;
int32_t sbY = baseY; int32_t sbY = baseY;

View file

@ -59,7 +59,7 @@ void widgetButtonOnKey(WidgetT *w, int32_t key, int32_t mod) {
if (key == ' ' || key == 0x0D) { if (key == ' ' || key == 0x0D) {
w->as.button.pressed = true; w->as.button.pressed = true;
sKeyPressedBtn = w; sKeyPressedBtn = w;
wgtInvalidate(w); wgtInvalidatePaint(w);
} }
} }

View file

@ -709,7 +709,7 @@ void widgetCanvasOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy) {
hit->as.canvas.lastX = cx; hit->as.canvas.lastX = cx;
hit->as.canvas.lastY = cy; hit->as.canvas.lastY = cy;
wgtInvalidate(hit); wgtInvalidatePaint(hit);
} }

View file

@ -64,7 +64,7 @@ void widgetCheckboxOnKey(WidgetT *w, int32_t key, int32_t mod) {
w->onChange(w); w->onChange(w);
} }
wgtInvalidate(w); wgtInvalidatePaint(w);
} }
} }

View file

@ -154,7 +154,7 @@ void widgetComboBoxOnKey(WidgetT *w, int32_t key, int32_t mod) {
} }
} }
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -167,7 +167,7 @@ void widgetComboBoxOnKey(WidgetT *w, int32_t key, int32_t mod) {
} }
} }
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -194,7 +194,7 @@ void widgetComboBoxOnKey(WidgetT *w, int32_t key, int32_t mod) {
w->onChange(w); w->onChange(w);
} }
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
} }
@ -213,7 +213,7 @@ void widgetComboBoxOnKey(WidgetT *w, int32_t key, int32_t mod) {
w->as.comboBox.listScrollPos = w->as.comboBox.hoverIdx; w->as.comboBox.listScrollPos = w->as.comboBox.hoverIdx;
} }
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -426,7 +426,7 @@ void widgetComboBoxPaintPopup(WidgetT *w, DisplayT *d, const BlitOpsT *ops, cons
rectFill(d, ops, popX + 2, iy, textW + TEXT_INPUT_PAD * 2, font->charHeight, ibg); rectFill(d, ops, popX + 2, iy, textW + TEXT_INPUT_PAD * 2, font->charHeight, ibg);
} }
drawText(d, ops, font, textX, iy, items[idx], ifg, ibg, idx == hoverIdx); drawText(d, ops, font, textX, iy, items[idx], ifg, ibg, false);
} }
} }

View file

@ -166,7 +166,7 @@ void widgetDropdownOnKey(WidgetT *w, int32_t key, int32_t mod) {
} }
} }
wgtInvalidate(w); wgtInvalidatePaint(w);
} }
@ -280,6 +280,6 @@ void widgetDropdownPaintPopup(WidgetT *w, DisplayT *d, const BlitOpsT *ops, cons
rectFill(d, ops, popX + 2, iy, textW + TEXT_INPUT_PAD * 2, font->charHeight, ibg); rectFill(d, ops, popX + 2, iy, textW + TEXT_INPUT_PAD * 2, font->charHeight, ibg);
} }
drawText(d, ops, font, textX, iy, items[idx], ifg, ibg, idx == hoverIdx); drawText(d, ops, font, textX, iy, items[idx], ifg, ibg, false);
} }
} }

View file

@ -192,21 +192,21 @@ void widgetOnMouse(WindowT *win, int32_t x, int32_t y, int32_t buttons) {
sDrawingCanvas->as.canvas.lastX = -1; sDrawingCanvas->as.canvas.lastX = -1;
sDrawingCanvas->as.canvas.lastY = -1; sDrawingCanvas->as.canvas.lastY = -1;
sDrawingCanvas = NULL; sDrawingCanvas = NULL;
wgtInvalidate(root); wgtInvalidatePaint(root);
return; return;
} }
// Handle canvas drawing (mouse move while pressed) // Handle canvas drawing (mouse move while pressed)
if (sDrawingCanvas && (buttons & 1)) { if (sDrawingCanvas && (buttons & 1)) {
widgetCanvasOnMouse(sDrawingCanvas, root, x, y); widgetCanvasOnMouse(sDrawingCanvas, root, x, y);
wgtInvalidate(root); wgtInvalidatePaint(root);
return; return;
} }
// Handle slider drag release // Handle slider drag release
if (sDragSlider && !(buttons & 1)) { if (sDragSlider && !(buttons & 1)) {
sDragSlider = NULL; sDragSlider = NULL;
wgtInvalidate(root); wgtInvalidatePaint(root);
return; return;
} }
@ -242,7 +242,7 @@ void widgetOnMouse(WindowT *win, int32_t x, int32_t y, int32_t buttons) {
sDragSlider->onChange(sDragSlider); sDragSlider->onChange(sDragSlider);
} }
wgtInvalidate(root); wgtInvalidatePaint(root);
} }
} }
@ -272,7 +272,7 @@ void widgetOnMouse(WindowT *win, int32_t x, int32_t y, int32_t buttons) {
} }
} }
wgtInvalidate(sPressedButton); wgtInvalidatePaint(sPressedButton);
sPressedButton = NULL; sPressedButton = NULL;
return; return;
} }
@ -302,7 +302,7 @@ void widgetOnMouse(WindowT *win, int32_t x, int32_t y, int32_t buttons) {
sPressedButton->as.button.pressed = over; sPressedButton->as.button.pressed = over;
} }
wgtInvalidate(sPressedButton); wgtInvalidatePaint(sPressedButton);
} }
return; return;
@ -376,7 +376,7 @@ void widgetOnMouse(WindowT *win, int32_t x, int32_t y, int32_t buttons) {
} }
sOpenPopup = NULL; sOpenPopup = NULL;
wgtInvalidate(root); wgtInvalidatePaint(root);
// Fall through to normal click handling // Fall through to normal click handling
} }

View file

@ -141,7 +141,7 @@ void widgetImageOnMouse(WidgetT *w, WidgetT *root, int32_t vx, int32_t vy) {
(void)vx; (void)vx;
(void)vy; (void)vy;
w->as.image.pressed = true; w->as.image.pressed = true;
wgtInvalidate(w); wgtInvalidatePaint(w);
if (w->onClick) { if (w->onClick) {
w->onClick(w); w->onClick(w);

View file

@ -77,7 +77,7 @@ void widgetImageButtonOnKey(WidgetT *w, int32_t key, int32_t mod) {
if (key == ' ' || key == 0x0D) { if (key == ' ' || key == 0x0D) {
w->as.imageButton.pressed = true; w->as.imageButton.pressed = true;
sKeyPressedBtn = w; sKeyPressedBtn = w;
wgtInvalidate(w); wgtInvalidatePaint(w);
} }
} }

View file

@ -156,7 +156,7 @@ void widgetListBoxOnKey(WidgetT *w, int32_t key, int32_t mod) {
w->onChange(w); w->onChange(w);
} }
wgtInvalidate(w); wgtInvalidatePaint(w);
} }
@ -292,7 +292,7 @@ void widgetListBoxPaint(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const Bitm
rectFill(d, ops, w->x + LISTBOX_BORDER, iy, contentW, font->charHeight, ibg); rectFill(d, ops, w->x + LISTBOX_BORDER, iy, contentW, font->charHeight, ibg);
} }
drawText(d, ops, font, innerX, iy, w->as.listBox.items[idx], ifg, ibg, idx == w->as.listBox.selectedIdx); drawText(d, ops, font, innerX, iy, w->as.listBox.items[idx], ifg, ibg, false);
} }
// Draw scrollbar // Draw scrollbar

View file

@ -250,6 +250,40 @@ void wgtInvalidate(WidgetT *w) {
} }
// ============================================================
// wgtInvalidatePaint
// ============================================================
//
// Lightweight repaint — skips measure/layout/scrollbar management.
// Use when only visual state changed (slider value, cursor blink,
// selection highlight, checkbox toggle) but widget sizes are stable.
void wgtInvalidatePaint(WidgetT *w) {
if (!w || !w->window) {
return;
}
WidgetT *root = w;
while (root->parent) {
root = root->parent;
}
AppContextT *ctx = (AppContextT *)root->userData;
if (!ctx) {
return;
}
// Repaint without measure/layout
RectT fullRect = {0, 0, w->window->contentW, w->window->contentH};
widgetOnPaint(w->window, &fullRect);
w->window->contentDirty = true;
dvxInvalidateWindow(ctx, w->window);
}
// ============================================================ // ============================================================
// wgtPaint // wgtPaint
// ============================================================ // ============================================================

View file

@ -92,7 +92,7 @@ void widgetRadioOnKey(WidgetT *w, int32_t key, int32_t mod) {
} }
} }
wgtInvalidate(w); wgtInvalidatePaint(w);
} else if (key == (0x50 | 0x100) || key == (0x4D | 0x100)) { } else if (key == (0x50 | 0x100) || key == (0x4D | 0x100)) {
// Down or Right — next radio in group // Down or Right — next radio in group
if (w->parent && w->parent->type == WidgetRadioGroupE) { if (w->parent && w->parent->type == WidgetRadioGroupE) {
@ -115,7 +115,7 @@ void widgetRadioOnKey(WidgetT *w, int32_t key, int32_t mod) {
next->parent->onChange(next->parent); next->parent->onChange(next->parent);
} }
wgtInvalidate(next); wgtInvalidatePaint(next);
} }
} }
} else if (key == (0x48 | 0x100) || key == (0x4B | 0x100)) { } else if (key == (0x48 | 0x100) || key == (0x4B | 0x100)) {
@ -139,7 +139,7 @@ void widgetRadioOnKey(WidgetT *w, int32_t key, int32_t mod) {
prev->parent->onChange(prev->parent); prev->parent->onChange(prev->parent);
} }
wgtInvalidate(prev); wgtInvalidatePaint(prev);
} }
} }
} }

View file

@ -119,7 +119,7 @@ void widgetSliderOnKey(WidgetT *w, int32_t key, int32_t mod) {
w->onChange(w); w->onChange(w);
} }
wgtInvalidate(w); wgtInvalidatePaint(w);
} }

View file

@ -697,7 +697,7 @@ done:
} }
} }
wgtInvalidate(w); wgtInvalidatePaint(w);
} }
@ -948,7 +948,7 @@ void widgetTextAreaOnKey(WidgetT *w, int32_t key, int32_t mod) {
textAreaOffToRowCol(buf, *pLen, pRow, pCol); textAreaOffToRowCol(buf, *pLen, pRow, pCol);
w->as.textArea.desiredCol = *pCol; w->as.textArea.desiredCol = *pCol;
textAreaEnsureVisible(w, visRows, visCols); textAreaEnsureVisible(w, visRows, visCols);
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -996,7 +996,7 @@ void widgetTextAreaOnKey(WidgetT *w, int32_t key, int32_t mod) {
} }
textAreaEnsureVisible(w, visRows, visCols); textAreaEnsureVisible(w, visRows, visCols);
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -1023,7 +1023,7 @@ void widgetTextAreaOnKey(WidgetT *w, int32_t key, int32_t mod) {
} }
textAreaEnsureVisible(w, visRows, visCols); textAreaEnsureVisible(w, visRows, visCols);
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -1067,7 +1067,7 @@ void widgetTextAreaOnKey(WidgetT *w, int32_t key, int32_t mod) {
} }
textAreaEnsureVisible(w, visRows, visCols); textAreaEnsureVisible(w, visRows, visCols);
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -1105,7 +1105,7 @@ void widgetTextAreaOnKey(WidgetT *w, int32_t key, int32_t mod) {
} }
textAreaEnsureVisible(w, visRows, visCols); textAreaEnsureVisible(w, visRows, visCols);
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -1144,7 +1144,7 @@ void widgetTextAreaOnKey(WidgetT *w, int32_t key, int32_t mod) {
} }
textAreaEnsureVisible(w, visRows, visCols); textAreaEnsureVisible(w, visRows, visCols);
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -1181,7 +1181,7 @@ void widgetTextAreaOnKey(WidgetT *w, int32_t key, int32_t mod) {
} }
textAreaEnsureVisible(w, visRows, visCols); textAreaEnsureVisible(w, visRows, visCols);
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -1197,7 +1197,7 @@ void widgetTextAreaOnKey(WidgetT *w, int32_t key, int32_t mod) {
w->as.textArea.desiredCol = *pCol; w->as.textArea.desiredCol = *pCol;
SEL_END(); SEL_END();
textAreaEnsureVisible(w, visRows, visCols); textAreaEnsureVisible(w, visRows, visCols);
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -1213,7 +1213,7 @@ void widgetTextAreaOnKey(WidgetT *w, int32_t key, int32_t mod) {
w->as.textArea.desiredCol = *pCol; w->as.textArea.desiredCol = *pCol;
SEL_END(); SEL_END();
textAreaEnsureVisible(w, visRows, visCols); textAreaEnsureVisible(w, visRows, visCols);
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -1229,7 +1229,7 @@ void widgetTextAreaOnKey(WidgetT *w, int32_t key, int32_t mod) {
SEL_END(); SEL_END();
textAreaEnsureVisible(w, visRows, visCols); textAreaEnsureVisible(w, visRows, visCols);
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -1245,7 +1245,7 @@ void widgetTextAreaOnKey(WidgetT *w, int32_t key, int32_t mod) {
SEL_END(); SEL_END();
textAreaEnsureVisible(w, visRows, visCols); textAreaEnsureVisible(w, visRows, visCols);
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -1256,7 +1256,7 @@ void widgetTextAreaOnKey(WidgetT *w, int32_t key, int32_t mod) {
w->as.textArea.desiredCol = 0; w->as.textArea.desiredCol = 0;
SEL_END(); SEL_END();
textAreaEnsureVisible(w, visRows, visCols); textAreaEnsureVisible(w, visRows, visCols);
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -1267,7 +1267,7 @@ void widgetTextAreaOnKey(WidgetT *w, int32_t key, int32_t mod) {
w->as.textArea.desiredCol = *pCol; w->as.textArea.desiredCol = *pCol;
SEL_END(); SEL_END();
textAreaEnsureVisible(w, visRows, visCols); textAreaEnsureVisible(w, visRows, visCols);
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -1284,7 +1284,7 @@ void widgetTextAreaOnKey(WidgetT *w, int32_t key, int32_t mod) {
*pCol = w->as.textArea.desiredCol < lineL ? w->as.textArea.desiredCol : lineL; *pCol = w->as.textArea.desiredCol < lineL ? w->as.textArea.desiredCol : lineL;
SEL_END(); SEL_END();
textAreaEnsureVisible(w, visRows, visCols); textAreaEnsureVisible(w, visRows, visCols);
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -1301,7 +1301,7 @@ void widgetTextAreaOnKey(WidgetT *w, int32_t key, int32_t mod) {
*pCol = w->as.textArea.desiredCol < lineL ? w->as.textArea.desiredCol : lineL; *pCol = w->as.textArea.desiredCol < lineL ? w->as.textArea.desiredCol : lineL;
SEL_END(); SEL_END();
textAreaEnsureVisible(w, visRows, visCols); textAreaEnsureVisible(w, visRows, visCols);
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -1313,7 +1313,7 @@ void widgetTextAreaOnKey(WidgetT *w, int32_t key, int32_t mod) {
w->as.textArea.desiredCol = 0; w->as.textArea.desiredCol = 0;
SEL_END(); SEL_END();
textAreaEnsureVisible(w, visRows, visCols); textAreaEnsureVisible(w, visRows, visCols);
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -1324,7 +1324,7 @@ void widgetTextAreaOnKey(WidgetT *w, int32_t key, int32_t mod) {
w->as.textArea.desiredCol = *pCol; w->as.textArea.desiredCol = *pCol;
SEL_END(); SEL_END();
textAreaEnsureVisible(w, visRows, visCols); textAreaEnsureVisible(w, visRows, visCols);
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -1361,7 +1361,7 @@ void widgetTextAreaOnKey(WidgetT *w, int32_t key, int32_t mod) {
} }
textAreaEnsureVisible(w, visRows, visCols); textAreaEnsureVisible(w, visRows, visCols);
wgtInvalidate(w); wgtInvalidatePaint(w);
return; return;
} }
@ -2520,5 +2520,5 @@ adjustScroll:
} }
} }
wgtInvalidate(w); wgtInvalidatePaint(w);
} }