aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/news.txt3
-rw-r--r--src/nvim/api/win_config.c53
-rw-r--r--src/nvim/window.c9
-rw-r--r--src/nvim/winfloat.c19
-rw-r--r--test/functional/api/window_spec.lua34
-rw-r--r--test/functional/ui/float_spec.lua5
6 files changed, 95 insertions, 28 deletions
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index 7d189d7df0..5e2a48701e 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -478,7 +478,8 @@ The following changes to existing APIs or features add new behavior.
|:vertical|, |:horizontal| and |:botright|.
• |nvim_open_win()| and |nvim_win_set_config()| now support opening normal (split)
- windows, and moving floating windows into split windows.
+ windows, moving floating windows into split windows, and opening windows in
+ non-current tabpages.
• 'errorfile' (|-q|) accepts `-` as an alias for stdin.
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c
index 3bc9cd816f..3a9986a7d1 100644
--- a/src/nvim/api/win_config.c
+++ b/src/nvim/api/win_config.c
@@ -236,19 +236,19 @@ Window nvim_open_win(Buffer buffer, Boolean enter, Dict(win_config) *config, Err
win_T *wp = NULL;
tabpage_T *tp = curtab;
+ win_T *parent = NULL;
+ if (config->win != -1) {
+ parent = find_window_by_handle(fconfig.window, err);
+ if (!parent) {
+ // find_window_by_handle has already set the error
+ goto cleanup;
+ } else if (is_split && parent->w_floating) {
+ api_set_error(err, kErrorTypeException, "Cannot split a floating window");
+ goto cleanup;
+ }
+ tp = win_find_tabpage(parent);
+ }
if (is_split) {
- win_T *parent = NULL;
- if (config->win != -1) {
- parent = find_window_by_handle(fconfig.window, err);
- if (!parent) {
- // find_window_by_handle has already set the error
- goto cleanup;
- } else if (parent->w_floating) {
- api_set_error(err, kErrorTypeException, "Cannot split a floating window");
- goto cleanup;
- }
- }
-
if (!check_split_disallowed_err(parent ? parent : curwin, err)) {
goto cleanup; // error already set
}
@@ -267,7 +267,6 @@ Window nvim_open_win(Buffer buffer, Boolean enter, Dict(win_config) *config, Err
if (parent == NULL || parent == curwin) {
wp = win_split_ins(size, flags, NULL, 0, NULL);
} else {
- tp = win_find_tabpage(parent);
switchwin_T switchwin;
// `parent` is valid in `tp`, so switch_win should not fail.
const int result = switch_win(&switchwin, parent, tp, true);
@@ -395,6 +394,7 @@ void nvim_win_set_config(Window window, Dict(win_config) *config, Error *err)
if (!win) {
return;
}
+
tabpage_T *win_tp = win_find_tabpage(win);
bool was_split = !win->w_floating;
bool has_split = HAS_KEY_X(config, split);
@@ -409,23 +409,28 @@ void nvim_win_set_config(Window window, Dict(win_config) *config, Error *err)
if (!parse_win_config(win, config, &fconfig, !was_split || to_split, err)) {
return;
}
+ win_T *parent = NULL;
+ if (config->win != -1) {
+ parent = find_window_by_handle(fconfig.window, err);
+ if (!parent) {
+ return;
+ } else if (to_split && parent->w_floating) {
+ api_set_error(err, kErrorTypeException, "Cannot split a floating window");
+ return;
+ }
+
+ // Prevent autocmd window from being moved into another tabpage
+ if (is_aucmd_win(win) && win_find_tabpage(win) != win_find_tabpage(parent)) {
+ api_set_error(err, kErrorTypeException, "Cannot move autocmd win to another tabpage");
+ return;
+ }
+ }
if (was_split && !to_split) {
if (!win_new_float(win, false, fconfig, err)) {
return;
}
redraw_later(win, UPD_NOT_VALID);
} else if (to_split) {
- win_T *parent = NULL;
- if (config->win != -1) {
- parent = find_window_by_handle(fconfig.window, err);
- if (!parent) {
- return;
- } else if (parent->w_floating) {
- api_set_error(err, kErrorTypeException, "Cannot split a floating window");
- return;
- }
- }
-
WinSplit old_split = win_split_dir(win);
if (has_vertical && !has_split) {
if (config->vertical) {
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 4c3fb5770c..8232767e20 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -5127,7 +5127,14 @@ win_T *win_alloc(win_T *after, bool hidden)
block_autocmds();
// link the window in the window list
if (!hidden) {
- win_append(after, new_wp, NULL);
+ tabpage_T *tp = NULL;
+ if (after) {
+ tp = win_find_tabpage(after);
+ if (tp == curtab) {
+ tp = NULL;
+ }
+ }
+ win_append(after, new_wp, tp);
}
new_wp->w_wincol = 0;
diff --git a/src/nvim/winfloat.c b/src/nvim/winfloat.c
index f271f7d055..a0f426e30d 100644
--- a/src/nvim/winfloat.c
+++ b/src/nvim/winfloat.c
@@ -41,7 +41,24 @@
win_T *win_new_float(win_T *wp, bool last, WinConfig fconfig, Error *err)
{
if (wp == NULL) {
- wp = win_alloc(last ? lastwin : lastwin_nofloating(), false);
+ tabpage_T *tp = NULL;
+ win_T *tp_last = last ? lastwin : lastwin_nofloating();
+ if (fconfig.window != 0) {
+ assert(!last);
+ win_T *parent_wp = find_window_by_handle(fconfig.window, err);
+ if (!parent_wp) {
+ return NULL;
+ }
+ tp = win_find_tabpage(parent_wp);
+ if (!tp) {
+ return NULL;
+ }
+ tp_last = tp->tp_lastwin;
+ while (tp_last->w_floating && tp_last->w_prev) {
+ tp_last = tp_last->w_prev;
+ }
+ }
+ wp = win_alloc(tp_last, false);
win_init(wp, curwin, 0);
} else {
assert(!last);
diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua
index 636338cb2e..15b9b0945c 100644
--- a/test/functional/api/window_spec.lua
+++ b/test/functional/api/window_spec.lua
@@ -1454,6 +1454,40 @@ describe('API/win', function()
}, layout)
end)
+ it('opens floating windows in other tabpages', function()
+ local first_win = api.nvim_get_current_win()
+ local first_tab = api.nvim_get_current_tabpage()
+
+ command('tabnew')
+ local new_tab = api.nvim_get_current_tabpage()
+ local win = api.nvim_open_win(0, false, {
+ relative = 'win',
+ win = first_win,
+ width = 5,
+ height = 5,
+ row = 1,
+ col = 1,
+ })
+ eq(api.nvim_win_get_tabpage(win), first_tab)
+ eq(api.nvim_get_current_tabpage(), new_tab)
+ end)
+
+ it('switches to new windows in non-current tabpages when enter=true', function()
+ local first_win = api.nvim_get_current_win()
+ local first_tab = api.nvim_get_current_tabpage()
+ command('tabnew')
+ local win = api.nvim_open_win(0, true, {
+ relative = 'win',
+ win = first_win,
+ width = 5,
+ height = 5,
+ row = 1,
+ col = 1,
+ })
+ eq(api.nvim_win_get_tabpage(win), first_tab)
+ eq(api.nvim_get_current_tabpage(), first_tab)
+ end)
+
local function setup_tabbed_autocmd_test()
local info = {}
info.orig_buf = api.nvim_get_current_buf()
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
index b7fb9dbd32..131cc15bfb 100644
--- a/test/functional/ui/float_spec.lua
+++ b/test/functional/ui/float_spec.lua
@@ -532,7 +532,10 @@ describe('float window', function()
local closed_win = api.nvim_get_current_win()
command('close')
local buf = api.nvim_create_buf(false,false)
- api.nvim_open_win(buf, true, {relative='win', win=closed_win, width=1, height=1, bufpos={0,0}})
+ eq(
+ 'Invalid window id: ' .. closed_win,
+ pcall_err(api.nvim_open_win, buf, true, {relative='win', win=closed_win, width=1, height=1, bufpos={0,0}})
+ )
assert_alive()
end)