From a810700bb8189fe7fb699f388fda6fdb9869fac8 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Tue, 25 Oct 2022 20:33:56 +0200 Subject: [PATCH] feat: automatically move out of the way of existing floating windows. Fixes #117 --- lua/noice/util/nui.lua | 26 ++++++++++++++++++++++++++ lua/noice/view/nui.lua | 22 ++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/lua/noice/util/nui.lua b/lua/noice/util/nui.lua index 66b36fd..3d4bee0 100644 --- a/lua/noice/util/nui.lua +++ b/lua/noice/util/nui.lua @@ -30,6 +30,32 @@ function M.normalize_win_options(opts) end end +---@return {xmin:integer, xmax:integer, ymin:integer, ymax:integer} +function M.bounds(win) + local pos = vim.api.nvim_win_get_position(win) + local height = vim.api.nvim_win_get_height(win) + local width = vim.api.nvim_win_get_width(win) + return { + xmin = pos[2], + xmax = pos[2] + width, + ymin = pos[1], + ymax = pos[1] + height, + } +end + +function M.overlap(win1, win2) + local b1 = M.bounds(win1) + local b2 = M.bounds(win2) + + if b2.xmin > b1.xmax or b1.xmin > b2.xmax then + return false + end + if b2.ymin > b1.ymax or b1.ymin > b2.ymax then + return false + end + return true +end + ---@param opts? NuiPopupOptions ---@return _.NuiPopupOptions function M.normalize_popup_options(opts) diff --git a/lua/noice/view/nui.lua b/lua/noice/view/nui.lua index 09a60bb..e762823 100644 --- a/lua/noice/view/nui.lua +++ b/lua/noice/view/nui.lua @@ -43,6 +43,27 @@ function NuiView:update_options() self._opts = Util.nui.normalize(self._opts) end +-- Check if other floating windows are overlapping and move out of the way +function NuiView:smart_move() + if not (self._opts.type == "popup" and self._opts.relative and self._opts.relative.type == "editor") then + return + end + + local wins = vim.tbl_filter(function(win) + return win ~= self._nui.winid + and not (self._nui.border and self._nui.border.winid == win) + and vim.api.nvim_win_is_valid(win) + and vim.api.nvim_win_get_config(win).relative == "editor" + and Util.nui.overlap(self._nui.winid, win) + end, vim.api.nvim_list_wins()) + + if #wins > 0 then + local layout = self:get_layout() + layout.position.row = 2 + self._nui:update_layout(layout) + end +end + function NuiView:create() if self._loading then return @@ -165,6 +186,7 @@ function NuiView:show() self._nui:show() if not self._visible then self._nui:update_layout(self:get_layout()) + self:smart_move() end self:tag()