aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-07-23 07:16:41 +0800
committerGitHub <noreply@github.com>2023-07-23 07:16:41 +0800
commita8cfdf43bc6226e32679ec59769ea3e48ca26193 (patch)
tree6454018d5d3067dea1d6436037300d2870105ac0
parentad95b369856969ccb05b3f92b24d7262b4de3d71 (diff)
downloadrneovim-a8cfdf43bc6226e32679ec59769ea3e48ca26193.tar.gz
rneovim-a8cfdf43bc6226e32679ec59769ea3e48ca26193.tar.bz2
rneovim-a8cfdf43bc6226e32679ec59769ea3e48ca26193.zip
fix(events): trigger VimResume on next UI request (#24426)
-rw-r--r--src/nvim/api/ui.c6
-rw-r--r--src/nvim/api/vim.c3
-rw-r--r--src/nvim/autocmd.c25
-rw-r--r--src/nvim/ex_docmd.c5
-rw-r--r--test/functional/api/ui_spec.lua59
-rw-r--r--test/functional/ui/screen_basic_spec.lua29
6 files changed, 94 insertions, 33 deletions
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index 861ce100cd..9fa5a89407 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -215,6 +215,8 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona
pmap_put(uint64_t)(&connected_uis, channel_id, ui);
ui_attach_impl(ui, channel_id);
+
+ may_trigger_vim_suspend_resume(false);
}
/// @deprecated
@@ -237,6 +239,10 @@ void nvim_ui_set_focus(uint64_t channel_id, Boolean gained, Error *error)
return;
}
+ if (gained) {
+ may_trigger_vim_suspend_resume(false);
+ }
+
do_autocmd_focusgained((bool)gained);
}
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index b1e472aa8c..8738b3e38e 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -305,6 +305,7 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_ks)
Integer nvim_input(String keys)
FUNC_API_SINCE(1) FUNC_API_FAST
{
+ may_trigger_vim_suspend_resume(false);
return (Integer)input_enqueue(keys);
}
@@ -334,6 +335,8 @@ void nvim_input_mouse(String button, String action, String modifier, Integer gri
Integer col, Error *err)
FUNC_API_SINCE(6) FUNC_API_FAST
{
+ may_trigger_vim_suspend_resume(false);
+
if (button.data == NULL || action.data == NULL) {
goto error;
}
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 4aa2ec56a4..a8c5d00383 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -46,6 +46,7 @@
#include "nvim/search.h"
#include "nvim/state.h"
#include "nvim/strings.h"
+#include "nvim/types.h"
#include "nvim/ui.h"
#include "nvim/ui_compositor.h"
#include "nvim/vim.h"
@@ -2521,6 +2522,30 @@ static bool arg_autocmd_flag_get(bool *flag, char **cmd_ptr, char *pattern, int
return false;
}
+/// When kFalse: VimSuspend should be triggered next.
+/// When kTrue: VimResume should be triggerd next.
+/// When kNone: Currently triggering VimSuspend or VimResume.
+static TriState pending_vimresume = kFalse;
+
+static void vimresume_event(void **argv)
+{
+ apply_autocmds(EVENT_VIMRESUME, NULL, NULL, false, NULL);
+ pending_vimresume = kFalse;
+}
+
+/// Trigger VimSuspend or VimResume autocommand.
+void may_trigger_vim_suspend_resume(bool suspend)
+{
+ if (suspend && pending_vimresume == kFalse) {
+ pending_vimresume = kNone;
+ apply_autocmds(EVENT_VIMSUSPEND, NULL, NULL, false, NULL);
+ pending_vimresume = kTrue;
+ } else if (!suspend && pending_vimresume == kTrue) {
+ pending_vimresume = kNone;
+ multiqueue_put(main_loop.events, vimresume_event, 0);
+ }
+}
+
// UI Enter
void do_autocmd_uienter(uint64_t chanid, bool attached)
{
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 7aea2cda53..f154b5b77f 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -4874,12 +4874,9 @@ static void ex_stop(exarg_T *eap)
if (!eap->forceit) {
autowrite_all();
}
- apply_autocmds(EVENT_VIMSUSPEND, NULL, NULL, false, NULL);
-
+ may_trigger_vim_suspend_resume(true);
ui_call_suspend();
ui_flush();
-
- apply_autocmds(EVENT_VIMRESUME, NULL, NULL, false, NULL);
}
/// ":exit", ":xit" and ":wq": Write file and quit the current window.
diff --git a/test/functional/api/ui_spec.lua b/test/functional/api/ui_spec.lua
index b616f51d10..60d115c6f1 100644
--- a/test/functional/api/ui_spec.lua
+++ b/test/functional/api/ui_spec.lua
@@ -1,8 +1,11 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
+local command = helpers.command
local eq = helpers.eq
local eval = helpers.eval
+local exec = helpers.exec
+local feed = helpers.feed
local meths = helpers.meths
local request = helpers.request
local pcall_err = helpers.pcall_err
@@ -76,3 +79,59 @@ it('autocmds UIEnter/UILeave', function()
'UILeave',
}, eval('g:evs'))
end)
+
+it('autocmds VimSuspend/VimResume #22041', function()
+ clear()
+ local screen = Screen.new()
+ screen:attach()
+ exec([[
+ let g:ev = []
+ autocmd VimResume * :call add(g:ev, 'r')
+ autocmd VimSuspend * :call add(g:ev, 's')
+ ]])
+
+ eq(false, screen.suspended)
+ feed('<C-Z>')
+ screen:expect(function() eq (true, screen.suspended) end)
+ eq({ 's' }, eval('g:ev'))
+ screen.suspended = false
+ feed('<Ignore>')
+ eq({ 's', 'r' }, eval('g:ev'))
+
+ command('suspend')
+ screen:expect(function() eq (true, screen.suspended) end)
+ eq({ 's', 'r', 's' }, eval('g:ev'))
+ screen.suspended = false
+ meths.input_mouse('move', '', '', 0, 0, 0)
+ eq({ 's', 'r', 's', 'r' }, eval('g:ev'))
+
+ feed('<C-Z>')
+ screen:expect(function() eq (true, screen.suspended) end)
+ meths.ui_set_focus(false)
+ eq({ 's', 'r', 's', 'r', 's' }, eval('g:ev'))
+ screen.suspended = false
+ meths.ui_set_focus(true)
+ eq({ 's', 'r', 's', 'r', 's', 'r' }, eval('g:ev'))
+
+ command('suspend')
+ screen:expect(function() eq (true, screen.suspended) end)
+ screen:detach()
+ eq({ 's', 'r', 's', 'r', 's', 'r', 's' }, eval('g:ev'))
+ screen.suspended = false
+ screen:attach()
+ eq({ 's', 'r', 's', 'r', 's', 'r', 's', 'r' }, eval('g:ev'))
+
+ eq(false, screen.suspended)
+ feed('<C-Z><C-Z><C-Z><C-Z>')
+ screen:expect(function() eq (true, screen.suspended) end)
+ eq({ 's', 'r', 's', 'r', 's', 'r', 's', 'r', 's' }, eval('g:ev'))
+ screen.suspended = false
+ feed('<C-Z><C-Z><C-Z><C-Z>')
+ eq({ 's', 'r', 's', 'r', 's', 'r', 's', 'r', 's', 'r', 's' }, eval('g:ev'))
+ screen:expect(function() eq (true, screen.suspended) end)
+ screen.suspended = false
+ feed('i<C-R>=g:ev<CR>')
+ eq({ 's', 'r', 's', 'r', 's', 'r', 's', 'r', 's', 'r', 's', 'r' }, eval('g:ev'))
+ eq({ 's', 'r', 's', 'r', 's', 'r', 's', 'r', 's', 'r', 's', 'r', '' },
+ meths.buf_get_lines(0, 0, -1, true))
+end)
diff --git a/test/functional/ui/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua
index 5d5be2e807..bc9517aa60 100644
--- a/test/functional/ui/screen_basic_spec.lua
+++ b/test/functional/ui/screen_basic_spec.lua
@@ -4,7 +4,6 @@ local spawn, set_session, clear = helpers.spawn, helpers.set_session, helpers.cl
local feed, command = helpers.feed, helpers.command
local insert = helpers.insert
local eq = helpers.eq
-local eval = helpers.eval
local funcs, meths = helpers.funcs, helpers.meths
describe('screen', function()
@@ -64,34 +63,6 @@ local function screen_tests(linegrid)
} )
end)
- describe(':suspend', function()
- it('is forwarded to the UI', function()
- local function check()
- eq(true, screen.suspended)
- end
-
- command('let g:ev = []')
- command('autocmd VimResume * :call add(g:ev, "r")')
- command('autocmd VimSuspend * :call add(g:ev, "s")')
-
- eq(false, screen.suspended)
- command('suspend')
- eq({ 's', 'r' }, eval('g:ev'))
-
- screen:expect(check)
- screen.suspended = false
-
- feed('<c-z>')
- eq({ 's', 'r', 's', 'r' }, eval('g:ev'))
-
- screen:expect(check)
- screen.suspended = false
-
- command('suspend')
- eq({ 's', 'r', 's', 'r', 's', 'r' }, eval('g:ev'))
- end)
- end)
-
describe('bell/visual bell', function()
it('is forwarded to the UI', function()
feed('<left>')