summaryrefslogtreecommitdiffstatshomepage
path: root/src/nvim/window.c
AgeCommit message (Collapse)AuthorFiles
2026-04-22vim-patch:9.2.0356: Cannot apply 'scrolloff' context lines at end of filezeertzjq1
Problem: Cannot apply 'scrolloff' context lines at end of file Solution: Add the 'scrolloffpad' option to keep 'scrolloff' context even when at the end of the file (McAuley Penney). closes: vim/vim#19040 https://github.com/vim/vim/commit/a414630393f81c9a5b8fa4d0fcc1287155f67751 Co-authored-by: McAuley Penney <jacobmpenney@gmail.com>
2026-04-21fix(move): avoid integer overflow with large 'scrolloff' (#39251)zeertzjq1
2026-04-19feat(options): add 'winpinned' to pin a window #39157luukvbaal1
Problem: - Unable to "pin" a window to prevent closing without specifically being targeted. - :fclose closes hidden windows (even before visible windows). Solution: - Add 'winpinned' window-local option. When set, window is skipped by :fclose and :only. Pin the ui2 cmdline window (which should always be visible), so that it is not closed by :only/fclose. - Skip over hidden (and pinned) windows with :fclose. Co-authored-by: glepnir <glephunter@gmail.com>
2026-04-16fix(float): don't unload 'hidden' float buffer with :close! (#39096)luukvbaal1
Problem: When closing floating windows to close a tabpage, if the current buffer will unload, buffers contained in those floating windows will too (unexpectedly). Solution: Don't pass along "free_buf" argument; check 'bufhidden' for the buffer in the to be closed float.
2026-04-14build: update clang v21, fix warningsdundargoc1
- `src/nvim/ex_cmds_defs.h`: use "U" instead of "u" per `readability-uppercase-literal-suffix`
2026-03-31fix(window): clear cmdline 'ruler' when window is closed #38631luukvbaal1
Problem: When 'ruler' is in last line of the screen and the current floating window is closed, the ruler is not cleared. Solution: When closing the current floating window, redraw the cmdline if that contained, and will no longer contain the 'ruler'.
2026-03-29vim-patch:9.2.0254: w_locked can be bypassed when setting recursivelySean Dewar1
Problem: w_locked can be bypassed when recursively set if not restored to its prior value. Solution: Rather than save/restore everywhere, just make it a count, like other locks (Sean Dewar) Requires the previous commit, otherwise b_nwindows will be wrong in tests, which causes a bunch of weird failures. closes: vim/vim#19728 https://github.com/vim/vim/commit/7cb43f286e55853cf21b9d8870a430390c1cc8f1 Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
2026-03-29vim-patch:9.2.0253: various issues with wrong b_nwindows after closing buffersSean Dewar1
Problem: close_buffer() callers incorrectly handle b_nwindows, especially after nasty autocmds, allowing it to go out-of-sync. May lead to buffers that can't be unloaded, or buffers that are prematurely freed whilst displayed. Solution: Modify close_buffer() and review its callers; let them decrement b_nwindows if it didn't unload the buffer. Remove some now unneeded workarounds like 8.2.2354, 9.1.0143, 9.1.0764, which didn't always work (Sean Dewar) (endless yapping omitted) related: vim/vim#19728 https://github.com/vim/vim/commit/bf21df1c7bc772e3a29961c961d0821584d50ee0 b_nwindows = 0 change for free_all_mem() was already ported. Originally Nvim returned true when b_nwindows was decremented before the end was reached (to better indicate the decrement). That's not needed anymore, so just return true only at the end, like Vim. (retval isn't used anywhere now anyways) Set textlock for dict watchers at the end of close_buffer() to prevent them from switching windows, as that can leave a window with a NULL buffer. (possible before this PR, but the new assert catches it; added a test) Despite textlock, things still aren't ideal, as watchers may observe the buffer as unloaded and hidden (b_nwindows was decremented), yet still in a window... Likewise, for Nvim, wipe_qf_buffer()'s comment may not be entirely accurate; autocmds are blocked, but on_detach callbacks (textlocked) and dict watchers may still run. Might be problematic, but those aren't new issues. Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
2026-03-17vim-patch:9.2.0180: possible crash with winminheight=0 (#38335)zeertzjq1
Problem: possible crash with winminheight=0 (Emilien Breton) Solution: Use <= instead of < when checking reserved room in frame_setheight() to correctly handle the zero-height boundary case (Hirohito Higashi). In frame_setheight(), when shrinking the current window and the only other window has 'winfixheight' with 'winminheight'=0, room_reserved was not cleared because the condition used '<' instead of '<='. The freed rows were discarded, leaving fr_height sum less than topframe fr_height. Subsequent resize operations then computed a wrong room_cmdline that expanded topframe beyond the screen, causing a crash. fixes: vim/vim#19706 closes: vim/vim#19712 https://github.com/vim/vim/commit/a5d9654620648ea6d3f2f8dc2a3e42de219cf860 Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
2026-03-16fix: nvim_open_tabpage cleanup, fixes, more testsSean Dewar1
- Cleanup, remove redundant comments, add more tests. - Enhance win_new_tabpage rather than create a new function for !enter, and use a different approach that minimizes side-effects. Return the tabpage_T * and first win_T * it allocated. - Disallow during textlock, like other APIs that open windows. - Remove existing win_alloc_firstwin error handling from win_new_tabpage; it's not needed, and looks incorrect. (enter_tabpage is called for curtab, which is not the old tabpage! Plus newtp is not freed) - Fix checks after creating the tabpage: - Don't fail if buf wasn't set successfully; the tab page may still be valid regardless. Set buffer like nvim_open_win, possibly blocking Enter/Leave events. (except BufWinEnter) - tp_curwin may not be the initial window opened by win_new_tabpage. Use the win_T * it returns instead, which is the real first window it allocated, regardless of autocmd shenanigans. - Properly check whether tab page was freed; it may have also been freed before win_set_buf. Plus, it may not be safe to read its handle!
2026-03-16feat(api): add nvim_open_tabpageWill Hopkins1
Problem: no API function for opening a new tab page and returning its handle, or to open without entering. Solution: add nvim_open_tabpage.
2026-03-15feat(help): super K (":help!") guesses tag at cursor #36205Justin M. Keyes1
Problem: `K` in help files may fail in some noisy text. Example: (`fun(config: vim.lsp.ClientConfig): boolean`) ^cursor Solution: - `:help!` (bang, no args) activates DWIM behavior: tries `<cWORD>`, then trims punctuation until a valid tag is found. - Set `keywordprg=:help!` by default. - Does not affect `CTRL-]`, that is still fully "tags" based.
2026-03-14fix(api): disallow moving window between tabpages in more casesSean Dewar1
Problem: more cases where it may not be safe to move a window between tabpages. Solution: check them. Rather speculative... I haven't spend much time looking, but I didn't find existing code that sets these locks to skip checking win_valid. (what I did find called it anyway, like in win_close) Still, I think it's a good precaution for what future code might do. If the fact that nvim_win_set_config *actually* moves windows between tabpages causes unforeseen issues, "faking" it like ":wincmd T" may be an alternative: split a new window, close the old one, but instead also block autocmds, copy the old window's config, and give it its handle?
2026-03-14refactor(window): lastwin_nofloating takes tpSean Dewar1
2026-03-14fix(window): don't leak fold memory with style=minimal #38287Sean Dewar1
Problem: discarding saved option values in the WinInfo of closed style=minimal windows leaks memory. Solution: also free the nested folds.
2026-03-08fix(api): merge split window config only on successSean Dewar1
Problem: nvim_win_set_config may merge configs despite failing to configure a split, and without applying necessary side-effects (like setting style=minimal options). Plus, autocommands may apply a different config after the merge, causing side-effects to apply for an outdated config. Solution: merge configs last, only on success. Include fields only relevant to splits. Properly set _cmdline_offset for splits. Maybe better to disallow _cmdline_offset for splits instead, as the pum is relative to cmdline_row anyway? (I didn't want to change behaviour too much) Also use expect_unchanged in an unrelated test to quash a warning.
2026-03-03fix(window): style=minimal window loses local options when switching buffers ↵glepnir1
#38138 Problem: 5943a81 skips saving window options in `buflist_altfpos` for style=minimal windows, which also prevents the window from restoring its own options when switching buffers. Solution: revert the change. In `get_winopts`, don't restore options from the `WinInfo` of style=minimal windows when reusing values for a different window. In `win_free`, clear `wi_optset` for minimal windows.
2026-02-15vim-patch:9.2.0004: Changing hidden prompt buffer cancels ↵zeertzjq1
:startinsert/:stopinsert (#37881) Problem: Changing hidden prompt buffer cancels :startinsert/:stopinsert (after 9.0.1439). Solution: Don't change mode for a prompt buffer in an autocommand window (zeertzjq). closes: vim/vim#19410 https://github.com/vim/vim/commit/8b81a6b6e1d514cf0544e0c6d12412ba813564b0
2026-02-12fix(api): preserve WinConfig style when converting float to split #37264glepnir1
Problem: When a float window with style='minimal' is converted to a split window and then changes buffer, the minimal style options get overridden. This happens because merge_win_config() clears the style field, so get_winopts() doesn't know to re-apply minimal style after restoring options from the buffer's wininfo. Solution: Save and restore the style field when clearing the config during float-to-split conversion.
2026-02-08fix(window): use real last buffer of closed windowSean Dewar1
Problem: close_buffer autocmds may switch buffers at the last moment when closing a window, causing terminal_check_size to prefer the size of a closed window, or TabClosed to set an old <abuf>. Solution: use the actual last buffer, similar to what TabClosed did before. NOTE: If buffer was unloaded/deleted (not wiped), then TabClosed's <abuf> may not use it. (w_buffer = NULL) Maybe odd, but it's how it worked before anyhow. Relies on close_buffer reliably setting w_buffer to NULL if freed, otherwise buf_valid is better. Only concern I see is if the window wasn't in the window list after closing the buffer (close_buffer won't set it to NULL then), but then win_close{_othertab} should've returned earlier.
2026-02-08fix(autocmd): potential TabClosed UAF, always set abufSean Dewar1
Problem: win_free_mem can free w_buffer (via qf_free_all), which may cause a heap use-after-free if used as TabClosed's <abuf>. I think TabClosed is also the only event to conditionally set <abuf> not based on event type. Solution: use the buffer saved by the bufref. Fall back to curbuf if invalid, like WinResized/WinScrolled. NOTE: Not always equivalent if close_buffer autocmds switch buffers at the last moment; previously <abuf> would be set to that buffer. Fixed in next commit. https://github.com/neovim/neovim/actions/runs/21765657455/job/62800643599?pr=37758#step:9:159 for an example of qf_free_all being a nuisance.
2026-02-08fix(terminal): update size after closing windowSean Dewar1
Problem: terminal's size may not update after one of its windows close. Solution: call terminal_check_size after closing a window. Disable test for Windows, as for some reason it only shows a few lines...
2026-01-20vim-patch:9.1.2097: TabClosedPre may be triggered twice for the same tab pagezeertzjq1
Problem: TabClosedPre may be triggered twice for the same tab page when closing another tab page in BufWinLeave (after 9.1.1211). Solution: Store whether TabClosedPre was triggered in tabpage_T (zeertzjq). Also fix the inconsistency that :tabclose! triggers TabClosedPre after a failed :tabclose, but :close! doesn't even if there is only one window in the tab page. closes: vim/vim#19211 https://github.com/vim/vim/commit/9168a04e0c63c95eec643dab14a8e0a8933d90e7
2026-01-20vim-patch:9.1.2093: heap-use-after-free when wiping buffer in TabClosedPrezeertzjq1
Problem: heap-use-after-free when wiping buffer in TabClosedPre. Solution: Check window_layout_locked() when closing window(s) in another tabpage (zeertzjq). closes: vim/vim#19196 https://github.com/vim/vim/commit/8fc7042b3da3939213bb3f4216dc581703a954dd
2026-01-20vim-patch:9.1.1211: TabClosedPre is triggered just before the tab is being freedzeertzjq1
Problem: TabClosedPre is triggered just before the tab is being freed, which limited its functionality. Solution: Trigger it a bit earlier and also on :tabclose and :tabonly (Jim Zhou) closes: vim/vim#16890 https://github.com/vim/vim/commit/bcf66e014141982192e2743829bceef60ce77727 Co-authored-by: Jim Zhou <jimzhouzzy@gmail.com>
2026-01-20vim-patch:9.1.1202: Missing TabClosedPre autocommandzeertzjq1
Problem: Missing TabClosedPre autocommand (zoumi) Solution: Add the TabClosedPre autcommand (Jim Zhou). fixes: vim/vim#16518 closes: vim/vim#16855 https://github.com/vim/vim/commit/5606ca5349982fe53cc6a2ec6345aa66f0613d40 Co-authored-by: Jim Zhou <jimzhouzzy@gmail.com>
2026-01-17vim-patch:9.1.2087: Crash when using :tabonly in BufUnloadzeertzjq1
Problem: Crash when using :tabonly in BufUnload. Solution: Set curbuf when setting curwin->w_buffer. Don't wipe out a buffer if there are no other buffers. Don't decrement b_nwindows if it was 0 before buf_freeall() (zeertzjq). fixes: vim/vim#19088#issuecomment-3710172769 closes: vim/vim#19186 https://github.com/vim/vim/commit/fa64f92f6ab8b8080bdba77155e7bb3530fa21f6
2026-01-17vim-patch:9.0.0909: error message for layout change does not match action ↵zeertzjq1
(#37436) Problem: Error message for layout change does not match action. Solution: Pass the command to where the error is given. (closes vim/vim#11573) https://github.com/vim/vim/commit/9fda81515b26ecd3c1e99f95334aaed3f7b6fea3 Thinking about this again, it's actually OK to check split_disallowed in window_layout_locked(), so add the check. Also add missing window_layout_locked() in tabpage_close(). Co-authored-by: Bram Moolenaar <Bram@vim.org>
2026-01-16vim-patch:9.1.0671: Problem: crash with WinNewPre autocommandzeertzjq1
Problem: crash with WinNewPre autocommand, because window structures are not yet safe to use Solution: Don't trigger WinNewPre on :tabnew https://github.com/vim/vim/commit/fb3f9699362f8d51c3b48fcaea1eb2ed16c81454 Cherry-pick doc updates from latest Vim runtime. Co-authored-by: Christian Brabandt <cb@256bit.org>
2026-01-16vim-patch:9.1.0117: Stop split-moving from firing WinNew and WinNewPre ↵zeertzjq1
autocommands Problem: win_splitmove fires WinNewPre and possibly WinNew when moving windows, even though no new windows are created. Solution: don't fire WinNew and WinNewPre when inserting an existing window, even if it isn't the current window. Improve the accuracy of related documentation. (Sean Dewar) related: vim/vim#14038 https://github.com/vim/vim/commit/96cc4aef3d47d0fd70e68908af3d48a0dce8ea70 Most of the patch was already ported. This includes the remaining part. Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
2026-01-16vim-patch:9.1.0059: No event triggered before creating a windowzeertzjq1
Problem: No event is triggered before creating a window. (Sergey Vlasov) Solution: Add the WinNewPre event (Sergey Vlasov) fixes: vim/vim#10635 closes: vim/vim#12761 https://github.com/vim/vim/commit/1f47db75fdc8c53c5c778b26ecfa0942ac801f22 Not sure if this should be triggered before creating a floating window, as its use case is related to window layout. Co-authored-by: Sergey Vlasov <sergey@vlasov.me>
2026-01-14vim-patch:9.1.2085: Use-after-free in winframe_remove()zeertzjq1
Problem: Use-after-free in winframe_remove() (henices) Solution: Set window_layout_locked() inside winframe_remove() and check that writing diff files is disallowed when the window layout is locked. It can happen with a custom diff expression when removing a window: 1. Buffer was removed, so win_frame_remove() is called to remove the window. 2. win_frame_remove() → frame_new_height() → scroll_to_fraction() → diff_check_fill() (checks for filler lines) 3. diff_check_fill() ends up causing a diff_try_update, and because we are not using internal diff, it has to first write the file to a buffer using buf_write() 4. buf_write() is called for a buffer that is not contained within a window, so it first calls aucmd_prepbuf() to create a new temporary window before writing the buffer and then later calls aucmd_restbuf(), which restores the previous window layout, calling winframe_remove() again, which will free the window/frame structure, eventually freeing stuff that will still be accessed at step 2. closes: vim/vim#19064 https://github.com/vim/vim/commit/ead1dda74a485ef0470e7252d07c1a36b8cde517 Nvim doesn't have this bug as Nvim uses a floating window as autocommand window, and removing it doesn't need winframe_remove(). Co-authored-by: Christian Brabandt <cb@256bit.org>
2026-01-14vim-patch:9.1.1323: b:undo_ftplugin not executed when re-using bufferzeertzjq1
Problem: b:undo_ftplugin not executed when re-using buffer (archy3) Solution: explicitly execute b:undo_ftplugin in buflist_new() when re-using the current buffer fixes: vim/vim#17113 closes: vim/vim#17133 https://github.com/vim/vim/commit/baa8c90cc0d214e036a3a7980d5cf95cae88a68d Cherry-pick test_filetype.vim changes from patch 9.1.1325. Co-authored-by: Christian Brabandt <cb@256bit.org>
2026-01-14vim-patch:partial:9.0.0907: restoring window after WinScrolled may failzeertzjq1
Problem: Restoring window after WinScrolled may fail. Solution: Lock the window layout when triggering WinScrolled. https://github.com/vim/vim/commit/d63a85592cef0ee4f0fec5efe2f8d66b31f01f05 Only check close_disallowed in window_layout_locked() for now. Also don't check window_layout_locked() when closing a floating window, as it's not checked when creating a floating window. Co-authored-by: Bram Moolenaar <Bram@vim.org>
2026-01-05vim-patch:8.1.0753: printf format not checked for semsg() (#37248)zeertzjq1
Problem: printf format not checked for semsg(). Solution: Add GNUC attribute and fix reported problems. (Dominique Pelle, closes vim/vim#3805) https://github.com/vim/vim/commit/b5443cc46dd1485d6c785dd8c65a2c07bd5a17f3 Cherry-pick a change from patch 8.2.3830. Co-authored-by: Bram Moolenaar <Bram@vim.org>
2026-01-05fix(window): crash closing split if autocmds close other splits (#37233)zeertzjq1
Problem: Crash when closing a split window if autocmds close other split windows but there are still floating windows. Solution: Bail out and give the window back its buffer.
2026-01-04fix(window): crash closing only non-float if autocmds :tabonly (#37218)Sean Dewar1
Problem: null pointer member access when closing the only non-float in the current tab page if autocommands after closing all floats also close all other tab pages. (making it the last window) Solution: check last_window again after closing the floats. Also reduce the scope of "wp"; it would be bugprone to use it before it's later reassigned to the rv of win_free_mem if freed by Buf/WinLeave.
2026-01-01vim-patch:8.2.2198: ml_get error when resizing window and using text propertyJan Edmund Lazo1
Problem: ml_get error when resizing window and using text property. Solution: Validate botline of the right window. (closes vim/vim#7528) https://github.com/vim/vim/commit/23999d799cfe844b604f193183f8f84052c8e746 Migrate to Vim's (in)validate_botline_win() API. Nvim wants to pass "curwin" instead of hiding them behind alias/macro/inline-function. https://github.com/neovim/neovim/pull/37164#discussion_r2655006908 Co-authored-by: Bram Moolenaar <Bram@vim.org>
2025-12-21fix(window): win_move_after UAF from naughty autocmds (#37065)Sean Dewar1
Problem: use-after-free in win_move_after if win_enter autocommands free win1/2. Solution: set w_pos_changed before calling win_enter.
2025-12-21vim-patch:9.1.2001: cursor may end up in wrong window after :botright copen ↵zeertzjq1
(#37056) Problem: After :botright copen and closing the quikfix window, the cursor ends up in the wrong window. The problem is fr_child always points to the first (leftmost for FR_ROW, topmost for FR_COL) child frame. When do :vsplit, the new window is created on the left, and frame_insert() updates the parent's fr_child to point to this new left window. Solution: Create a snapshot before open the quickfix window and restore it when close it (glepnir). closes: vim/vim#18961 https://github.com/vim/vim/commit/b43f9ded7e98261e3e662a8e919f54e7399b0316 Co-authored-by: glepnir <glephunter@gmail.com>
2025-12-10fix(eval): 0 should mean current tabpage in gettabvar() (#36891)zeertzjq1
This matches the gettabvar() behavior change in Vim 8.1.1218.
2025-11-26feat(float): 'statusline' in floating windows #36521glepnir1
Problem: Can't show 'statusline' in floating windows. Solution: Use window-local 'statusline' to control floating window statusline visibility.
2025-11-25fix(events): crash on WinScrolled #35995Kent Sibilev1
Problem: apply_autocmds function can free both buf_T and win_T pointers Solution: instead retain winids for WinResized and WinScrolled autocmds and use curbuf pointer, which is consistent with other uses of apply_autocmds function
2025-11-15vim-patch:9.1.1916: WinEnter autocommand confuses Vim when closing tabpage ↵zeertzjq1
(#36567) Problem: WinEnter autocommand may confuse Vim when closing tabpage (hokorobi) Solution: Verify that curwin did not change in close_others() fixes: vim/vim#18722 closes: vim/vim#18733 https://github.com/vim/vim/commit/61b73b89a3114b4bf62ffbedc8d0d3aa321bdcd5 Co-authored-by: Christian Brabandt <cb@256bit.org>
2025-10-11fix(window): don't make hidden/unfocusable previous window current #36142luukvbaal1
Problem: Previous window is made current while it is unfocusable/hidden. Solution: Treat hidden/unfocusable window as an invalid previous window.
2025-10-11fix: stale lines("w$") after nvim_win_set_height when splitkeep=screen #36056phanium1
Problem: when splitkeep=screen, after enlarge float window with nvim_win_set_height, lines("w$") return stale value Solution: update in win_set_inner_size
2025-10-08vim-patch:9.1.1836: 'culopt' "screenline" not redrawn with line("w0") and :retabzeertzjq1
Problem: 'cursorlineopt' "screenline" isn't redrawn when moving cursor and then using line("w0") and :retab that does nothing. Solution: Call redraw_for_cursorcolumn() when setting a valid w_virtcol (zeertzjq). closes: vim/vim#18506 https://github.com/vim/vim/commit/a0849143614e687a305b6195dd8724840786e372
2025-10-05vim-patch:9.1.1831: stray vseps in right-most 'winfixwidth' windowSean Dewar1
Problem: vertical separator of 'winfixwidth' windows may remain if they become right-most windows from closing windows to the right. Solution: Don't implicitly rely on frame_new_width to fix vseps, as the call may be skipped for 'winfixwidth' windows to preserve their width; do it explicitly in winframe_remove (Sean Dewar). Note that I prefer win_new_width here over setting w_width directly, which would've previously been done by win_split_ins after frame_add_vsep, as this wasn't true for winframe_remove. Though the equivalent issue of bottom 'winfixheight' windows leaving stray statuslines with &ls=0 doesn't seem to exist, test it anyway. closes: vim/vim#18481 https://github.com/vim/vim/commit/620c6556778a0df15be4fa33647fff1f6ab36255 Nvim: calling win_new_width over setting w_width directly is especially important in making sure stuff like w_view_width is correct here. Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
2025-09-19vim-patch:9.1.1773: Crash in BufLeave after BufUnload closes other windows ↵zeertzjq1
(#35830) Problem: Crash in BufLeave/WinLeave/TabLeave when closing window after BufUnload closes all other windows in the tab page. Solution: Avoid duplicate BufLeave/WinLeave events. Trigger TabLeave before removing the buffer (zeertzjq). related: vim/vim#14166 related: neovim/neovim#33603 closes: vim/vim#18330 https://github.com/vim/vim/commit/0c70820015c7a37425c07bf30ad277ee2656d496
2025-09-13feat(ui): support grid=0 in nvim_input_mouse #32535fredizzimo1
Problem: Multigrid UIs have to find out which window to send the input by using the Nvim focus rules, which are not fully documented. Furthermore,`getmousepos()` has several problems when multigrid is enabled, with the main one being that screenrow and screencol are window relative instead of screen relative, due to the fact that the UI don't send any absolute coordinates. Solution: Allow passing 0 as grid to `nvim_input_mouse`, with absolute coordinates, which lets nvim determine the actual window to send the mouse input to. This works as long as nvim is in charge of the window positioning. If the UI repositions or resizes the windows, it can still pass the grid it determines like before.