4 * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/types.h>
27 * This file is rather misleadingly named, it contains the code which takes a
28 * key code and translates it into something suitable to be sent to the
29 * application running in a pane (similar to input.c does in the other
30 * direction with output).
33 static void input_key_mouse(struct window_pane
*, struct mouse_event
*);
35 /* Entry in the key tree. */
36 struct input_key_entry
{
40 RB_ENTRY(input_key_entry
) entry
;
42 RB_HEAD(input_key_tree
, input_key_entry
);
44 /* Tree of input keys. */
45 static int input_key_cmp(struct input_key_entry
*,
46 struct input_key_entry
*);
47 RB_GENERATE_STATIC(input_key_tree
, input_key_entry
, entry
, input_key_cmp
);
48 struct input_key_tree input_key_tree
= RB_INITIALIZER(&input_key_tree
);
50 /* List of default keys, the tree is built from this. */
51 static struct input_key_entry input_key_defaults
[] = {
53 { .key
= KEYC_PASTE_START
,
56 { .key
= KEYC_PASTE_END
,
120 { .key
= KEYC_UP
|KEYC_CURSOR
,
123 { .key
= KEYC_DOWN
|KEYC_CURSOR
,
126 { .key
= KEYC_RIGHT
|KEYC_CURSOR
,
129 { .key
= KEYC_LEFT
|KEYC_CURSOR
,
146 { .key
= KEYC_KP_SLASH
|KEYC_KEYPAD
,
149 { .key
= KEYC_KP_STAR
|KEYC_KEYPAD
,
152 { .key
= KEYC_KP_MINUS
|KEYC_KEYPAD
,
155 { .key
= KEYC_KP_SEVEN
|KEYC_KEYPAD
,
158 { .key
= KEYC_KP_EIGHT
|KEYC_KEYPAD
,
161 { .key
= KEYC_KP_NINE
|KEYC_KEYPAD
,
164 { .key
= KEYC_KP_PLUS
|KEYC_KEYPAD
,
167 { .key
= KEYC_KP_FOUR
|KEYC_KEYPAD
,
170 { .key
= KEYC_KP_FIVE
|KEYC_KEYPAD
,
173 { .key
= KEYC_KP_SIX
|KEYC_KEYPAD
,
176 { .key
= KEYC_KP_ONE
|KEYC_KEYPAD
,
179 { .key
= KEYC_KP_TWO
|KEYC_KEYPAD
,
182 { .key
= KEYC_KP_THREE
|KEYC_KEYPAD
,
185 { .key
= KEYC_KP_ENTER
|KEYC_KEYPAD
,
188 { .key
= KEYC_KP_ZERO
|KEYC_KEYPAD
,
191 { .key
= KEYC_KP_PERIOD
|KEYC_KEYPAD
,
194 { .key
= KEYC_KP_SLASH
,
197 { .key
= KEYC_KP_STAR
,
200 { .key
= KEYC_KP_MINUS
,
203 { .key
= KEYC_KP_SEVEN
,
206 { .key
= KEYC_KP_EIGHT
,
209 { .key
= KEYC_KP_NINE
,
212 { .key
= KEYC_KP_PLUS
,
215 { .key
= KEYC_KP_FOUR
,
218 { .key
= KEYC_KP_FIVE
,
221 { .key
= KEYC_KP_SIX
,
224 { .key
= KEYC_KP_ONE
,
227 { .key
= KEYC_KP_TWO
,
230 { .key
= KEYC_KP_THREE
,
233 { .key
= KEYC_KP_ENTER
,
236 { .key
= KEYC_KP_ZERO
,
239 { .key
= KEYC_KP_PERIOD
,
243 /* Keys with an embedded modifier. */
244 { .key
= KEYC_F1
|KEYC_BUILD_MODIFIERS
,
247 { .key
= KEYC_F2
|KEYC_BUILD_MODIFIERS
,
250 { .key
= KEYC_F3
|KEYC_BUILD_MODIFIERS
,
253 { .key
= KEYC_F4
|KEYC_BUILD_MODIFIERS
,
256 { .key
= KEYC_F5
|KEYC_BUILD_MODIFIERS
,
259 { .key
= KEYC_F6
|KEYC_BUILD_MODIFIERS
,
262 { .key
= KEYC_F7
|KEYC_BUILD_MODIFIERS
,
265 { .key
= KEYC_F8
|KEYC_BUILD_MODIFIERS
,
268 { .key
= KEYC_F9
|KEYC_BUILD_MODIFIERS
,
271 { .key
= KEYC_F10
|KEYC_BUILD_MODIFIERS
,
274 { .key
= KEYC_F11
|KEYC_BUILD_MODIFIERS
,
277 { .key
= KEYC_F12
|KEYC_BUILD_MODIFIERS
,
280 { .key
= KEYC_UP
|KEYC_BUILD_MODIFIERS
,
283 { .key
= KEYC_DOWN
|KEYC_BUILD_MODIFIERS
,
286 { .key
= KEYC_RIGHT
|KEYC_BUILD_MODIFIERS
,
289 { .key
= KEYC_LEFT
|KEYC_BUILD_MODIFIERS
,
292 { .key
= KEYC_HOME
|KEYC_BUILD_MODIFIERS
,
295 { .key
= KEYC_END
|KEYC_BUILD_MODIFIERS
,
298 { .key
= KEYC_PPAGE
|KEYC_BUILD_MODIFIERS
,
301 { .key
= KEYC_NPAGE
|KEYC_BUILD_MODIFIERS
,
304 { .key
= KEYC_IC
|KEYC_BUILD_MODIFIERS
,
307 { .key
= KEYC_DC
|KEYC_BUILD_MODIFIERS
,
311 static const key_code input_key_modifiers
[] = {
315 KEYC_META
|KEYC_IMPLIED_META
,
316 KEYC_SHIFT
|KEYC_META
|KEYC_IMPLIED_META
,
318 KEYC_SHIFT
|KEYC_CTRL
,
319 KEYC_META
|KEYC_IMPLIED_META
|KEYC_CTRL
,
320 KEYC_SHIFT
|KEYC_META
|KEYC_IMPLIED_META
|KEYC_CTRL
323 /* Input key comparison function. */
325 input_key_cmp(struct input_key_entry
*ike1
, struct input_key_entry
*ike2
)
327 if (ike1
->key
< ike2
->key
)
329 if (ike1
->key
> ike2
->key
)
334 /* Look for key in tree. */
335 static struct input_key_entry
*
336 input_key_get(key_code key
)
338 struct input_key_entry entry
= { .key
= key
};
340 return (RB_FIND(input_key_tree
, &input_key_tree
, &entry
));
343 /* Split a character into two UTF-8 bytes. */
345 input_key_split2(u_int c
, u_char
*dst
)
348 dst
[0] = (c
>> 6) | 0xc0;
349 dst
[1] = (c
& 0x3f) | 0x80;
356 /* Build input key tree. */
358 input_key_build(void)
360 struct input_key_entry
*ike
, *new;
365 for (i
= 0; i
< nitems(input_key_defaults
); i
++) {
366 ike
= &input_key_defaults
[i
];
367 if (~ike
->key
& KEYC_BUILD_MODIFIERS
) {
368 RB_INSERT(input_key_tree
, &input_key_tree
, ike
);
372 for (j
= 2; j
< nitems(input_key_modifiers
); j
++) {
373 key
= (ike
->key
& ~KEYC_BUILD_MODIFIERS
);
374 data
= xstrdup(ike
->data
);
375 data
[strcspn(data
, "_")] = '0' + j
;
377 new = xcalloc(1, sizeof *new);
378 new->key
= key
|input_key_modifiers
[j
];
380 RB_INSERT(input_key_tree
, &input_key_tree
, new);
384 RB_FOREACH(ike
, input_key_tree
, &input_key_tree
) {
385 log_debug("%s: 0x%llx (%s) is %s", __func__
, ike
->key
,
386 key_string_lookup_key(ike
->key
, 1), ike
->data
);
390 /* Translate a key code into an output key sequence for a pane. */
392 input_key_pane(struct window_pane
*wp
, key_code key
, struct mouse_event
*m
)
394 if (log_get_level() != 0) {
395 log_debug("writing key 0x%llx (%s) to %%%u", key
,
396 key_string_lookup_key(key
, 1), wp
->id
);
399 if (KEYC_IS_MOUSE(key
)) {
400 if (m
!= NULL
&& m
->wp
!= -1 && (u_int
)m
->wp
== wp
->id
)
401 input_key_mouse(wp
, m
);
404 return (input_key(wp
->screen
, wp
->event
, key
));
408 input_key_write(const char *from
, struct bufferevent
*bev
, const char *data
,
411 log_debug("%s: %.*s", from
, (int)size
, data
);
412 bufferevent_write(bev
, data
, size
);
416 * Encode and write an extended key escape sequence in one of the two
417 * possible formats, depending on the configured output mode.
420 input_key_extended(struct bufferevent
*bev
, key_code key
)
422 char tmp
[64], modifier
;
426 switch (key
& KEYC_MASK_MODIFIERS
) {
433 case KEYC_SHIFT
|KEYC_META
:
439 case KEYC_SHIFT
|KEYC_CTRL
:
442 case KEYC_META
|KEYC_CTRL
:
445 case KEYC_SHIFT
|KEYC_META
|KEYC_CTRL
:
452 if (KEYC_IS_UNICODE(key
)) {
453 utf8_to_data(key
& KEYC_MASK_KEY
, &ud
);
454 if (utf8_towc(&ud
, &wc
) == UTF8_DONE
)
459 key
&= KEYC_MASK_KEY
;
461 if (options_get_number(global_options
, "extended-keys-format") == 1)
462 xsnprintf(tmp
, sizeof tmp
, "\033[27;%c;%llu~", modifier
, key
);
464 xsnprintf(tmp
, sizeof tmp
, "\033[%llu;%cu", key
, modifier
);
466 input_key_write(__func__
, bev
, tmp
, strlen(tmp
));
471 * Outputs the key in the "standard" mode. This is by far the most
472 * complicated output mode, with a lot of remapping in order to
473 * emulate quirks of terminals that today can be only found in museums.
476 input_key_vt10x(struct bufferevent
*bev
, key_code key
)
481 static const char *standard_map
[2] = {
482 "1!9(0)=+;:'\",<.>/-8? 2",
483 "119900=+;;'',,..\x1f\x1f\x7f\x7f\0\0",
486 log_debug("%s: key in %llx", __func__
, key
);
489 input_key_write(__func__
, bev
, "\033", 1);
492 * There's no way to report modifiers for unicode keys in standard mode
493 * so lose the modifiers.
495 if (KEYC_IS_UNICODE(key
)) {
496 utf8_to_data(key
, &ud
);
497 input_key_write(__func__
, bev
, ud
.data
, ud
.size
);
502 * Prevent TAB, CR and LF from being swallowed by the C0 remapping
505 onlykey
= key
& KEYC_MASK_KEY
;
506 if (onlykey
== '\r' || onlykey
== '\n' || onlykey
== '\t')
510 * Convert keys with Ctrl modifier into corresponding C0 control codes,
511 * with the exception of *some* keys, which are remapped into printable
514 * There is no special handling for Shift modifier, which is pretty
515 * much redundant anyway, as no terminal will send <base key>|SHIFT,
516 * but only <shifted key>|SHIFT.
518 if (key
& KEYC_CTRL
) {
519 p
= strchr(standard_map
[0], onlykey
);
521 key
= standard_map
[1][p
- standard_map
[0]];
522 else if (onlykey
>= '3' && onlykey
<= '7')
523 key
= onlykey
- '\030';
524 else if (onlykey
>= '@' && onlykey
<= '~')
525 key
= onlykey
& 0x1f;
530 log_debug("%s: key out %llx", __func__
, key
);
532 ud
.data
[0] = key
& 0x7f;
533 input_key_write(__func__
, bev
, &ud
.data
[0], 1);
537 /* Pick keys that are reported as vt10x keys in modifyOtherKeys=1 mode. */
539 input_key_mode1(struct bufferevent
*bev
, key_code key
)
543 log_debug("%s: key in %llx", __func__
, key
);
547 * https://invisible-island.net/xterm/modified-keys-us-pc105.html.
549 onlykey
= key
& KEYC_MASK_KEY
;
550 if ((key
& (KEYC_META
| KEYC_CTRL
)) == KEYC_CTRL
&&
555 (onlykey
>= '2' && onlykey
<= '8') ||
556 (onlykey
>= '@' && onlykey
<= '~')))
557 return (input_key_vt10x(bev
, key
));
560 * A regular key + Meta. In the absence of a standard to back this, we
561 * mimic what iTerm 2 does.
563 if ((key
& (KEYC_CTRL
| KEYC_META
)) == KEYC_META
)
564 return (input_key_vt10x(bev
, key
));
569 /* Translate a key code into an output key sequence. */
571 input_key(struct screen
*s
, struct bufferevent
*bev
, key_code key
)
573 struct input_key_entry
*ike
= NULL
;
577 /* Mouse keys need a pane. */
578 if (KEYC_IS_MOUSE(key
))
581 /* Literal keys go as themselves (can't be more than eight bits). */
582 if (key
& KEYC_LITERAL
) {
583 ud
.data
[0] = (u_char
)key
;
584 input_key_write(__func__
, bev
, &ud
.data
[0], 1);
588 /* Is this backspace? */
589 if ((key
& KEYC_MASK_KEY
) == KEYC_BSPACE
) {
590 newkey
= options_get_number(global_options
, "backspace");
593 key
= newkey
|(key
& (KEYC_MASK_MODIFIERS
|KEYC_MASK_FLAGS
));
596 /* Is this backtab? */
597 if ((key
& KEYC_MASK_KEY
) == KEYC_BTAB
) {
598 if ((s
->mode
& EXTENDED_KEY_MODES
) != 0) {
599 /* When in xterm extended mode, remap into S-Tab. */
600 key
= '\011' | (key
& ~KEYC_MASK_KEY
) | KEYC_SHIFT
;
602 /* Otherwise clear modifiers. */
603 key
&= ~KEYC_MASK_MODIFIERS
;
608 * A trivial case, that is a 7-bit key, excluding C0 control characters
609 * that can't be entered from the keyboard, and no modifiers; or a UTF-8
610 * key and no modifiers.
612 if (!(key
& ~KEYC_MASK_KEY
)) {
616 (key
>= 0x20 && key
<= 0x7f)) {
618 input_key_write(__func__
, bev
, &ud
.data
[0], 1);
621 if (KEYC_IS_UNICODE(key
)) {
622 utf8_to_data(key
, &ud
);
623 input_key_write(__func__
, bev
, ud
.data
, ud
.size
);
629 * Look up the standard VT10x keys in the tree. If not in application
630 * keypad or cursor mode, remove the respective flags from the key.
632 if (~s
->mode
& MODE_KKEYPAD
)
634 if (~s
->mode
& MODE_KCURSOR
)
637 ike
= input_key_get(key
);
638 if (ike
== NULL
&& (key
& KEYC_META
) && (~key
& KEYC_IMPLIED_META
))
639 ike
= input_key_get(key
& ~KEYC_META
);
640 if (ike
== NULL
&& (key
& KEYC_CURSOR
))
641 ike
= input_key_get(key
& ~KEYC_CURSOR
);
642 if (ike
== NULL
&& (key
& KEYC_KEYPAD
))
643 ike
= input_key_get(key
& ~KEYC_KEYPAD
);
645 log_debug("%s: found key 0x%llx: \"%s\"", __func__
, key
,
647 if ((key
== KEYC_PASTE_START
|| key
== KEYC_PASTE_END
) &&
648 (~s
->mode
& MODE_BRACKETPASTE
))
650 if ((key
& KEYC_META
) && (~key
& KEYC_IMPLIED_META
))
651 input_key_write(__func__
, bev
, "\033", 1);
652 input_key_write(__func__
, bev
, ike
->data
, strlen(ike
->data
));
656 /* Ignore internal function key codes. */
657 if ((key
>= KEYC_BASE
&& key
< KEYC_BASE_END
) ||
658 (key
>= KEYC_USER
&& key
< KEYC_USER_END
)) {
659 log_debug("%s: ignoring key 0x%llx", __func__
, key
);
664 * No builtin key sequence; construct an extended key sequence
665 * depending on the client mode.
667 * If something invalid reaches here, an invalid output may be
668 * produced. For example Ctrl-Shift-2 is invalid (as there's
669 * no way to enter it). The correct form is Ctrl-Shift-@, at
670 * least in US English keyboard layout.
672 switch (s
->mode
& EXTENDED_KEY_MODES
) {
673 case MODE_KEYS_EXTENDED_2
:
675 * The simplest mode to handle - *all* modified keys are
676 * reported in the extended form.
678 return (input_key_extended(bev
, key
));
679 case MODE_KEYS_EXTENDED
:
681 * Some keys are still reported in standard mode, to maintain
682 * compatibility with applications unaware of extended keys.
684 if (input_key_mode1(bev
, key
) == -1)
685 return (input_key_extended(bev
, key
));
688 /* The standard mode. */
689 return (input_key_vt10x(bev
, key
));
693 /* Get mouse event string. */
695 input_key_get_mouse(struct screen
*s
, struct mouse_event
*m
, u_int x
, u_int y
,
696 const char **rbuf
, size_t *rlen
)
704 /* If this pane is not in button or all mode, discard motion events. */
705 if (MOUSE_DRAG(m
->b
) && (s
->mode
& MOTION_MOUSE_MODES
) == 0)
707 if ((s
->mode
& ALL_MOUSE_MODES
) == 0)
711 * If this event is a release event and not in all mode, discard it.
712 * In SGR mode we can tell absolutely because a release is normally
713 * shown by the last character. Without SGR, we check if the last
714 * buttons was also a release.
716 if (m
->sgr_type
!= ' ') {
717 if (MOUSE_DRAG(m
->sgr_b
) &&
718 MOUSE_RELEASE(m
->sgr_b
) &&
719 (~s
->mode
& MODE_MOUSE_ALL
))
722 if (MOUSE_DRAG(m
->b
) &&
723 MOUSE_RELEASE(m
->b
) &&
724 MOUSE_RELEASE(m
->lb
) &&
725 (~s
->mode
& MODE_MOUSE_ALL
))
730 * Use the SGR (1006) extension only if the application requested it
731 * and the underlying terminal also sent the event in this format (this
732 * is because an old style mouse release event cannot be converted into
733 * the new SGR format, since the released button is unknown). Otherwise
734 * pretend that tmux doesn't speak this extension, and fall back to the
735 * UTF-8 (1005) extension if the application requested, or to the
738 if (m
->sgr_type
!= ' ' && (s
->mode
& MODE_MOUSE_SGR
)) {
739 len
= xsnprintf(buf
, sizeof buf
, "\033[<%u;%u;%u%c",
740 m
->sgr_b
, x
+ 1, y
+ 1, m
->sgr_type
);
741 } else if (s
->mode
& MODE_MOUSE_UTF8
) {
742 if (m
->b
> MOUSE_PARAM_UTF8_MAX
- MOUSE_PARAM_BTN_OFF
||
743 x
> MOUSE_PARAM_UTF8_MAX
- MOUSE_PARAM_POS_OFF
||
744 y
> MOUSE_PARAM_UTF8_MAX
- MOUSE_PARAM_POS_OFF
)
746 len
= xsnprintf(buf
, sizeof buf
, "\033[M");
747 len
+= input_key_split2(m
->b
+ MOUSE_PARAM_BTN_OFF
, &buf
[len
]);
748 len
+= input_key_split2(x
+ MOUSE_PARAM_POS_OFF
, &buf
[len
]);
749 len
+= input_key_split2(y
+ MOUSE_PARAM_POS_OFF
, &buf
[len
]);
751 if (m
->b
+ MOUSE_PARAM_BTN_OFF
> MOUSE_PARAM_MAX
)
754 len
= xsnprintf(buf
, sizeof buf
, "\033[M");
755 buf
[len
++] = m
->b
+ MOUSE_PARAM_BTN_OFF
;
758 * The incoming x and y may be out of the range which can be
759 * supported by the "normal" mouse protocol. Clamp the
760 * coordinates to the supported range.
762 if (x
+ MOUSE_PARAM_POS_OFF
> MOUSE_PARAM_MAX
)
763 buf
[len
++] = MOUSE_PARAM_MAX
;
765 buf
[len
++] = x
+ MOUSE_PARAM_POS_OFF
;
766 if (y
+ MOUSE_PARAM_POS_OFF
> MOUSE_PARAM_MAX
)
767 buf
[len
++] = MOUSE_PARAM_MAX
;
769 buf
[len
++] = y
+ MOUSE_PARAM_POS_OFF
;
777 /* Translate mouse and output. */
779 input_key_mouse(struct window_pane
*wp
, struct mouse_event
*m
)
781 struct screen
*s
= wp
->screen
;
786 /* Ignore events if no mouse mode or the pane is not visible. */
787 if (m
->ignore
|| (s
->mode
& ALL_MOUSE_MODES
) == 0)
789 if (cmd_mouse_at(wp
, m
, &x
, &y
, 0) != 0)
791 if (!window_pane_visible(wp
))
793 if (!input_key_get_mouse(s
, m
, x
, y
, &buf
, &len
))
795 log_debug("writing mouse %.*s to %%%u", (int)len
, buf
, wp
->id
);
796 input_key_write(__func__
, wp
->event
, buf
, len
);