forked from aniani/vim
patch 8.1.2053: SafeStateAgain not triggered if callback uses feedkeys()
Problem: SafeStateAgain not triggered if callback uses feedkeys(). Solution: Check for safe state in the input loop. Make log messages easier to find. Add 'S' flag to state().
This commit is contained in:
parent
7a9bd7c1e0
commit
d103ee7843
@ -9060,7 +9060,8 @@ state([{what}]) *state()*
|
|||||||
added. E.g, this checks if the screen has scrolled: >
|
added. E.g, this checks if the screen has scrolled: >
|
||||||
if state('s') != ''
|
if state('s') != ''
|
||||||
<
|
<
|
||||||
These characters indicate the state:
|
These characters indicate the state, generally indicating that
|
||||||
|
something is busy:
|
||||||
m halfway a mapping, :normal command, feedkeys() or
|
m halfway a mapping, :normal command, feedkeys() or
|
||||||
stuffed command
|
stuffed command
|
||||||
o operator pending or waiting for a command argument
|
o operator pending or waiting for a command argument
|
||||||
@ -9068,7 +9069,9 @@ state([{what}]) *state()*
|
|||||||
x executing an autocommand
|
x executing an autocommand
|
||||||
w blocked on waiting, e.g. ch_evalexpr() and
|
w blocked on waiting, e.g. ch_evalexpr() and
|
||||||
ch_read(), ch_readraw() when reading json.
|
ch_read(), ch_readraw() when reading json.
|
||||||
c callback invoked (repeats for recursiveness up to "ccc")
|
S not triggering SafeState or SafeStateAgain
|
||||||
|
c callback invoked, including timer (repeats for
|
||||||
|
recursiveness up to "ccc")
|
||||||
s screen has scrolled for messages
|
s screen has scrolled for messages
|
||||||
|
|
||||||
str2float({expr}) *str2float()*
|
str2float({expr}) *str2float()*
|
||||||
|
@ -933,7 +933,7 @@ ins_typebuf(
|
|||||||
init_typebuf();
|
init_typebuf();
|
||||||
if (++typebuf.tb_change_cnt == 0)
|
if (++typebuf.tb_change_cnt == 0)
|
||||||
typebuf.tb_change_cnt = 1;
|
typebuf.tb_change_cnt = 1;
|
||||||
state_no_longer_safe();
|
state_no_longer_safe("ins_typebuf()");
|
||||||
|
|
||||||
addlen = (int)STRLEN(str);
|
addlen = (int)STRLEN(str);
|
||||||
|
|
||||||
@ -1797,7 +1797,7 @@ vgetc(void)
|
|||||||
// Need to process the character before we know it's safe to do something
|
// Need to process the character before we know it's safe to do something
|
||||||
// else.
|
// else.
|
||||||
if (c != K_IGNORE)
|
if (c != K_IGNORE)
|
||||||
state_no_longer_safe();
|
state_no_longer_safe("key typed");
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@ -2047,6 +2047,7 @@ parse_queued_messages(void)
|
|||||||
int i;
|
int i;
|
||||||
int save_may_garbage_collect = may_garbage_collect;
|
int save_may_garbage_collect = may_garbage_collect;
|
||||||
static int entered = 0;
|
static int entered = 0;
|
||||||
|
int was_safe = get_was_safe_state();
|
||||||
|
|
||||||
// Do not handle messages while redrawing, because it may cause buffers to
|
// Do not handle messages while redrawing, because it may cause buffers to
|
||||||
// change or be wiped while they are being redrawn.
|
// change or be wiped while they are being redrawn.
|
||||||
@ -2102,7 +2103,7 @@ parse_queued_messages(void)
|
|||||||
|
|
||||||
// When not nested we'll go back to waiting for a typed character. If it
|
// When not nested we'll go back to waiting for a typed character. If it
|
||||||
// was safe before then this triggers a SafeStateAgain autocommand event.
|
// was safe before then this triggers a SafeStateAgain autocommand event.
|
||||||
if (entered == 1)
|
if (entered == 1 && was_safe)
|
||||||
may_trigger_safestateagain();
|
may_trigger_safestateagain();
|
||||||
|
|
||||||
may_garbage_collect = save_may_garbage_collect;
|
may_garbage_collect = save_may_garbage_collect;
|
||||||
|
49
src/main.c
49
src/main.c
@ -1048,6 +1048,19 @@ op_pending(void)
|
|||||||
&& current_oap->regname == NUL);
|
&& current_oap->regname == NUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return whether currently it is safe, assuming it was safe before (high level
|
||||||
|
* state didn't change).
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
is_safe_now(void)
|
||||||
|
{
|
||||||
|
return stuff_empty()
|
||||||
|
&& typebuf.tb_len == 0
|
||||||
|
&& scriptin[curscript] == NULL
|
||||||
|
&& !global_busy;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Trigger SafeState if currently in s safe state, that is "safe" is TRUE and
|
* Trigger SafeState if currently in s safe state, that is "safe" is TRUE and
|
||||||
* there is no typeahead.
|
* there is no typeahead.
|
||||||
@ -1055,18 +1068,14 @@ op_pending(void)
|
|||||||
void
|
void
|
||||||
may_trigger_safestate(int safe)
|
may_trigger_safestate(int safe)
|
||||||
{
|
{
|
||||||
int is_safe = safe
|
int is_safe = safe && is_safe_now();
|
||||||
&& stuff_empty()
|
|
||||||
&& typebuf.tb_len == 0
|
|
||||||
&& scriptin[curscript] == NULL
|
|
||||||
&& !global_busy;
|
|
||||||
|
|
||||||
#ifdef FEAT_JOB_CHANNEL
|
#ifdef FEAT_JOB_CHANNEL
|
||||||
if (was_safe != is_safe)
|
if (was_safe != is_safe)
|
||||||
// Only log when the state changes, otherwise it happens at nearly
|
// Only log when the state changes, otherwise it happens at nearly
|
||||||
// every key stroke.
|
// every key stroke.
|
||||||
ch_log(NULL, is_safe ? "Start triggering SafeState"
|
ch_log(NULL, is_safe ? "SafeState: Start triggering"
|
||||||
: "Stop triggering SafeState");
|
: "SafeState: Stop triggering");
|
||||||
#endif
|
#endif
|
||||||
if (is_safe)
|
if (is_safe)
|
||||||
apply_autocmds(EVENT_SAFESTATE, NULL, NULL, FALSE, curbuf);
|
apply_autocmds(EVENT_SAFESTATE, NULL, NULL, FALSE, curbuf);
|
||||||
@ -1079,15 +1088,21 @@ may_trigger_safestate(int safe)
|
|||||||
* may_trigger_safestate().
|
* may_trigger_safestate().
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
state_no_longer_safe(void)
|
state_no_longer_safe(char *reason UNUSED)
|
||||||
{
|
{
|
||||||
#ifdef FEAT_JOB_CHANNEL
|
#ifdef FEAT_JOB_CHANNEL
|
||||||
if (was_safe)
|
if (was_safe)
|
||||||
ch_log(NULL, "safe state reset");
|
ch_log(NULL, "SafeState: reset: %s", reason);
|
||||||
#endif
|
#endif
|
||||||
was_safe = FALSE;
|
was_safe = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
get_was_safe_state(void)
|
||||||
|
{
|
||||||
|
return was_safe;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Invoked when leaving code that invokes callbacks. Then trigger
|
* Invoked when leaving code that invokes callbacks. Then trigger
|
||||||
* SafeStateAgain, if it was safe when starting to wait for a character.
|
* SafeStateAgain, if it was safe when starting to wait for a character.
|
||||||
@ -1095,16 +1110,28 @@ state_no_longer_safe(void)
|
|||||||
void
|
void
|
||||||
may_trigger_safestateagain(void)
|
may_trigger_safestateagain(void)
|
||||||
{
|
{
|
||||||
|
if (!was_safe)
|
||||||
|
{
|
||||||
|
// If the safe state was reset in state_no_longer_safe(), e.g. because
|
||||||
|
// of calling feedkeys(), we check if it's now safe again (all keys
|
||||||
|
// were consumed).
|
||||||
|
was_safe = is_safe_now();
|
||||||
|
#ifdef FEAT_JOB_CHANNEL
|
||||||
|
if (was_safe)
|
||||||
|
ch_log(NULL, "SafeState: undo reset");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
if (was_safe)
|
if (was_safe)
|
||||||
{
|
{
|
||||||
#ifdef FEAT_JOB_CHANNEL
|
#ifdef FEAT_JOB_CHANNEL
|
||||||
ch_log(NULL, "Leaving unsafe area, triggering SafeStateAgain");
|
ch_log(NULL, "SafeState: back to waiting, triggering SafeStateAgain");
|
||||||
#endif
|
#endif
|
||||||
apply_autocmds(EVENT_SAFESTATEAGAIN, NULL, NULL, FALSE, curbuf);
|
apply_autocmds(EVENT_SAFESTATEAGAIN, NULL, NULL, FALSE, curbuf);
|
||||||
}
|
}
|
||||||
#ifdef FEAT_JOB_CHANNEL
|
#ifdef FEAT_JOB_CHANNEL
|
||||||
else
|
else
|
||||||
ch_log(NULL, "Leaving unsafe area, not triggering SafeStateAgain");
|
ch_log(NULL,
|
||||||
|
"SafeState: back to waiting, not triggering SafeStateAgain");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,8 @@ void common_init(mparm_T *paramp);
|
|||||||
int is_not_a_term(void);
|
int is_not_a_term(void);
|
||||||
int op_pending(void);
|
int op_pending(void);
|
||||||
void may_trigger_safestate(int safe);
|
void may_trigger_safestate(int safe);
|
||||||
void state_no_longer_safe(void);
|
void state_no_longer_safe(char *reason);
|
||||||
|
int get_was_safe_state(void);
|
||||||
void may_trigger_safestateagain(void);
|
void may_trigger_safestateagain(void);
|
||||||
void main_loop(int cmdwin, int noexmode);
|
void main_loop(int cmdwin, int noexmode);
|
||||||
void getout_preserve_modified(int exitval);
|
void getout_preserve_modified(int exitval);
|
||||||
|
@ -757,6 +757,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2053,
|
||||||
/**/
|
/**/
|
||||||
2052,
|
2052,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user