aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/tui/input.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/tui/input.c')
-rw-r--r--src/nvim/tui/input.c44
1 files changed, 37 insertions, 7 deletions
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index 654b857301..99eb230a88 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -10,6 +10,8 @@
#include "nvim/event/rstream.h"
#define PASTETOGGLE_KEY "<Paste>"
+#define FOCUSGAINED_KEY "<FocusGained>"
+#define FOCUSLOST_KEY "<FocusLost>"
#define KEY_BUFFER_SIZE 0xfff
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -222,9 +224,9 @@ static void tk_getkeys(TermInput *input, bool force)
while ((result = tk_getkey(input->tk, &key, force)) == TERMKEY_RES_KEY) {
if (key.type == TERMKEY_TYPE_UNICODE && !key.modifiers) {
forward_simple_utf8(input, &key);
- } else if (key.type == TERMKEY_TYPE_UNICODE ||
- key.type == TERMKEY_TYPE_FUNCTION ||
- key.type == TERMKEY_TYPE_KEYSYM) {
+ } else if (key.type == TERMKEY_TYPE_UNICODE
+ || key.type == TERMKEY_TYPE_FUNCTION
+ || key.type == TERMKEY_TYPE_KEYSYM) {
forward_modified_utf8(input, &key);
} else if (key.type == TERMKEY_TYPE_MOUSE) {
forward_mouse_event(input, &key);
@@ -252,11 +254,37 @@ static void timer_cb(TimeWatcher *watcher, void *data)
flush_input(data, true);
}
+/// 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
+///
+/// @param input the input stream
+/// @return true iff handle_focus_event consumed some input
+static bool handle_focus_event(TermInput *input)
+{
+ if (rbuffer_size(input->read_stream.buffer) > 2
+ && (!rbuffer_cmp(input->read_stream.buffer, "\x1b[I", 3)
+ || !rbuffer_cmp(input->read_stream.buffer, "\x1b[O", 3))) {
+ // 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);
+ }
+ return true;
+ }
+ return false;
+}
+
static bool handle_bracketed_paste(TermInput *input)
{
- if (rbuffer_size(input->read_stream.buffer) > 5 &&
- (!rbuffer_cmp(input->read_stream.buffer, "\x1b[200~", 6) ||
- !rbuffer_cmp(input->read_stream.buffer, "\x1b[201~", 6))) {
+ if (rbuffer_size(input->read_stream.buffer) > 5
+ && (!rbuffer_cmp(input->read_stream.buffer, "\x1b[200~", 6)
+ || !rbuffer_cmp(input->read_stream.buffer, "\x1b[201~", 6))) {
bool enable = *rbuffer_get(input->read_stream.buffer, 4) == '0';
// Advance past the sequence
rbuffer_consumed(input->read_stream.buffer, 6);
@@ -314,7 +342,9 @@ static void read_cb(Stream *stream, RBuffer *buf, size_t c, void *data,
}
do {
- if (handle_bracketed_paste(input) || handle_forced_escape(input)) {
+ if (handle_focus_event(input)
+ || handle_bracketed_paste(input)
+ || handle_forced_escape(input)) {
continue;
}