Skip to content

Commit 0a3a85f

Browse files
feat(ui): add backdrop (#1759)
Adds a backdrop for the Mason window. Can be disabled by setting the `ui.backdrop` option: ```lua require("mason").setup { ui = { backdrop = 100 } } ``` The backdrop is not displayed if `'termguicolors'` is not enabled or if Neovim is transparent. Co-authored-by: William Boman <[email protected]>
1 parent 1114b23 commit 0a3a85f

File tree

5 files changed

+64
-18
lines changed

5 files changed

+64
-18
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,10 @@ local DEFAULT_SETTINGS = {
269269
-- The border to use for the UI window. Accepts same border values as |nvim_open_win()|.
270270
border = "none",
271271

272+
---@since 1.11.0
273+
-- The backdrop opacity. 0 is fully opaque, 100 is fully transparent.
274+
backdrop = 60,
275+
272276
---@since 1.0.0
273277
-- Width of the window. Accepts:
274278
-- - Integer greater than 1 for fixed width.

doc/mason.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,10 @@ Example:
331331
-- The border to use for the UI window. Accepts same border values as |nvim_open_win()|.
332332
border = "none",
333333

334+
---@since 1.11.0
335+
-- The backdrop opacity. 0 is fully opaque, 100 is fully transparent.
336+
backdrop = 60,
337+
334338
---@since 1.0.0
335339
-- Width of the window. Accepts:
336340
-- - Integer greater than 1 for fixed width.

lua/mason-core/ui/display.lua

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,24 @@ local function create_popup_window_opts(opts, sizes_only)
207207
return popup_layout
208208
end
209209

210+
local function create_backdrop_window_opts()
211+
return {
212+
relative = "editor",
213+
width = vim.o.columns,
214+
height = vim.o.lines,
215+
row = 0,
216+
col = 0,
217+
style = "minimal",
218+
focusable = false,
219+
zindex = 44,
220+
}
221+
end
222+
210223
---@param name string Human readable identifier.
211224
---@param filetype string
212225
function M.new_view_only_win(name, filetype)
213226
local namespace = vim.api.nvim_create_namespace(("installer_%s"):format(name))
214-
local bufnr, renderer, mutate_state, get_state, unsubscribe, win_id, window_mgmt_augroup, autoclose_augroup, registered_keymaps, registered_keybinds, registered_effect_handlers, sticky_cursor
227+
local bufnr, backdrop_bufnr, renderer, mutate_state, get_state, unsubscribe, win_id, backdrop_win_id, window_mgmt_augroup, autoclose_augroup, registered_keymaps, registered_keybinds, registered_effect_handlers, sticky_cursor
215228
local has_initiated = false
216229
---@type WindowOpts
217230
local window_opts = {}
@@ -228,7 +241,7 @@ function M.new_view_only_win(name, filetype)
228241
virtual_lines = false,
229242
}, namespace)
230243

231-
local function delete_win_buf()
244+
local function close_window()
232245
-- We queue the win_buf to be deleted in a schedule call, otherwise when used with folke/which-key (and
233246
-- set timeoutlen=0) we run into a weird segfault.
234247
-- It should probably be unnecessary once https://github.com/neovim/neovim/issues/15548 is resolved
@@ -237,10 +250,6 @@ function M.new_view_only_win(name, filetype)
237250
log.trace "Deleting window"
238251
vim.api.nvim_win_close(win_id, true)
239252
end
240-
if bufnr and vim.api.nvim_buf_is_valid(bufnr) then
241-
log.trace "Deleting buffer"
242-
vim.api.nvim_buf_delete(bufnr, { force = true })
243-
end
244253
end)
245254
end
246255

@@ -373,6 +382,21 @@ function M.new_view_only_win(name, filetype)
373382
bufnr = vim.api.nvim_create_buf(false, true)
374383
win_id = vim.api.nvim_open_win(bufnr, true, create_popup_window_opts(window_opts, false))
375384

385+
local normal_hl = vim.api.nvim_get_hl and vim.api.nvim_get_hl(0, { name = "Normal" })
386+
local is_nvim_transparent = normal_hl and normal_hl.bg == nil
387+
388+
if settings.current.ui.backdrop ~= 100 and vim.o.termguicolors and not is_nvim_transparent then
389+
backdrop_bufnr = vim.api.nvim_create_buf(false, true)
390+
backdrop_win_id = vim.api.nvim_open_win(backdrop_bufnr, false, create_backdrop_window_opts())
391+
392+
vim.wo[backdrop_win_id].winhighlight = "Normal:MasonBackdrop"
393+
vim.wo[backdrop_win_id].winblend = settings.current.ui.backdrop
394+
vim.bo[backdrop_bufnr].buftype = "nofile"
395+
-- https://github.com/folke/lazy.nvim/issues/1399
396+
vim.bo[backdrop_bufnr].filetype = "mason_backdrop"
397+
vim.bo[backdrop_bufnr].bufhidden = "wipe"
398+
end
399+
376400
vim.api.nvim_create_autocmd("CmdLineEnter", {
377401
buffer = bufnr,
378402
callback = function()
@@ -440,27 +464,36 @@ function M.new_view_only_win(name, filetype)
440464
group = window_mgmt_augroup,
441465
buffer = bufnr,
442466
callback = function()
443-
if vim.api.nvim_win_is_valid(win_id) then
467+
if win_id and vim.api.nvim_win_is_valid(win_id) then
444468
draw(renderer(get_state()))
445469
vim.api.nvim_win_set_config(win_id, create_popup_window_opts(window_opts, true))
446470
end
471+
if backdrop_win_id and vim.api.nvim_win_is_valid(backdrop_win_id) then
472+
vim.api.nvim_win_set_config(backdrop_win_id, create_backdrop_window_opts())
473+
end
474+
end,
475+
})
476+
477+
vim.api.nvim_create_autocmd({ "WinClosed" }, {
478+
once = true,
479+
pattern = tostring(win_id),
480+
callback = function()
481+
if backdrop_win_id and vim.api.nvim_win_is_valid(backdrop_win_id) then
482+
vim.api.nvim_win_close(backdrop_win_id, true)
483+
end
447484
end,
448485
})
449486

450487
vim.api.nvim_create_autocmd({ "BufHidden", "BufUnload" }, {
451488
group = autoclose_augroup,
452489
buffer = bufnr,
453-
callback = function()
454-
-- Schedule is done because otherwise the window won't actually close in some cases (for example if
455-
-- you're loading another buffer into it)
456-
vim.schedule(function()
457-
if vim.api.nvim_win_is_valid(win_id) then
458-
vim.api.nvim_win_close(win_id, true)
459-
end
460-
end)
461-
end,
490+
-- This is for instances where the window remains but the buffer is no longer visible, for example when
491+
-- loading another buffer into it (this is basically imitating 'winfixbuf', which was added in 0.10.0).
492+
callback = close_window,
462493
})
463494

495+
-- This autocmd is responsible for closing the Mason window(s) when the user focuses another window. It
496+
-- essentially behaves as WinLeave except it keeps the Mason window(s) open under certain circumstances.
464497
local win_enter_aucmd
465498
win_enter_aucmd = vim.api.nvim_create_autocmd({ "WinEnter" }, {
466499
group = autoclose_augroup,
@@ -469,7 +502,7 @@ function M.new_view_only_win(name, filetype)
469502
local buftype = vim.api.nvim_buf_get_option(0, "buftype")
470503
-- This allows us to keep the floating window open for things like diagnostic popups, UI inputs á la dressing.nvim, etc.
471504
if buftype ~= "prompt" and buftype ~= "nofile" then
472-
delete_win_buf()
505+
close_window()
473506
vim.api.nvim_del_autocmd(win_enter_aucmd)
474507
end
475508
end,
@@ -527,7 +560,7 @@ function M.new_view_only_win(name, filetype)
527560
assert(has_initiated, "Display has not been initiated, cannot close.")
528561
unsubscribe(true)
529562
log.fmt_trace("Closing window win_id=%s, bufnr=%s", win_id, bufnr)
530-
delete_win_buf()
563+
close_window()
531564
vim.api.nvim_del_augroup_by_id(window_mgmt_augroup)
532565
vim.api.nvim_del_augroup_by_id(autoclose_augroup)
533566
end),

lua/mason/settings.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ local DEFAULT_SETTINGS = {
7777
-- The border to use for the UI window. Accepts same border values as |nvim_open_win()|.
7878
border = "none",
7979

80+
---@since 1.11.0
81+
-- The backdrop opacity. 0 is fully opaque, 100 is fully transparent.
82+
backdrop = 60,
83+
8084
---@since 1.0.0
8185
-- Width of the window. Accepts:
8286
-- - Integer greater than 1 for fixed width.

lua/mason/ui/colors.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
local hl_groups = {
2+
MasonBackdrop = { bg = "#000000", default = true },
23
MasonNormal = { link = "NormalFloat", default = true },
34
MasonHeader = { bold = true, fg = "#222222", bg = "#DCA561", default = true },
45
MasonHeaderSecondary = { bold = true, fg = "#222222", bg = "#56B6C2", default = true },

0 commit comments

Comments
 (0)