mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	Merge #7221 from justinmk/ev-focusgained
tui: schedule event instead of <FocusGained> pseudokey
This commit is contained in:
		| @@ -215,6 +215,7 @@ static void ui_set_option(UI *ui, String name, Object value, Error *error) | ||||
| #undef UI_EXT_OPTION | ||||
| } | ||||
|  | ||||
| /// Pushes data into UI.UIData, to be consumed later by remote_ui_flush(). | ||||
| static void push_call(UI *ui, char *name, Array args) | ||||
| { | ||||
|   Array call = ARRAY_DICT_INIT; | ||||
|   | ||||
| @@ -255,12 +255,11 @@ free_vim_args: | ||||
|   return rv; | ||||
| } | ||||
|  | ||||
| /// Execute lua code. Parameters might be passed, they are available inside | ||||
| /// the chunk as `...`. The chunk can return a value. | ||||
| /// Execute lua code. Parameters (if any) are available as `...` inside the | ||||
| /// chunk. The chunk can return a value. | ||||
| /// | ||||
| /// To evaluate an expression, it must be prefixed with "return ". For | ||||
| /// instance, to call a lua function with arguments sent in and get its | ||||
| /// return value back, use the code "return my_function(...)". | ||||
| /// Only statements are executed. To evaluate an expression, prefix it | ||||
| /// with `return`: return my_function(...) | ||||
| /// | ||||
| /// @param code       lua code to execute | ||||
| /// @param args       Arguments to the code | ||||
| @@ -423,29 +422,18 @@ void nvim_del_var(String name, Error *err) | ||||
|   dict_set_var(&globvardict, name, NIL, true, false, err); | ||||
| } | ||||
|  | ||||
| /// Sets a global variable | ||||
| /// | ||||
| /// @deprecated | ||||
| /// | ||||
| /// @param name     Variable name | ||||
| /// @param value    Variable value | ||||
| /// @param[out] err Error details, if any | ||||
| /// @see nvim_set_var | ||||
| /// @return Old value or nil if there was no previous value. | ||||
| /// | ||||
| ///         @warning It may return nil if there was no previous value | ||||
| ///                  or if previous value was `v:null`. | ||||
| /// @warning May return nil if there was no previous value | ||||
| ///          OR if previous value was `v:null`. | ||||
| Object vim_set_var(String name, Object value, Error *err) | ||||
| { | ||||
|   return dict_set_var(&globvardict, name, value, false, true, err); | ||||
| } | ||||
|  | ||||
| /// Removes a global variable | ||||
| /// | ||||
| /// @deprecated | ||||
| /// | ||||
| /// @param name     Variable name | ||||
| /// @param[out] err Error details, if any | ||||
| /// @return Old value | ||||
| /// @see nvim_del_var | ||||
| Object vim_del_var(String name, Error *err) | ||||
| { | ||||
|   return dict_set_var(&globvardict, name, NIL, true, true, err); | ||||
|   | ||||
							
								
								
									
										41
									
								
								src/nvim/aucmd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/nvim/aucmd.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| // This is an open source non-commercial project. Dear PVS-Studio, please check | ||||
| // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com | ||||
|  | ||||
| #include "nvim/os/os.h" | ||||
| #include "nvim/fileio.h" | ||||
| #include "nvim/vim.h" | ||||
| #include "nvim/main.h" | ||||
| #include "nvim/ui.h" | ||||
|  | ||||
| #ifdef INCLUDE_GENERATED_DECLARATIONS | ||||
| # include "aucmd.c.generated.h" | ||||
| #endif | ||||
|  | ||||
| static void focusgained_event(void **argv) | ||||
| { | ||||
|   bool *gainedp = argv[0]; | ||||
|   do_autocmd_focusgained(*gainedp); | ||||
|   xfree(gainedp); | ||||
| } | ||||
| void aucmd_schedule_focusgained(bool gained) | ||||
| { | ||||
|   bool *gainedp = xmalloc(sizeof(*gainedp)); | ||||
|   *gainedp = gained; | ||||
|   loop_schedule_deferred(&main_loop, | ||||
|                          event_create(focusgained_event, 1, gainedp)); | ||||
| } | ||||
|  | ||||
| static void do_autocmd_focusgained(bool gained) | ||||
|   FUNC_ATTR_NONNULL_ALL | ||||
| { | ||||
|   static bool recursive = false; | ||||
|  | ||||
|   if (recursive) { | ||||
|     return;  // disallow recursion | ||||
|   } | ||||
|   recursive = true; | ||||
|   apply_autocmds((gained ? EVENT_FOCUSGAINED : EVENT_FOCUSLOST), | ||||
|                  NULL, NULL, false, curbuf); | ||||
|   recursive = false; | ||||
| } | ||||
|  | ||||
							
								
								
									
										9
									
								
								src/nvim/aucmd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/nvim/aucmd.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| #ifndef NVIM_AUCMD_H | ||||
| #define NVIM_AUCMD_H | ||||
|  | ||||
| #ifdef INCLUDE_GENERATED_DECLARATIONS | ||||
| # include "aucmd.h.generated.h" | ||||
| #endif | ||||
|  | ||||
| #endif  // NVIM_AUCMD_H | ||||
|  | ||||
| @@ -974,14 +974,6 @@ static int insert_handle_key(InsertState *s) | ||||
|     multiqueue_process_events(main_loop.events); | ||||
|     break; | ||||
|  | ||||
|   case K_FOCUSGAINED:  // Neovim has been given focus | ||||
|     apply_autocmds(EVENT_FOCUSGAINED, NULL, NULL, false, curbuf); | ||||
|     break; | ||||
|  | ||||
|   case K_FOCUSLOST:   // Neovim has lost focus | ||||
|     apply_autocmds(EVENT_FOCUSLOST, NULL, NULL, false, curbuf); | ||||
|     break; | ||||
|  | ||||
|   case K_HOME:        // <Home> | ||||
|   case K_KHOME: | ||||
|   case K_S_HOME: | ||||
| @@ -3167,8 +3159,7 @@ static bool ins_compl_prep(int c) | ||||
|  | ||||
|   /* Ignore end of Select mode mapping and mouse scroll buttons. */ | ||||
|   if (c == K_SELECT || c == K_MOUSEDOWN || c == K_MOUSEUP | ||||
|       || c == K_MOUSELEFT || c == K_MOUSERIGHT || c == K_EVENT | ||||
|       || c == K_FOCUSGAINED || c == K_FOCUSLOST) { | ||||
|       || c == K_MOUSELEFT || c == K_MOUSERIGHT || c == K_EVENT) { | ||||
|     return retval; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -59,7 +59,14 @@ void loop_poll_events(Loop *loop, int ms) | ||||
|   multiqueue_process_events(loop->fast_events); | ||||
| } | ||||
|  | ||||
| // Schedule an event from another thread | ||||
| /// Schedules an event from another thread. | ||||
| /// | ||||
| /// @note Event is queued into `fast_events`, which is processed outside of the | ||||
| ///       primary `events` queue by loop_poll_events(). For `main_loop`, that | ||||
| ///       means `fast_events` is NOT processed in an "editor mode" | ||||
| ///       (VimState.execute), so redraw and other side-effects are likely to be | ||||
| ///       skipped. | ||||
| /// @see loop_schedule_deferred | ||||
| void loop_schedule(Loop *loop, Event event) | ||||
| { | ||||
|   uv_mutex_lock(&loop->mutex); | ||||
| @@ -68,6 +75,24 @@ void loop_schedule(Loop *loop, Event event) | ||||
|   uv_mutex_unlock(&loop->mutex); | ||||
| } | ||||
|  | ||||
| /// Schedules an event from another thread. Unlike loop_schedule(), the event | ||||
| /// is forwarded to `Loop.events`, instead of being processed immediately. | ||||
| /// | ||||
| /// @see loop_schedule | ||||
| void loop_schedule_deferred(Loop *loop, Event event) | ||||
| { | ||||
|   Event *eventp = xmalloc(sizeof(*eventp)); | ||||
|   *eventp = event; | ||||
|   loop_schedule(loop, event_create(loop_deferred_event, 2, loop, eventp)); | ||||
| } | ||||
| static void loop_deferred_event(void **argv) | ||||
| { | ||||
|   Loop *loop = argv[0]; | ||||
|   Event *eventp = argv[1]; | ||||
|   multiqueue_put_event(loop->events, *eventp); | ||||
|   xfree(eventp); | ||||
| } | ||||
|  | ||||
| void loop_on_put(MultiQueue *queue, void *data) | ||||
| { | ||||
|   Loop *loop = data; | ||||
|   | ||||
| @@ -16,10 +16,28 @@ KLIST_INIT(WatcherPtr, WatcherPtr, _noop) | ||||
|  | ||||
| typedef struct loop { | ||||
|   uv_loop_t uv; | ||||
|   MultiQueue *events, *fast_events, *thread_events; | ||||
|   MultiQueue *events; | ||||
|   MultiQueue *thread_events; | ||||
|   // Immediate events: | ||||
|   //    "Events that should be processed after exiting uv_run() (to avoid | ||||
|   //    recursion), but before returning from loop_poll_events()." | ||||
|   //    502aee690c980fcb3cfcb3f211dcfad06103db46 | ||||
|   // Practical consequence: these events are processed by | ||||
|   //    state_enter()..os_inchar() | ||||
|   // whereas "regular" (main_loop.events) events are processed by | ||||
|   //    state_enter()..VimState.execute() | ||||
|   // But state_enter()..os_inchar() can be "too early" if you want the event | ||||
|   // to trigger UI updates and other user-activity-related side-effects. | ||||
|   MultiQueue *fast_events; | ||||
|  | ||||
|   // used by process/job-control subsystem | ||||
|   klist_t(WatcherPtr) *children; | ||||
|   uv_signal_t children_watcher; | ||||
|   uv_timer_t children_kill_timer, poll_timer; | ||||
|   uv_timer_t children_kill_timer; | ||||
|  | ||||
|   // generic timer, used by loop_poll_events() | ||||
|   uv_timer_t poll_timer; | ||||
|  | ||||
|   size_t children_stop_requests; | ||||
|   uv_async_t async; | ||||
|   uv_mutex_t mutex; | ||||
|   | ||||
| @@ -1620,14 +1620,6 @@ static int command_line_handle_key(CommandLineState *s) | ||||
|     } | ||||
|     return command_line_not_changed(s); | ||||
|  | ||||
|   case K_FOCUSGAINED:  // Neovim has been given focus | ||||
|     apply_autocmds(EVENT_FOCUSGAINED, NULL, NULL, false, curbuf); | ||||
|     return command_line_not_changed(s); | ||||
|  | ||||
|   case K_FOCUSLOST:   // Neovim has lost focus | ||||
|     apply_autocmds(EVENT_FOCUSLOST, NULL, NULL, false, curbuf); | ||||
|     return command_line_not_changed(s); | ||||
|  | ||||
|   default: | ||||
|     // Normal character with no special meaning.  Just set mod_mask | ||||
|     // to 0x0 so that typing Shift-Space in the GUI doesn't enter | ||||
|   | ||||
| @@ -140,154 +140,152 @@ static char_u modifier_keys_table[] = | ||||
| }; | ||||
|  | ||||
| static struct key_name_entry { | ||||
|   int key;              /* Special key code or ascii value */ | ||||
|   char_u  *name;        /* Name of key */ | ||||
|   int key;              // Special key code or ascii value | ||||
|   char *name;           // Name of key | ||||
| } key_names_table[] = | ||||
| { | ||||
|   {' ',               (char_u *)"Space"}, | ||||
|   {TAB,               (char_u *)"Tab"}, | ||||
|   {K_TAB,             (char_u *)"Tab"}, | ||||
|   {NL,                (char_u *)"NL"}, | ||||
|   {NL,                (char_u *)"NewLine"},     /* Alternative name */ | ||||
|   {NL,                (char_u *)"LineFeed"},    /* Alternative name */ | ||||
|   {NL,                (char_u *)"LF"},          /* Alternative name */ | ||||
|   {CAR,               (char_u *)"CR"}, | ||||
|   {CAR,               (char_u *)"Return"},      /* Alternative name */ | ||||
|   {CAR,               (char_u *)"Enter"},       /* Alternative name */ | ||||
|   {K_BS,              (char_u *)"BS"}, | ||||
|   {K_BS,              (char_u *)"BackSpace"},   /* Alternative name */ | ||||
|   {ESC,               (char_u *)"Esc"}, | ||||
|   {CSI,               (char_u *)"CSI"}, | ||||
|   {K_CSI,             (char_u *)"xCSI"}, | ||||
|   {'|',               (char_u *)"Bar"}, | ||||
|   {'\\',              (char_u *)"Bslash"}, | ||||
|   {K_DEL,             (char_u *)"Del"}, | ||||
|   {K_DEL,             (char_u *)"Delete"},      /* Alternative name */ | ||||
|   {K_KDEL,            (char_u *)"kDel"}, | ||||
|   {K_UP,              (char_u *)"Up"}, | ||||
|   {K_DOWN,            (char_u *)"Down"}, | ||||
|   {K_LEFT,            (char_u *)"Left"}, | ||||
|   {K_RIGHT,           (char_u *)"Right"}, | ||||
|   {K_XUP,             (char_u *)"xUp"}, | ||||
|   {K_XDOWN,           (char_u *)"xDown"}, | ||||
|   {K_XLEFT,           (char_u *)"xLeft"}, | ||||
|   {K_XRIGHT,          (char_u *)"xRight"}, | ||||
|   { ' ',               "Space" }, | ||||
|   { TAB,               "Tab" }, | ||||
|   { K_TAB,             "Tab" }, | ||||
|   { NL,                "NL" }, | ||||
|   { NL,                "NewLine" },     // Alternative name | ||||
|   { NL,                "LineFeed" },    // Alternative name | ||||
|   { NL,                "LF" },          // Alternative name | ||||
|   { CAR,               "CR" }, | ||||
|   { CAR,               "Return" },      // Alternative name | ||||
|   { CAR,               "Enter" },       // Alternative name | ||||
|   { K_BS,              "BS" }, | ||||
|   { K_BS,              "BackSpace" },   // Alternative name | ||||
|   { ESC,               "Esc" }, | ||||
|   { CSI,               "CSI" }, | ||||
|   { K_CSI,             "xCSI" }, | ||||
|   { '|',               "Bar" }, | ||||
|   { '\\',              "Bslash" }, | ||||
|   { K_DEL,             "Del" }, | ||||
|   { K_DEL,             "Delete" },      // Alternative name | ||||
|   { K_KDEL,            "kDel" }, | ||||
|   { K_UP,              "Up" }, | ||||
|   { K_DOWN,            "Down" }, | ||||
|   { K_LEFT,            "Left" }, | ||||
|   { K_RIGHT,           "Right" }, | ||||
|   { K_XUP,             "xUp" }, | ||||
|   { K_XDOWN,           "xDown" }, | ||||
|   { K_XLEFT,           "xLeft" }, | ||||
|   { K_XRIGHT,          "xRight" }, | ||||
|  | ||||
|   {K_F1,              (char_u *)"F1"}, | ||||
|   {K_F2,              (char_u *)"F2"}, | ||||
|   {K_F3,              (char_u *)"F3"}, | ||||
|   {K_F4,              (char_u *)"F4"}, | ||||
|   {K_F5,              (char_u *)"F5"}, | ||||
|   {K_F6,              (char_u *)"F6"}, | ||||
|   {K_F7,              (char_u *)"F7"}, | ||||
|   {K_F8,              (char_u *)"F8"}, | ||||
|   {K_F9,              (char_u *)"F9"}, | ||||
|   {K_F10,             (char_u *)"F10"}, | ||||
|   { K_F1,              "F1" }, | ||||
|   { K_F2,              "F2" }, | ||||
|   { K_F3,              "F3" }, | ||||
|   { K_F4,              "F4" }, | ||||
|   { K_F5,              "F5" }, | ||||
|   { K_F6,              "F6" }, | ||||
|   { K_F7,              "F7" }, | ||||
|   { K_F8,              "F8" }, | ||||
|   { K_F9,              "F9" }, | ||||
|   { K_F10,             "F10" }, | ||||
|  | ||||
|   {K_F11,             (char_u *)"F11"}, | ||||
|   {K_F12,             (char_u *)"F12"}, | ||||
|   {K_F13,             (char_u *)"F13"}, | ||||
|   {K_F14,             (char_u *)"F14"}, | ||||
|   {K_F15,             (char_u *)"F15"}, | ||||
|   {K_F16,             (char_u *)"F16"}, | ||||
|   {K_F17,             (char_u *)"F17"}, | ||||
|   {K_F18,             (char_u *)"F18"}, | ||||
|   {K_F19,             (char_u *)"F19"}, | ||||
|   {K_F20,             (char_u *)"F20"}, | ||||
|   { K_F11,             "F11" }, | ||||
|   { K_F12,             "F12" }, | ||||
|   { K_F13,             "F13" }, | ||||
|   { K_F14,             "F14" }, | ||||
|   { K_F15,             "F15" }, | ||||
|   { K_F16,             "F16" }, | ||||
|   { K_F17,             "F17" }, | ||||
|   { K_F18,             "F18" }, | ||||
|   { K_F19,             "F19" }, | ||||
|   { K_F20,             "F20" }, | ||||
|  | ||||
|   {K_F21,             (char_u *)"F21"}, | ||||
|   {K_F22,             (char_u *)"F22"}, | ||||
|   {K_F23,             (char_u *)"F23"}, | ||||
|   {K_F24,             (char_u *)"F24"}, | ||||
|   {K_F25,             (char_u *)"F25"}, | ||||
|   {K_F26,             (char_u *)"F26"}, | ||||
|   {K_F27,             (char_u *)"F27"}, | ||||
|   {K_F28,             (char_u *)"F28"}, | ||||
|   {K_F29,             (char_u *)"F29"}, | ||||
|   {K_F30,             (char_u *)"F30"}, | ||||
|   { K_F21,             "F21" }, | ||||
|   { K_F22,             "F22" }, | ||||
|   { K_F23,             "F23" }, | ||||
|   { K_F24,             "F24" }, | ||||
|   { K_F25,             "F25" }, | ||||
|   { K_F26,             "F26" }, | ||||
|   { K_F27,             "F27" }, | ||||
|   { K_F28,             "F28" }, | ||||
|   { K_F29,             "F29" }, | ||||
|   { K_F30,             "F30" }, | ||||
|  | ||||
|   {K_F31,             (char_u *)"F31"}, | ||||
|   {K_F32,             (char_u *)"F32"}, | ||||
|   {K_F33,             (char_u *)"F33"}, | ||||
|   {K_F34,             (char_u *)"F34"}, | ||||
|   {K_F35,             (char_u *)"F35"}, | ||||
|   {K_F36,             (char_u *)"F36"}, | ||||
|   {K_F37,             (char_u *)"F37"}, | ||||
|   { K_F31,             "F31" }, | ||||
|   { K_F32,             "F32" }, | ||||
|   { K_F33,             "F33" }, | ||||
|   { K_F34,             "F34" }, | ||||
|   { K_F35,             "F35" }, | ||||
|   { K_F36,             "F36" }, | ||||
|   { K_F37,             "F37" }, | ||||
|  | ||||
|   {K_XF1,             (char_u *)"xF1"}, | ||||
|   {K_XF2,             (char_u *)"xF2"}, | ||||
|   {K_XF3,             (char_u *)"xF3"}, | ||||
|   {K_XF4,             (char_u *)"xF4"}, | ||||
|   { K_XF1,             "xF1" }, | ||||
|   { K_XF2,             "xF2" }, | ||||
|   { K_XF3,             "xF3" }, | ||||
|   { K_XF4,             "xF4" }, | ||||
|  | ||||
|   {K_HELP,            (char_u *)"Help"}, | ||||
|   {K_UNDO,            (char_u *)"Undo"}, | ||||
|   {K_INS,             (char_u *)"Insert"}, | ||||
|   {K_INS,             (char_u *)"Ins"},         /* Alternative name */ | ||||
|   {K_KINS,            (char_u *)"kInsert"}, | ||||
|   {K_HOME,            (char_u *)"Home"}, | ||||
|   {K_KHOME,           (char_u *)"kHome"}, | ||||
|   {K_XHOME,           (char_u *)"xHome"}, | ||||
|   {K_ZHOME,           (char_u *)"zHome"}, | ||||
|   {K_END,             (char_u *)"End"}, | ||||
|   {K_KEND,            (char_u *)"kEnd"}, | ||||
|   {K_XEND,            (char_u *)"xEnd"}, | ||||
|   {K_ZEND,            (char_u *)"zEnd"}, | ||||
|   {K_PAGEUP,          (char_u *)"PageUp"}, | ||||
|   {K_PAGEDOWN,        (char_u *)"PageDown"}, | ||||
|   {K_KPAGEUP,         (char_u *)"kPageUp"}, | ||||
|   {K_KPAGEDOWN,       (char_u *)"kPageDown"}, | ||||
|   { K_HELP,            "Help" }, | ||||
|   { K_UNDO,            "Undo" }, | ||||
|   { K_INS,             "Insert" }, | ||||
|   { K_INS,             "Ins" },         // Alternative name | ||||
|   { K_KINS,            "kInsert" }, | ||||
|   { K_HOME,            "Home" }, | ||||
|   { K_KHOME,           "kHome" }, | ||||
|   { K_XHOME,           "xHome" }, | ||||
|   { K_ZHOME,           "zHome" }, | ||||
|   { K_END,             "End" }, | ||||
|   { K_KEND,            "kEnd" }, | ||||
|   { K_XEND,            "xEnd" }, | ||||
|   { K_ZEND,            "zEnd" }, | ||||
|   { K_PAGEUP,          "PageUp" }, | ||||
|   { K_PAGEDOWN,        "PageDown" }, | ||||
|   { K_KPAGEUP,         "kPageUp" }, | ||||
|   { K_KPAGEDOWN,       "kPageDown" }, | ||||
|  | ||||
|   {K_KPLUS,           (char_u *)"kPlus"}, | ||||
|   {K_KMINUS,          (char_u *)"kMinus"}, | ||||
|   {K_KDIVIDE,         (char_u *)"kDivide"}, | ||||
|   {K_KMULTIPLY,       (char_u *)"kMultiply"}, | ||||
|   {K_KENTER,          (char_u *)"kEnter"}, | ||||
|   {K_KPOINT,          (char_u *)"kPoint"}, | ||||
|   { K_KPLUS,           "kPlus" }, | ||||
|   { K_KMINUS,          "kMinus" }, | ||||
|   { K_KDIVIDE,         "kDivide" }, | ||||
|   { K_KMULTIPLY,       "kMultiply" }, | ||||
|   { K_KENTER,          "kEnter" }, | ||||
|   { K_KPOINT,          "kPoint" }, | ||||
|  | ||||
|   {K_K0,              (char_u *)"k0"}, | ||||
|   {K_K1,              (char_u *)"k1"}, | ||||
|   {K_K2,              (char_u *)"k2"}, | ||||
|   {K_K3,              (char_u *)"k3"}, | ||||
|   {K_K4,              (char_u *)"k4"}, | ||||
|   {K_K5,              (char_u *)"k5"}, | ||||
|   {K_K6,              (char_u *)"k6"}, | ||||
|   {K_K7,              (char_u *)"k7"}, | ||||
|   {K_K8,              (char_u *)"k8"}, | ||||
|   {K_K9,              (char_u *)"k9"}, | ||||
|   { K_K0,              "k0" }, | ||||
|   { K_K1,              "k1" }, | ||||
|   { K_K2,              "k2" }, | ||||
|   { K_K3,              "k3" }, | ||||
|   { K_K4,              "k4" }, | ||||
|   { K_K5,              "k5" }, | ||||
|   { K_K6,              "k6" }, | ||||
|   { K_K7,              "k7" }, | ||||
|   { K_K8,              "k8" }, | ||||
|   { K_K9,              "k9" }, | ||||
|  | ||||
|   {'<',               (char_u *)"lt"}, | ||||
|   { '<',               "lt" }, | ||||
|  | ||||
|   {K_MOUSE,           (char_u *)"Mouse"}, | ||||
|   {K_LEFTMOUSE,       (char_u *)"LeftMouse"}, | ||||
|   {K_LEFTMOUSE_NM,    (char_u *)"LeftMouseNM"}, | ||||
|   {K_LEFTDRAG,        (char_u *)"LeftDrag"}, | ||||
|   {K_LEFTRELEASE,     (char_u *)"LeftRelease"}, | ||||
|   {K_LEFTRELEASE_NM,  (char_u *)"LeftReleaseNM"}, | ||||
|   {K_MIDDLEMOUSE,     (char_u *)"MiddleMouse"}, | ||||
|   {K_MIDDLEDRAG,      (char_u *)"MiddleDrag"}, | ||||
|   {K_MIDDLERELEASE,   (char_u *)"MiddleRelease"}, | ||||
|   {K_RIGHTMOUSE,      (char_u *)"RightMouse"}, | ||||
|   {K_RIGHTDRAG,       (char_u *)"RightDrag"}, | ||||
|   {K_RIGHTRELEASE,    (char_u *)"RightRelease"}, | ||||
|   {K_MOUSEDOWN,       (char_u *)"ScrollWheelUp"}, | ||||
|   {K_MOUSEUP,         (char_u *)"ScrollWheelDown"}, | ||||
|   {K_MOUSELEFT,       (char_u *)"ScrollWheelRight"}, | ||||
|   {K_MOUSERIGHT,      (char_u *)"ScrollWheelLeft"}, | ||||
|   {K_MOUSEDOWN,       (char_u *)"MouseDown"},   /* OBSOLETE: Use	  */ | ||||
|   {K_MOUSEUP,         (char_u *)"MouseUp"},     /* ScrollWheelXXX instead */ | ||||
|   {K_X1MOUSE,         (char_u *)"X1Mouse"}, | ||||
|   {K_X1DRAG,          (char_u *)"X1Drag"}, | ||||
|   {K_X1RELEASE,               (char_u *)"X1Release"}, | ||||
|   {K_X2MOUSE,         (char_u *)"X2Mouse"}, | ||||
|   {K_X2DRAG,          (char_u *)"X2Drag"}, | ||||
|   {K_X2RELEASE,               (char_u *)"X2Release"}, | ||||
|   {K_DROP,            (char_u *)"Drop"}, | ||||
|   {K_ZERO,            (char_u *)"Nul"}, | ||||
|   {K_SNR,             (char_u *)"SNR"}, | ||||
|   {K_PLUG,            (char_u *)"Plug"}, | ||||
|   {K_PASTE,           (char_u *)"Paste"}, | ||||
|   {K_FOCUSGAINED,     (char_u *)"FocusGained"}, | ||||
|   {K_FOCUSLOST,       (char_u *)"FocusLost"}, | ||||
|   { K_MOUSE,           "Mouse" }, | ||||
|   { K_LEFTMOUSE,       "LeftMouse" }, | ||||
|   { K_LEFTMOUSE_NM,    "LeftMouseNM" }, | ||||
|   { K_LEFTDRAG,        "LeftDrag" }, | ||||
|   { K_LEFTRELEASE,     "LeftRelease" }, | ||||
|   { K_LEFTRELEASE_NM,  "LeftReleaseNM" }, | ||||
|   { K_MIDDLEMOUSE,     "MiddleMouse" }, | ||||
|   { K_MIDDLEDRAG,      "MiddleDrag" }, | ||||
|   { K_MIDDLERELEASE,   "MiddleRelease" }, | ||||
|   { K_RIGHTMOUSE,      "RightMouse" }, | ||||
|   { K_RIGHTDRAG,       "RightDrag" }, | ||||
|   { K_RIGHTRELEASE,    "RightRelease" }, | ||||
|   { K_MOUSEDOWN,       "ScrollWheelUp" }, | ||||
|   { K_MOUSEUP,         "ScrollWheelDown" }, | ||||
|   { K_MOUSELEFT,       "ScrollWheelRight" }, | ||||
|   { K_MOUSERIGHT,      "ScrollWheelLeft" }, | ||||
|   { K_MOUSEDOWN,       "MouseDown" },   // OBSOLETE: Use | ||||
|   { K_MOUSEUP,         "MouseUp" },     // ScrollWheelXXX instead | ||||
|   { K_X1MOUSE,         "X1Mouse" }, | ||||
|   { K_X1DRAG,          "X1Drag" }, | ||||
|   { K_X1RELEASE,       "X1Release" }, | ||||
|   { K_X2MOUSE,         "X2Mouse" }, | ||||
|   { K_X2DRAG,          "X2Drag" }, | ||||
|   { K_X2RELEASE,       "X2Release" }, | ||||
|   { K_DROP,            "Drop" }, | ||||
|   { K_ZERO,            "Nul" }, | ||||
|   { K_SNR,             "SNR" }, | ||||
|   { K_PLUG,            "Plug" }, | ||||
|   { K_PASTE,           "Paste" }, | ||||
|   { 0,                 NULL } | ||||
| }; | ||||
|  | ||||
| @@ -721,7 +719,7 @@ int find_special_key_in_table(int c) | ||||
|  */ | ||||
| int get_special_key_code(const char_u *name) | ||||
| { | ||||
|   char_u  *table_name; | ||||
|   char *table_name; | ||||
|   int i, j; | ||||
|  | ||||
|   for (i = 0; key_names_table[i].name != NULL; i++) { | ||||
|   | ||||
| @@ -428,8 +428,6 @@ enum key_extra { | ||||
| #define K_CMDWIN        TERMCAP2KEY(KS_EXTRA, KE_CMDWIN) | ||||
|  | ||||
| #define K_DROP          TERMCAP2KEY(KS_EXTRA, KE_DROP) | ||||
| #define K_FOCUSGAINED   TERMCAP2KEY(KS_EXTRA, KE_FOCUSGAINED) | ||||
| #define K_FOCUSLOST     TERMCAP2KEY(KS_EXTRA, KE_FOCUSLOST) | ||||
|  | ||||
| #define K_EVENT         TERMCAP2KEY(KS_EXTRA, KE_EVENT) | ||||
| #define K_PASTE         TERMCAP2KEY(KS_EXTRA, KE_PASTE) | ||||
|   | ||||
| @@ -95,8 +95,12 @@ void log_unlock(void) | ||||
|   uv_mutex_unlock(&mutex); | ||||
| } | ||||
|  | ||||
| bool do_log(int log_level, const char *func_name, int line_num, bool eol, | ||||
|             const char* fmt, ...) FUNC_ATTR_UNUSED | ||||
| /// @param context    description of a shared context or subsystem | ||||
| /// @param func_name  function name, or NULL | ||||
| /// @param line_num   source line number, or -1 | ||||
| bool do_log(int log_level, const char *context, const char *func_name, | ||||
|             int line_num, bool eol, const char *fmt, ...) | ||||
|   FUNC_ATTR_UNUSED | ||||
| { | ||||
|   if (log_level < MIN_LOG_LEVEL) { | ||||
|     return false; | ||||
| @@ -112,8 +116,8 @@ bool do_log(int log_level, const char *func_name, int line_num, bool eol, | ||||
|  | ||||
|   va_list args; | ||||
|   va_start(args, fmt); | ||||
|   ret = v_do_log_to_file(log_file, log_level, func_name, line_num, eol, | ||||
|                               fmt, args); | ||||
|   ret = v_do_log_to_file(log_file, log_level, context, func_name, line_num, | ||||
|                          eol, fmt, args); | ||||
|   va_end(args); | ||||
|  | ||||
|   if (log_file != stderr && log_file != stdout) { | ||||
| @@ -151,7 +155,7 @@ FILE *open_log_file(void) | ||||
|   static bool opening_log_file = false; | ||||
|   // check if it's a recursive call | ||||
|   if (opening_log_file) { | ||||
|     do_log_to_file(stderr, ERROR_LOG_LEVEL, __func__, __LINE__, true, | ||||
|     do_log_to_file(stderr, ERROR_LOG_LEVEL, NULL, __func__, __LINE__, true, | ||||
|                    "Cannot LOG() recursively."); | ||||
|     return stderr; | ||||
|   } | ||||
| @@ -171,7 +175,7 @@ FILE *open_log_file(void) | ||||
|   //  - LOG() is called before early_init() | ||||
|   //  - Directory does not exist | ||||
|   //  - File is not writable | ||||
|   do_log_to_file(stderr, ERROR_LOG_LEVEL, __func__, __LINE__, true, | ||||
|   do_log_to_file(stderr, ERROR_LOG_LEVEL, NULL, __func__, __LINE__, true, | ||||
|                  "Logging to stderr, failed to open $" LOG_FILE_ENV ": %s", | ||||
|                  log_file_path); | ||||
|   return stderr; | ||||
| @@ -201,7 +205,7 @@ void log_callstack_to_file(FILE *log_file, const char *const func_name, | ||||
|   // Now we have a command string like: | ||||
|   //    addr2line -e /path/to/exe -f -p 0x123 0x456 ... | ||||
|  | ||||
|   do_log_to_file(log_file, DEBUG_LOG_LEVEL, func_name, line_num, true, | ||||
|   do_log_to_file(log_file, DEBUG_LOG_LEVEL, NULL, func_name, line_num, true, | ||||
|                  "trace:"); | ||||
|   FILE *fp = popen(cmdbuf, "r"); | ||||
|   char linebuf[IOSIZE]; | ||||
| @@ -230,22 +234,23 @@ end: | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static bool do_log_to_file(FILE *log_file, int log_level, | ||||
| static bool do_log_to_file(FILE *log_file, int log_level, const char *context, | ||||
|                            const char *func_name, int line_num, bool eol, | ||||
|                            const char* fmt, ...) | ||||
| { | ||||
|   va_list args; | ||||
|   va_start(args, fmt); | ||||
|   bool ret = v_do_log_to_file(log_file, log_level, func_name, line_num, eol, | ||||
|                               fmt, args); | ||||
|   bool ret = v_do_log_to_file(log_file, log_level, context, func_name, | ||||
|                               line_num, eol, fmt, args); | ||||
|   va_end(args); | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| static bool v_do_log_to_file(FILE *log_file, int log_level, | ||||
|                              const char *func_name, int line_num, bool eol, | ||||
|                              const char* fmt, va_list args) | ||||
|                              const char *context, const char *func_name, | ||||
|                              int line_num, bool eol, const char *fmt, | ||||
|                              va_list args) | ||||
| { | ||||
|   static const char *log_levels[] = { | ||||
|     [DEBUG_LOG_LEVEL]   = "DEBUG", | ||||
| @@ -268,8 +273,15 @@ static bool v_do_log_to_file(FILE *log_file, int log_level, | ||||
|  | ||||
|   // print the log message prefixed by the current timestamp and pid | ||||
|   int64_t pid = os_get_pid(); | ||||
|   if (fprintf(log_file, "%s %s %" PRId64 "/%s:%d: ", date_time, | ||||
|               log_levels[log_level], pid, func_name, line_num) < 0) { | ||||
|   int rv = (line_num == -1 || func_name == NULL) | ||||
|     ? fprintf(log_file, "%s %s %" PRId64 " %s", date_time, | ||||
|               log_levels[log_level], pid, | ||||
|               (context == NULL ? "?:" : context)) | ||||
|     : fprintf(log_file, "%s %s %" PRId64 " %s%s:%d: ", date_time, | ||||
|               log_levels[log_level], pid, | ||||
|               (context == NULL ? "" : context), | ||||
|               func_name, line_num); | ||||
|   if (rv < 0) { | ||||
|     return false; | ||||
|   } | ||||
|   if (vfprintf(log_file, fmt, args) < 0) { | ||||
|   | ||||
| @@ -22,42 +22,42 @@ | ||||
| #  define MIN_LOG_LEVEL INFO_LOG_LEVEL | ||||
| #endif | ||||
|  | ||||
| #define LOG(level, ...) do_log((level), __func__, __LINE__, true, \ | ||||
| #define LOG(level, ...) do_log((level), NULL, __func__, __LINE__, true, \ | ||||
|                                __VA_ARGS__) | ||||
|  | ||||
| #if MIN_LOG_LEVEL <= DEBUG_LOG_LEVEL | ||||
| # undef DLOG | ||||
| # undef DLOGN | ||||
| # define DLOG(...) do_log(DEBUG_LOG_LEVEL, __func__, __LINE__, true, \ | ||||
| # define DLOG(...) do_log(DEBUG_LOG_LEVEL, NULL, __func__, __LINE__, true, \ | ||||
|                           __VA_ARGS__) | ||||
| # define DLOGN(...) do_log(DEBUG_LOG_LEVEL, __func__, __LINE__, false, \ | ||||
| # define DLOGN(...) do_log(DEBUG_LOG_LEVEL, NULL, __func__, __LINE__, false, \ | ||||
|                            __VA_ARGS__) | ||||
| #endif | ||||
|  | ||||
| #if MIN_LOG_LEVEL <= INFO_LOG_LEVEL | ||||
| # undef ILOG | ||||
| # undef ILOGN | ||||
| # define ILOG(...) do_log(INFO_LOG_LEVEL, __func__, __LINE__, true, \ | ||||
| # define ILOG(...) do_log(INFO_LOG_LEVEL, NULL, __func__, __LINE__, true, \ | ||||
|                           __VA_ARGS__) | ||||
| # define ILOGN(...) do_log(INFO_LOG_LEVEL, __func__, __LINE__, false, \ | ||||
| # define ILOGN(...) do_log(INFO_LOG_LEVEL, NULL, __func__, __LINE__, false, \ | ||||
|                            __VA_ARGS__) | ||||
| #endif | ||||
|  | ||||
| #if MIN_LOG_LEVEL <= WARN_LOG_LEVEL | ||||
| # undef WLOG | ||||
| # undef WLOGN | ||||
| # define WLOG(...) do_log(WARN_LOG_LEVEL, __func__, __LINE__, true, \ | ||||
| # define WLOG(...) do_log(WARN_LOG_LEVEL, NULL, __func__, __LINE__, true, \ | ||||
|                           __VA_ARGS__) | ||||
| # define WLOGN(...) do_log(WARN_LOG_LEVEL, __func__, __LINE__, false, \ | ||||
| # define WLOGN(...) do_log(WARN_LOG_LEVEL, NULL, __func__, __LINE__, false, \ | ||||
|                            __VA_ARGS__) | ||||
| #endif | ||||
|  | ||||
| #if MIN_LOG_LEVEL <= ERROR_LOG_LEVEL | ||||
| # undef ELOG | ||||
| # undef ELOGN | ||||
| # define ELOG(...) do_log(ERROR_LOG_LEVEL, __func__, __LINE__, true, \ | ||||
| # define ELOG(...) do_log(ERROR_LOG_LEVEL, NULL, __func__, __LINE__, true, \ | ||||
|                           __VA_ARGS__) | ||||
| # define ELOGN(...) do_log(ERROR_LOG_LEVEL, __func__, __LINE__, false, \ | ||||
| # define ELOGN(...) do_log(ERROR_LOG_LEVEL, NULL, __func__, __LINE__, false, \ | ||||
|                            __VA_ARGS__) | ||||
| #endif | ||||
|  | ||||
|   | ||||
| @@ -188,12 +188,11 @@ uint64_t channel_connect(bool tcp, const char *address, int timeout, | ||||
|   return channel->id; | ||||
| } | ||||
|  | ||||
| /// Sends event/arguments to channel | ||||
| /// Publishes an event to a channel. | ||||
| /// | ||||
| /// @param id The channel id. If 0, the event will be sent to all | ||||
| ///        channels that have subscribed to the event type | ||||
| /// @param name The event name, an arbitrary string | ||||
| /// @param args Array with event arguments | ||||
| /// @param id Channel id. 0 means "broadcast to all subscribed channels" | ||||
| /// @param name Event name (application-defined) | ||||
| /// @param args Array of event arguments | ||||
| /// @return True if the event was sent successfully, false otherwise. | ||||
| bool channel_send_event(uint64_t id, const char *name, Array args) | ||||
| { | ||||
| @@ -215,7 +214,6 @@ bool channel_send_event(uint64_t id, const char *name, Array args) | ||||
|       send_event(channel, name, args); | ||||
|     } | ||||
|   }  else { | ||||
|     // TODO(tarruda): Implement event broadcasting in vimscript | ||||
|     broadcast_event(name, args); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -345,8 +345,6 @@ static const struct nv_cmd { | ||||
|   { K_F8,      farsi_f8,       0,                      0 }, | ||||
|   { K_F9,      farsi_f9,       0,                      0 }, | ||||
|   { K_EVENT,   nv_event,       NV_KEEPREG,             0 }, | ||||
|   { K_FOCUSGAINED, nv_focusgained, NV_KEEPREG,         0 }, | ||||
|   { K_FOCUSLOST,   nv_focuslost,   NV_KEEPREG,         0 }, | ||||
| }; | ||||
|  | ||||
| /* Number of commands in nv_cmds[]. */ | ||||
| @@ -7961,18 +7959,6 @@ static void nv_event(cmdarg_T *cap) | ||||
|   finish_op = false; | ||||
| } | ||||
|  | ||||
| /// Trigger FocusGained event. | ||||
| static void nv_focusgained(cmdarg_T *cap) | ||||
| { | ||||
|   apply_autocmds(EVENT_FOCUSGAINED, NULL, NULL, false, curbuf); | ||||
| } | ||||
|  | ||||
| /// Trigger FocusLost event. | ||||
| static void nv_focuslost(cmdarg_T *cap) | ||||
| { | ||||
|   apply_autocmds(EVENT_FOCUSLOST, NULL, NULL, false, curbuf); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Return TRUE when 'mousemodel' is set to "popup" or "popup_setpos". | ||||
|  */ | ||||
|   | ||||
| @@ -26,10 +26,11 @@ void state_enter(VimState *s) | ||||
|     int check_result = s->check ? s->check(s) : 1; | ||||
|  | ||||
|     if (!check_result) { | ||||
|       break; | ||||
|       break;     // Terminate this state. | ||||
|     } else if (check_result == -1) { | ||||
|       continue; | ||||
|       continue;  // check() again. | ||||
|     } | ||||
|     // Execute this state. | ||||
|  | ||||
|     int key; | ||||
|  | ||||
| @@ -48,11 +49,13 @@ getkey: | ||||
|       ui_flush(); | ||||
|       // Call `os_inchar` directly to block for events or user input without | ||||
|       // consuming anything from `input_buffer`(os/input.c) or calling the | ||||
|       // mapping engine. If an event was put into the queue, we send K_EVENT | ||||
|       // directly. | ||||
|       // mapping engine. | ||||
|       (void)os_inchar(NULL, 0, -1, 0); | ||||
|       input_disable_events(); | ||||
|       key = !multiqueue_empty(main_loop.events) ? K_EVENT : safe_vgetc(); | ||||
|       // If an event was put into the queue, we send K_EVENT directly. | ||||
|       key = !multiqueue_empty(main_loop.events) | ||||
|             ? K_EVENT | ||||
|             : safe_vgetc(); | ||||
|     } | ||||
|  | ||||
|     if (key == K_EVENT) { | ||||
|   | ||||
| @@ -432,14 +432,6 @@ static int terminal_execute(VimState *state, int key) | ||||
|   TerminalState *s = (TerminalState *)state; | ||||
|  | ||||
|   switch (key) { | ||||
|     case K_FOCUSGAINED:  // nvim has been given focus | ||||
|       apply_autocmds(EVENT_FOCUSGAINED, NULL, NULL, false, curbuf); | ||||
|       break; | ||||
|  | ||||
|     case K_FOCUSLOST:   // nvim has lost focus | ||||
|       apply_autocmds(EVENT_FOCUSLOST, NULL, NULL, false, curbuf); | ||||
|       break; | ||||
|  | ||||
|     // Temporary fix until paste events gets implemented | ||||
|     case K_PASTE: | ||||
|       break; | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
| #include "nvim/api/private/helpers.h" | ||||
| #include "nvim/ascii.h" | ||||
| #include "nvim/main.h" | ||||
| #include "nvim/aucmd.h" | ||||
| #include "nvim/os/os.h" | ||||
| #include "nvim/os/input.h" | ||||
| #include "nvim/event/rstream.h" | ||||
| @@ -280,9 +281,9 @@ static void timer_cb(TimeWatcher *watcher, void *data) | ||||
|  | ||||
| /// Handle focus events. | ||||
| /// | ||||
| /// If the upcoming sequence of bytes in the input stream matches either the | ||||
| /// escape code for focus gained `<ESC>[I` or focus lost `<ESC>[O` then consume | ||||
| /// that sequence and push the appropriate event into the input queue | ||||
| /// If the upcoming sequence of bytes in the input stream matches the termcode | ||||
| /// for "focus gained" or "focus lost", consume that sequence and schedule an | ||||
| /// event on the main loop. | ||||
| /// | ||||
| /// @param input the input stream | ||||
| /// @return true iff handle_focus_event consumed some input | ||||
| @@ -294,11 +295,7 @@ static bool handle_focus_event(TermInput *input) | ||||
|     // Advance past the sequence | ||||
|     bool focus_gained = *rbuffer_get(input->read_stream.buffer, 2) == 'I'; | ||||
|     rbuffer_consumed(input->read_stream.buffer, 3); | ||||
|     if (focus_gained) { | ||||
|       enqueue_input(input, FOCUSGAINED_KEY, sizeof(FOCUSGAINED_KEY) - 1); | ||||
|     } else { | ||||
|       enqueue_input(input, FOCUSLOST_KEY, sizeof(FOCUSLOST_KEY) - 1); | ||||
|     } | ||||
|     aucmd_schedule_focusgained(focus_gained); | ||||
|     return true; | ||||
|   } | ||||
|   return false; | ||||
|   | ||||
| @@ -71,10 +71,10 @@ static char uilog_last_event[1024] = { 0 }; | ||||
|       uilog_seen++; \ | ||||
|     } else { \ | ||||
|       if (uilog_seen > 0) { \ | ||||
|         do_log(DEBUG_LOG_LEVEL, "ui", 0, true, \ | ||||
|         do_log(DEBUG_LOG_LEVEL, "UI: ", NULL, -1, true, \ | ||||
|                "%s (+%zu times...)", uilog_last_event, uilog_seen); \ | ||||
|       } \ | ||||
|       DLOG("ui: " STR(funname)); \ | ||||
|       do_log(DEBUG_LOG_LEVEL, "UI: ", NULL, -1, true, STR(funname)); \ | ||||
|       uilog_seen = 0; \ | ||||
|       xstrlcpy(uilog_last_event, STR(funname), sizeof(uilog_last_event)); \ | ||||
|     } \ | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| -- Some sanity checks for the TUI using the builtin terminal emulator | ||||
| -- as a simple way to send keys and assert screen state. | ||||
| -- TUI acceptance tests. | ||||
| -- Uses :terminal as a way to send keys and assert screen state. | ||||
| local global_helpers = require('test.helpers') | ||||
| local helpers = require('test.functional.helpers')(after_each) | ||||
| local thelpers = require('test.functional.terminal.helpers') | ||||
| local feed_data = thelpers.feed_data | ||||
| @@ -194,7 +195,7 @@ describe('tui with non-tty file descriptors', function() | ||||
|   end) | ||||
| end) | ||||
|  | ||||
| describe('tui focus event handling', function() | ||||
| describe('tui FocusGained/FocusLost', function() | ||||
|   local screen | ||||
|  | ||||
|   before_each(function() | ||||
| @@ -206,7 +207,8 @@ describe('tui focus event handling', function() | ||||
|     feed_data("\034\016")  -- CTRL-\ CTRL-N | ||||
|   end) | ||||
|  | ||||
|   it('can handle focus events in normal mode', function() | ||||
|   it('in normal-mode', function() | ||||
|     retry(2, 3 * screen.timeout, function() | ||||
|     feed_data('\027[I') | ||||
|     screen:expect([[ | ||||
|       {1: }                                                 | | ||||
| @@ -229,10 +231,12 @@ describe('tui focus event handling', function() | ||||
|       {3:-- TERMINAL --}                                    | | ||||
|     ]]) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
|   it('can handle focus events in insert mode', function() | ||||
|   it('in insert-mode', function() | ||||
|     feed_command('set noshowmode') | ||||
|     feed_data('i') | ||||
|     retry(2, 3 * screen.timeout, function() | ||||
|     feed_data('\027[I') | ||||
|     screen:expect([[ | ||||
|       {1: }                                                 | | ||||
| @@ -254,8 +258,11 @@ describe('tui focus event handling', function() | ||||
|       {3:-- TERMINAL --}                                    | | ||||
|     ]]) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
|   it('can handle focus events in cmdline mode', function() | ||||
|   -- During cmdline-mode we ignore :echo invoked by timers/events. | ||||
|   -- See commit: 5cc87d4dabd02167117be7a978b5c8faaa975419. | ||||
|   it('in cmdline-mode does NOT :echo', function() | ||||
|     feed_data(':') | ||||
|     feed_data('\027[I') | ||||
|     screen:expect([[ | ||||
| @@ -264,7 +271,7 @@ describe('tui focus event handling', function() | ||||
|       {4:~                                                 }| | ||||
|       {4:~                                                 }| | ||||
|       {5:[No Name]                                         }| | ||||
|       g{1:a}ined                                            | | ||||
|       :{1: }                                                | | ||||
|       {3:-- TERMINAL --}                                    | | ||||
|     ]]) | ||||
|     feed_data('\027[O') | ||||
| @@ -274,17 +281,46 @@ describe('tui focus event handling', function() | ||||
|       {4:~                                                 }| | ||||
|       {4:~                                                 }| | ||||
|       {5:[No Name]                                         }| | ||||
|       l{1:o}st                                              | | ||||
|       :{1: }                                                | | ||||
|       {3:-- TERMINAL --}                                    | | ||||
|     ]]) | ||||
|   end) | ||||
|  | ||||
|   it('can handle focus events in terminal mode', function() | ||||
|   it('in cmdline-mode', function() | ||||
|     -- Set up autocmds that modify the buffer, instead of just calling :echo. | ||||
|     -- This is how we can test handling of focus gained/lost during cmdline-mode. | ||||
|     -- See commit: 5cc87d4dabd02167117be7a978b5c8faaa975419. | ||||
|     feed_data(":autocmd!\n") | ||||
|     feed_data(":autocmd FocusLost * call append(line('$'), 'lost')\n") | ||||
|     feed_data(":autocmd FocusGained * call append(line('$'), 'gained')\n") | ||||
|     -- Enter cmdline-mode. | ||||
|     feed_data(':') | ||||
|     screen:sleep(1) | ||||
|     -- Send focus lost/gained termcodes. | ||||
|     feed_data('\027[O') | ||||
|     feed_data('\027[I') | ||||
|     screen:sleep(1) | ||||
|     -- Exit cmdline-mode. Redraws from timers/events are blocked during | ||||
|     -- cmdline-mode, so the buffer won't be updated until we exit cmdline-mode. | ||||
|     feed_data('\n') | ||||
|     screen:expect([[ | ||||
|       {1: }                                                 | | ||||
|       lost                                              | | ||||
|       gained                                            | | ||||
|       {4:~                                                 }| | ||||
|       {5:[No Name] [+]                                     }| | ||||
|       :                                                 | | ||||
|       {3:-- TERMINAL --}                                    | | ||||
|     ]]) | ||||
|   end) | ||||
|  | ||||
|   it('in terminal-mode', function() | ||||
|     feed_data(':set shell='..nvim_dir..'/shell-test\n') | ||||
|     feed_data(':set noshowmode laststatus=0\n') | ||||
|  | ||||
|     retry(2, 3 * screen.timeout, function() | ||||
|       feed_data(':terminal\n') | ||||
|       screen:sleep(1) | ||||
|       feed_data('\027[I') | ||||
|       screen:expect([[ | ||||
|         {1:r}eady $                                           | | ||||
| @@ -311,13 +347,30 @@ describe('tui focus event handling', function() | ||||
|       feed_data(':bwipeout!\n') | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
|   it('in press-enter prompt', function() | ||||
|     feed_data(":echom 'msg1'|echom 'msg2'|echom 'msg3'|echom 'msg4'|echom 'msg5'\n") | ||||
|     -- Execute :messages to provoke the press-enter prompt. | ||||
|     feed_data(":messages\n") | ||||
|     feed_data('\027[I') | ||||
|     feed_data('\027[I') | ||||
|     screen:expect([[ | ||||
|       msg1                                              | | ||||
|       msg2                                              | | ||||
|       msg3                                              | | ||||
|       msg4                                              | | ||||
|       msg5                                              | | ||||
|       {10:Press ENTER or type command to continue}{1: }          | | ||||
|       {3:-- TERMINAL --}                                    | | ||||
|     ]]) | ||||
|   end) | ||||
| end) | ||||
|  | ||||
| -- These tests require `thelpers` because --headless/--embed | ||||
| -- does not initialize the TUI. | ||||
| describe("tui 't_Co' (terminal colors)", function() | ||||
|   local screen | ||||
|   local is_freebsd = (helpers.eval("system('uname') =~? 'FreeBSD'") == 1) | ||||
|   local is_freebsd = (string.lower(global_helpers.uname()) == 'freebsd') | ||||
|  | ||||
|   local function assert_term_colors(term, colorterm, maxcolors) | ||||
|     helpers.clear({env={TERM=term}, args={}}) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Justin M. Keyes
					Justin M. Keyes