feat: dynamic terminal resizing with scrollback#61
feat: dynamic terminal resizing with scrollback#61Mauricio-Leyva wants to merge 2 commits intoviralcode:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds dynamic terminal resizing with full scrollback support to the Vib-OS GUI terminal emulator. When the terminal window is resized, the terminal buffer dynamically adjusts its character grid dimensions, and content that scrolls off the top is preserved in a ring-buffer scrollback that users can browse with arrow keys. The event loop is also updated to trigger redraws on keyboard events for responsive scrollback navigation.
Changes:
- Added a ring-buffer scrollback system (
TERM_SCROLLBACK_LINES = 200) with save/restore on scroll and resize, and arrow key–driven viewport scrolling interminal.c. - Implemented
term_resize()to dynamically recalculate rows/cols from pixel dimensions, with proper content migration (pulling from scrollback when growing, pushing to scrollback when shrinking). - Updated the event loop in
main.cto set aneeds_redrawflag on virtio keyboard events and disabled the init process launch (documented as not yet ready).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
| kernel/gui/terminal.c | Core changes: scrollback ring buffer, term_save_to_scrollback, scrollback-aware rendering, arrow key scroll handling, term_resize, updated term_create with scrollback allocation and clamping. |
| kernel/gui/window.c | Calls term_resize from draw_window so the terminal adapts to window size changes; added term_resize extern declaration. |
| kernel/core/main.c | Resized default terminal window, added g_key_pressed flag for keyboard-triggered redraws, disabled init process with explanatory comment. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
kernel/gui/terminal.c
Outdated
| if (nsbc) { | ||
| /* Fill with blank spaces */ | ||
| for (size_t i = 0; i < ss; i++) { | ||
| nsbc[i] = ' '; nsbf[i] = 7; nsbb[i] = 0; |
There was a problem hiding this comment.
The null check only verifies nsbc, but if nsbf or nsbb failed to allocate (returned NULL), the code will dereference NULL pointers on lines 1440, 1450, and 1451 when writing to nsbf[i] and nsbb[i]. All three allocations should be null-checked before proceeding. If any of them fail, the allocated ones should be freed and the function should skip the scrollback migration (or bail out entirely).
| /* Allocate scrollback buffer */ | ||
| size_t sb_size = TERM_SCROLLBACK_LINES * cols; | ||
| term->sb_chars = kmalloc(sb_size); | ||
| term->sb_fg = kmalloc(sb_size); | ||
| term->sb_bg = kmalloc(sb_size); | ||
| term->sb_count = 0; | ||
| term->sb_head = 0; | ||
| term->scroll_offset = 0; |
There was a problem hiding this comment.
term_destroy() (line 1368) does not free the scrollback buffers sb_chars, sb_fg, and sb_bg that are now allocated in term_create(). This is a memory leak. The scrollback buffers should be freed in term_destroy() alongside the other buffers. Since those fields are added by this PR, the destroy function needs to be updated to match.
kernel/core/main.c
Outdated
| * the system to hang. TODO: implement proper syscall handlers before | ||
| * re-enabling init. | ||
| */ | ||
| printk(KERN_INFO "Skipping /sbin/init (GUI runs in kernel mode)\\n"); |
There was a problem hiding this comment.
\\n is a double-escaped newline that will output a literal \n string instead of a newline character. All other printk calls in this file use \n. This should be \n instead of \\n.
kernel/gui/terminal.c
Outdated
| #define TERM_HISTORY_LEN 128 | ||
| char history[32][128]; | ||
| int history_count; | ||
| int history_browse; /* Index when browsing with arrow keys */ |
There was a problem hiding this comment.
The history_browse field is added and initialized but never actually used anywhere. If the intent is to allow browsing command history with arrow keys (as suggested by the welcome message "Use Arrow Up/Down to scroll history"), note that the arrow keys currently control scrollback instead. Consider either implementing history browsing or removing this unused field to avoid confusion.
| int history_browse; /* Index when browsing with arrow keys */ |
kernel/gui/terminal.c
Outdated
| term_puts(term, "Type '\033[33mhelp\033[0m' for commands, " | ||
| "'\033[33mneofetch\033[0m' for system info.\n\n"); | ||
| "'\033[33mneofetch\033[0m' for system info.\n"); | ||
| term_puts(term, "Use \033[33mArrow Up/Down\033[0m to scroll history.\n\n"); |
There was a problem hiding this comment.
The welcome message says "scroll history" but the arrow keys actually control scrollback (viewport scrolling), not command history browsing. This could confuse users who expect arrow up/down to recall previous commands (standard shell behavior). Consider changing the text to "Use Arrow Up/Down to scroll back" or similar wording that accurately describes the scrollback behavior.
| term_puts(term, "Use \033[33mArrow Up/Down\033[0m to scroll history.\n\n"); | |
| term_puts(term, "Use \033[33mArrow Up/Down\033[0m to scroll back.\n\n"); |
kernel/gui/terminal.c
Outdated
| /* 2. Allocate new visible screen buffer */ | ||
| size_t new_size = (size_t)new_cols * new_rows; | ||
| char *nc = kmalloc(new_size); | ||
| uint8_t *nfg = kmalloc(new_size); | ||
| uint8_t *nbg = kmalloc(new_size); | ||
| if (!nc || !nfg || !nbg) { | ||
| if (nc) kfree(nc); if (nfg) kfree(nfg); if (nbg) kfree(nbg); | ||
| return; | ||
| } |
There was a problem hiding this comment.
If the visible buffer allocation fails here (lines 1467-1469), the function returns early. However, the scrollback buffer may have already been reallocated to new_cols stride in step 1 (lines 1431-1460), while t->cols still holds the old column count. Subsequent calls to term_save_to_scrollback and term_render will use t->cols as the stride into the scrollback buffer, causing out-of-bounds access or data corruption since the scrollback now has new_cols stride. You need to either update t->cols before returning, or roll back the scrollback reallocation on failure.
kernel/gui/terminal.c
Outdated
| if (term->sb_chars) { | ||
| for (size_t i = 0; i < sb_size; i++) { | ||
| term->sb_chars[i] = ' '; | ||
| term->sb_fg[i] = 7; | ||
| term->sb_bg[i] = 0; | ||
| } |
There was a problem hiding this comment.
The null check only verifies sb_chars before initialization, but if sb_fg or sb_bg failed to allocate, lines 1325 and 1326 will write to NULL pointers. Either check all three pointers, or add the scrollback buffers to the error check at line 1304 (e.g., if (!term->sb_chars || !term->sb_fg || !term->sb_bg) alongside the other checks).
|
@Mauricio-Leyva did you test this and can you provide a video. i want you to test the last fix commit @9a8d008 |
|
Yes, I have tested the latest commit 9a8d008 and everything is working smoothly. Here is the video showing the terminal resizing and scrollback: dynamic_terminal.mp4 |
Dynamic Terminal Resizing with full scrollback
Added dynamic calculation of rows/cols based on window size.
Rewrote term_resize() to properly reflow scrolling when shrinking/expanding window diagonals, matching native terminal behavior.
Fixed event loop to properly trigger needs_redraw on keyboard events so Arrow Up/Down scrollback works beautifully.