xref: /netbsd-src/external/bsd/tmux/dist/input-keys.c (revision 890b6d91a44b7fcb2dfbcbc1e93463086e462d2d)
199e242abSchristos /* $OpenBSD$ */
2698d5317Sjmmv 
3698d5317Sjmmv /*
4f26e8bc9Schristos  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
5698d5317Sjmmv  *
6698d5317Sjmmv  * Permission to use, copy, modify, and distribute this software for any
7698d5317Sjmmv  * purpose with or without fee is hereby granted, provided that the above
8698d5317Sjmmv  * copyright notice and this permission notice appear in all copies.
9698d5317Sjmmv  *
10698d5317Sjmmv  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11698d5317Sjmmv  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12698d5317Sjmmv  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13698d5317Sjmmv  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14698d5317Sjmmv  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15698d5317Sjmmv  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16698d5317Sjmmv  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17698d5317Sjmmv  */
18698d5317Sjmmv 
19698d5317Sjmmv #include <sys/types.h>
20698d5317Sjmmv 
21698d5317Sjmmv #include <stdlib.h>
22698d5317Sjmmv #include <string.h>
23698d5317Sjmmv 
24698d5317Sjmmv #include "tmux.h"
25698d5317Sjmmv 
26698d5317Sjmmv /*
27698d5317Sjmmv  * This file is rather misleadingly named, it contains the code which takes a
28698d5317Sjmmv  * key code and translates it into something suitable to be sent to the
29698d5317Sjmmv  * application running in a pane (similar to input.c does in the other
30698d5317Sjmmv  * direction with output).
31698d5317Sjmmv  */
32698d5317Sjmmv 
33e9a2d6faSchristos static void	 input_key_mouse(struct window_pane *, struct mouse_event *);
3499e242abSchristos 
35e271dbb8Schristos /* Entry in the key tree. */
36e271dbb8Schristos struct input_key_entry {
37f26e8bc9Schristos 	key_code			 key;
38698d5317Sjmmv 	const char			*data;
39698d5317Sjmmv 
40e271dbb8Schristos 	RB_ENTRY(input_key_entry)	 entry;
41698d5317Sjmmv };
42e271dbb8Schristos RB_HEAD(input_key_tree, input_key_entry);
43698d5317Sjmmv 
44e271dbb8Schristos /* Tree of input keys. */
45e271dbb8Schristos static int	input_key_cmp(struct input_key_entry *,
46e271dbb8Schristos 		    struct input_key_entry *);
47e271dbb8Schristos RB_GENERATE_STATIC(input_key_tree, input_key_entry, entry, input_key_cmp);
48e271dbb8Schristos struct input_key_tree input_key_tree = RB_INITIALIZER(&input_key_tree);
49e271dbb8Schristos 
50e271dbb8Schristos /* List of default keys, the tree is built from this. */
51e271dbb8Schristos static struct input_key_entry input_key_defaults[] = {
52fe99a117Schristos 	/* Paste keys. */
53e271dbb8Schristos 	{ .key = KEYC_PASTE_START,
54e271dbb8Schristos 	  .data = "\033[200~"
55e271dbb8Schristos 	},
56e271dbb8Schristos 	{ .key = KEYC_PASTE_END,
57e271dbb8Schristos 	  .data = "\033[201~"
58e271dbb8Schristos 	},
59fe99a117Schristos 
60698d5317Sjmmv 	/* Function keys. */
61e271dbb8Schristos 	{ .key = KEYC_F1,
62e271dbb8Schristos 	  .data = "\033OP"
63e271dbb8Schristos 	},
64e271dbb8Schristos 	{ .key = KEYC_F2,
65e271dbb8Schristos 	  .data = "\033OQ"
66e271dbb8Schristos 	},
67e271dbb8Schristos 	{ .key = KEYC_F3,
68e271dbb8Schristos 	  .data = "\033OR"
69e271dbb8Schristos 	},
70e271dbb8Schristos 	{ .key = KEYC_F4,
71e271dbb8Schristos 	  .data = "\033OS"
72e271dbb8Schristos 	},
73e271dbb8Schristos 	{ .key = KEYC_F5,
74e271dbb8Schristos 	  .data = "\033[15~"
75e271dbb8Schristos 	},
76e271dbb8Schristos 	{ .key = KEYC_F6,
77e271dbb8Schristos 	  .data = "\033[17~"
78e271dbb8Schristos 	},
79e271dbb8Schristos 	{ .key = KEYC_F7,
80e271dbb8Schristos 	  .data = "\033[18~"
81e271dbb8Schristos 	},
82e271dbb8Schristos 	{ .key = KEYC_F8,
83e271dbb8Schristos 	  .data = "\033[19~"
84e271dbb8Schristos 	},
85e271dbb8Schristos 	{ .key = KEYC_F9,
86e271dbb8Schristos 	  .data = "\033[20~"
87e271dbb8Schristos 	},
88e271dbb8Schristos 	{ .key = KEYC_F10,
89e271dbb8Schristos 	  .data = "\033[21~"
90e271dbb8Schristos 	},
91e271dbb8Schristos 	{ .key = KEYC_F11,
92e271dbb8Schristos 	  .data = "\033[23~"
93e271dbb8Schristos 	},
94e271dbb8Schristos 	{ .key = KEYC_F12,
95e271dbb8Schristos 	  .data = "\033[24~"
96e271dbb8Schristos 	},
97e271dbb8Schristos 	{ .key = KEYC_IC,
98e271dbb8Schristos 	  .data = "\033[2~"
99e271dbb8Schristos 	},
100e271dbb8Schristos 	{ .key = KEYC_DC,
101e271dbb8Schristos 	  .data = "\033[3~"
102e271dbb8Schristos 	},
103e271dbb8Schristos 	{ .key = KEYC_HOME,
104e271dbb8Schristos 	  .data = "\033[1~"
105e271dbb8Schristos 	},
106e271dbb8Schristos 	{ .key = KEYC_END,
107e271dbb8Schristos 	  .data = "\033[4~"
108e271dbb8Schristos 	},
109e271dbb8Schristos 	{ .key = KEYC_NPAGE,
110e271dbb8Schristos 	  .data = "\033[6~"
111e271dbb8Schristos 	},
112e271dbb8Schristos 	{ .key = KEYC_PPAGE,
113e271dbb8Schristos 	  .data = "\033[5~"
114e271dbb8Schristos 	},
115e271dbb8Schristos 	{ .key = KEYC_BTAB,
116e271dbb8Schristos 	  .data = "\033[Z"
117e271dbb8Schristos 	},
118698d5317Sjmmv 
119e271dbb8Schristos 	/* Arrow keys. */
120e271dbb8Schristos 	{ .key = KEYC_UP|KEYC_CURSOR,
121e271dbb8Schristos 	  .data = "\033OA"
122e271dbb8Schristos 	},
123e271dbb8Schristos 	{ .key = KEYC_DOWN|KEYC_CURSOR,
124e271dbb8Schristos 	  .data = "\033OB"
125e271dbb8Schristos 	},
126e271dbb8Schristos 	{ .key = KEYC_RIGHT|KEYC_CURSOR,
127e271dbb8Schristos 	  .data = "\033OC"
128e271dbb8Schristos 	},
129e271dbb8Schristos 	{ .key = KEYC_LEFT|KEYC_CURSOR,
130e271dbb8Schristos 	  .data = "\033OD"
131e271dbb8Schristos 	},
132e271dbb8Schristos 	{ .key = KEYC_UP,
133e271dbb8Schristos 	  .data = "\033[A"
134e271dbb8Schristos 	},
135e271dbb8Schristos 	{ .key = KEYC_DOWN,
136e271dbb8Schristos 	  .data = "\033[B"
137e271dbb8Schristos 	},
138e271dbb8Schristos 	{ .key = KEYC_RIGHT,
139e271dbb8Schristos 	  .data = "\033[C"
140e271dbb8Schristos 	},
141e271dbb8Schristos 	{ .key = KEYC_LEFT,
142e271dbb8Schristos 	  .data = "\033[D"
143e271dbb8Schristos 	},
144698d5317Sjmmv 
145e271dbb8Schristos 	/* Keypad keys. */
146e271dbb8Schristos 	{ .key = KEYC_KP_SLASH|KEYC_KEYPAD,
147e271dbb8Schristos 	  .data = "\033Oo"
148e271dbb8Schristos 	},
149e271dbb8Schristos 	{ .key = KEYC_KP_STAR|KEYC_KEYPAD,
150e271dbb8Schristos 	  .data = "\033Oj"
151e271dbb8Schristos 	},
152e271dbb8Schristos 	{ .key = KEYC_KP_MINUS|KEYC_KEYPAD,
153e271dbb8Schristos 	  .data = "\033Om"
154e271dbb8Schristos 	},
155e271dbb8Schristos 	{ .key = KEYC_KP_SEVEN|KEYC_KEYPAD,
156e271dbb8Schristos 	  .data = "\033Ow"
157e271dbb8Schristos 	},
158e271dbb8Schristos 	{ .key = KEYC_KP_EIGHT|KEYC_KEYPAD,
159e271dbb8Schristos 	  .data = "\033Ox"
160e271dbb8Schristos 	},
161e271dbb8Schristos 	{ .key = KEYC_KP_NINE|KEYC_KEYPAD,
162e271dbb8Schristos 	  .data = "\033Oy"
163e271dbb8Schristos 	},
164e271dbb8Schristos 	{ .key = KEYC_KP_PLUS|KEYC_KEYPAD,
165e271dbb8Schristos 	  .data = "\033Ok"
166e271dbb8Schristos 	},
167e271dbb8Schristos 	{ .key = KEYC_KP_FOUR|KEYC_KEYPAD,
168e271dbb8Schristos 	  .data = "\033Ot"
169e271dbb8Schristos 	},
170e271dbb8Schristos 	{ .key = KEYC_KP_FIVE|KEYC_KEYPAD,
171e271dbb8Schristos 	  .data = "\033Ou"
172e271dbb8Schristos 	},
173e271dbb8Schristos 	{ .key = KEYC_KP_SIX|KEYC_KEYPAD,
174e271dbb8Schristos 	  .data = "\033Ov"
175e271dbb8Schristos 	},
176e271dbb8Schristos 	{ .key = KEYC_KP_ONE|KEYC_KEYPAD,
177e271dbb8Schristos 	  .data = "\033Oq"
178e271dbb8Schristos 	},
179e271dbb8Schristos 	{ .key = KEYC_KP_TWO|KEYC_KEYPAD,
180e271dbb8Schristos 	  .data = "\033Or"
181e271dbb8Schristos 	},
182e271dbb8Schristos 	{ .key = KEYC_KP_THREE|KEYC_KEYPAD,
183e271dbb8Schristos 	  .data = "\033Os"
184e271dbb8Schristos 	},
185e271dbb8Schristos 	{ .key = KEYC_KP_ENTER|KEYC_KEYPAD,
186e271dbb8Schristos 	  .data = "\033OM"
187e271dbb8Schristos 	},
188e271dbb8Schristos 	{ .key = KEYC_KP_ZERO|KEYC_KEYPAD,
189e271dbb8Schristos 	  .data = "\033Op"
190e271dbb8Schristos 	},
191e271dbb8Schristos 	{ .key = KEYC_KP_PERIOD|KEYC_KEYPAD,
192e271dbb8Schristos 	  .data = "\033On"
193e271dbb8Schristos 	},
194e271dbb8Schristos 	{ .key = KEYC_KP_SLASH,
195e271dbb8Schristos 	  .data = "/"
196e271dbb8Schristos 	},
197e271dbb8Schristos 	{ .key = KEYC_KP_STAR,
198e271dbb8Schristos 	  .data = "*"
199e271dbb8Schristos 	},
200e271dbb8Schristos 	{ .key = KEYC_KP_MINUS,
201e271dbb8Schristos 	  .data = "-"
202e271dbb8Schristos 	},
203e271dbb8Schristos 	{ .key = KEYC_KP_SEVEN,
204e271dbb8Schristos 	  .data = "7"
205e271dbb8Schristos 	},
206e271dbb8Schristos 	{ .key = KEYC_KP_EIGHT,
207e271dbb8Schristos 	  .data = "8"
208e271dbb8Schristos 	},
209e271dbb8Schristos 	{ .key = KEYC_KP_NINE,
210e271dbb8Schristos 	  .data = "9"
211e271dbb8Schristos 	},
212e271dbb8Schristos 	{ .key = KEYC_KP_PLUS,
213e271dbb8Schristos 	  .data = "+"
214e271dbb8Schristos 	},
215e271dbb8Schristos 	{ .key = KEYC_KP_FOUR,
216e271dbb8Schristos 	  .data = "4"
217e271dbb8Schristos 	},
218e271dbb8Schristos 	{ .key = KEYC_KP_FIVE,
219e271dbb8Schristos 	  .data = "5"
220e271dbb8Schristos 	},
221e271dbb8Schristos 	{ .key = KEYC_KP_SIX,
222e271dbb8Schristos 	  .data = "6"
223e271dbb8Schristos 	},
224e271dbb8Schristos 	{ .key = KEYC_KP_ONE,
225e271dbb8Schristos 	  .data = "1"
226e271dbb8Schristos 	},
227e271dbb8Schristos 	{ .key = KEYC_KP_TWO,
228e271dbb8Schristos 	  .data = "2"
229e271dbb8Schristos 	},
230e271dbb8Schristos 	{ .key = KEYC_KP_THREE,
231e271dbb8Schristos 	  .data = "3"
232e271dbb8Schristos 	},
233e271dbb8Schristos 	{ .key = KEYC_KP_ENTER,
234e271dbb8Schristos 	  .data = "\n"
235e271dbb8Schristos 	},
236e271dbb8Schristos 	{ .key = KEYC_KP_ZERO,
237e271dbb8Schristos 	  .data = "0"
238e271dbb8Schristos 	},
239e271dbb8Schristos 	{ .key = KEYC_KP_PERIOD,
240e271dbb8Schristos 	  .data = "."
241e271dbb8Schristos 	},
242698d5317Sjmmv 
243e271dbb8Schristos 	/* Keys with an embedded modifier. */
244e271dbb8Schristos 	{ .key = KEYC_F1|KEYC_BUILD_MODIFIERS,
245e271dbb8Schristos 	  .data = "\033[1;_P"
246e271dbb8Schristos 	},
247e271dbb8Schristos 	{ .key = KEYC_F2|KEYC_BUILD_MODIFIERS,
248e271dbb8Schristos 	  .data = "\033[1;_Q"
249e271dbb8Schristos 	},
250e271dbb8Schristos 	{ .key = KEYC_F3|KEYC_BUILD_MODIFIERS,
251e271dbb8Schristos 	  .data = "\033[1;_R"
252e271dbb8Schristos 	},
253e271dbb8Schristos 	{ .key = KEYC_F4|KEYC_BUILD_MODIFIERS,
254e271dbb8Schristos 	  .data = "\033[1;_S"
255e271dbb8Schristos 	},
256e271dbb8Schristos 	{ .key = KEYC_F5|KEYC_BUILD_MODIFIERS,
257e271dbb8Schristos 	  .data = "\033[15;_~"
258e271dbb8Schristos 	},
259e271dbb8Schristos 	{ .key = KEYC_F6|KEYC_BUILD_MODIFIERS,
260e271dbb8Schristos 	  .data = "\033[17;_~"
261e271dbb8Schristos 	},
262e271dbb8Schristos 	{ .key = KEYC_F7|KEYC_BUILD_MODIFIERS,
263e271dbb8Schristos 	  .data = "\033[18;_~"
264e271dbb8Schristos 	},
265e271dbb8Schristos 	{ .key = KEYC_F8|KEYC_BUILD_MODIFIERS,
266e271dbb8Schristos 	  .data = "\033[19;_~"
267e271dbb8Schristos 	},
268e271dbb8Schristos 	{ .key = KEYC_F9|KEYC_BUILD_MODIFIERS,
269e271dbb8Schristos 	  .data = "\033[20;_~"
270e271dbb8Schristos 	},
271e271dbb8Schristos 	{ .key = KEYC_F10|KEYC_BUILD_MODIFIERS,
272e271dbb8Schristos 	  .data = "\033[21;_~"
273e271dbb8Schristos 	},
274e271dbb8Schristos 	{ .key = KEYC_F11|KEYC_BUILD_MODIFIERS,
275e271dbb8Schristos 	  .data = "\033[23;_~"
276e271dbb8Schristos 	},
277e271dbb8Schristos 	{ .key = KEYC_F12|KEYC_BUILD_MODIFIERS,
278e271dbb8Schristos 	  .data = "\033[24;_~"
279e271dbb8Schristos 	},
280e271dbb8Schristos 	{ .key = KEYC_UP|KEYC_BUILD_MODIFIERS,
281e271dbb8Schristos 	  .data = "\033[1;_A"
282e271dbb8Schristos 	},
283e271dbb8Schristos 	{ .key = KEYC_DOWN|KEYC_BUILD_MODIFIERS,
284e271dbb8Schristos 	  .data = "\033[1;_B"
285e271dbb8Schristos 	},
286e271dbb8Schristos 	{ .key = KEYC_RIGHT|KEYC_BUILD_MODIFIERS,
287e271dbb8Schristos 	  .data = "\033[1;_C"
288e271dbb8Schristos 	},
289e271dbb8Schristos 	{ .key = KEYC_LEFT|KEYC_BUILD_MODIFIERS,
290e271dbb8Schristos 	  .data = "\033[1;_D"
291e271dbb8Schristos 	},
292e271dbb8Schristos 	{ .key = KEYC_HOME|KEYC_BUILD_MODIFIERS,
293e271dbb8Schristos 	  .data = "\033[1;_H"
294e271dbb8Schristos 	},
295e271dbb8Schristos 	{ .key = KEYC_END|KEYC_BUILD_MODIFIERS,
296e271dbb8Schristos 	  .data = "\033[1;_F"
297e271dbb8Schristos 	},
298e271dbb8Schristos 	{ .key = KEYC_PPAGE|KEYC_BUILD_MODIFIERS,
299e271dbb8Schristos 	  .data = "\033[5;_~"
300e271dbb8Schristos 	},
301e271dbb8Schristos 	{ .key = KEYC_NPAGE|KEYC_BUILD_MODIFIERS,
302e271dbb8Schristos 	  .data = "\033[6;_~"
303e271dbb8Schristos 	},
304e271dbb8Schristos 	{ .key = KEYC_IC|KEYC_BUILD_MODIFIERS,
305e271dbb8Schristos 	  .data = "\033[2;_~"
306e271dbb8Schristos 	},
307e271dbb8Schristos 	{ .key = KEYC_DC|KEYC_BUILD_MODIFIERS,
308e271dbb8Schristos 	  .data = "\033[3;_~"
309f844e94eSwiz 	},
310698d5317Sjmmv };
311e271dbb8Schristos static const key_code input_key_modifiers[] = {
312e271dbb8Schristos 	0,
313e271dbb8Schristos 	0,
314e271dbb8Schristos 	KEYC_SHIFT,
315e271dbb8Schristos 	KEYC_META|KEYC_IMPLIED_META,
316e271dbb8Schristos 	KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META,
317e271dbb8Schristos 	KEYC_CTRL,
318e271dbb8Schristos 	KEYC_SHIFT|KEYC_CTRL,
319e271dbb8Schristos 	KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL,
320e271dbb8Schristos 	KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL
321e271dbb8Schristos };
322e271dbb8Schristos 
323e271dbb8Schristos /* Input key comparison function. */
324e271dbb8Schristos static int
325e271dbb8Schristos input_key_cmp(struct input_key_entry *ike1, struct input_key_entry *ike2)
326e271dbb8Schristos {
327e271dbb8Schristos 	if (ike1->key < ike2->key)
328e271dbb8Schristos 		return (-1);
329e271dbb8Schristos 	if (ike1->key > ike2->key)
330e271dbb8Schristos 		return (1);
331e271dbb8Schristos 	return (0);
332e271dbb8Schristos }
333e271dbb8Schristos 
334e271dbb8Schristos /* Look for key in tree. */
335e271dbb8Schristos static struct input_key_entry *
336e271dbb8Schristos input_key_get(key_code key)
337e271dbb8Schristos {
338e271dbb8Schristos 	struct input_key_entry	entry = { .key = key };
339e271dbb8Schristos 
340e271dbb8Schristos 	return (RB_FIND(input_key_tree, &input_key_tree, &entry));
341e271dbb8Schristos }
342698d5317Sjmmv 
343f26e8bc9Schristos /* Split a character into two UTF-8 bytes. */
344f26e8bc9Schristos static size_t
345e271dbb8Schristos input_key_split2(u_int c, char *dst)
346f26e8bc9Schristos {
347f26e8bc9Schristos 	if (c > 0x7f) {
348f26e8bc9Schristos 		dst[0] = (c >> 6) | 0xc0;
349f26e8bc9Schristos 		dst[1] = (c & 0x3f) | 0x80;
350f26e8bc9Schristos 		return (2);
351f26e8bc9Schristos 	}
352f26e8bc9Schristos 	dst[0] = c;
353f26e8bc9Schristos 	return (1);
354f26e8bc9Schristos }
355f26e8bc9Schristos 
356e271dbb8Schristos /* Build input key tree. */
357e271dbb8Schristos void
358e271dbb8Schristos input_key_build(void)
359698d5317Sjmmv {
360e271dbb8Schristos 	struct input_key_entry	*ike, *new;
361e271dbb8Schristos 	u_int			 i, j;
362e271dbb8Schristos 	char			*data;
363e271dbb8Schristos 	key_code		 key;
364698d5317Sjmmv 
365e271dbb8Schristos 	for (i = 0; i < nitems(input_key_defaults); i++) {
366e271dbb8Schristos 		ike = &input_key_defaults[i];
367e271dbb8Schristos 		if (~ike->key & KEYC_BUILD_MODIFIERS) {
368e271dbb8Schristos 			RB_INSERT(input_key_tree, &input_key_tree, ike);
369e271dbb8Schristos 			continue;
370e271dbb8Schristos 		}
371e271dbb8Schristos 
372e271dbb8Schristos 		for (j = 2; j < nitems(input_key_modifiers); j++) {
373e271dbb8Schristos 			key = (ike->key & ~KEYC_BUILD_MODIFIERS);
374e271dbb8Schristos 			data = xstrdup(ike->data);
375e271dbb8Schristos 			data[strcspn(data, "_")] = '0' + j;
376e271dbb8Schristos 
377e271dbb8Schristos 			new = xcalloc(1, sizeof *new);
378e271dbb8Schristos 			new->key = key|input_key_modifiers[j];
379e271dbb8Schristos 			new->data = data;
380e271dbb8Schristos 			RB_INSERT(input_key_tree, &input_key_tree, new);
381e271dbb8Schristos 		}
382e271dbb8Schristos 	}
383e271dbb8Schristos 
384e271dbb8Schristos 	RB_FOREACH(ike, input_key_tree, &input_key_tree) {
385e271dbb8Schristos 		log_debug("%s: 0x%llx (%s) is %s", __func__, ike->key,
386e271dbb8Schristos 		    key_string_lookup_key(ike->key, 1), ike->data);
387e271dbb8Schristos 	}
388e271dbb8Schristos }
389e271dbb8Schristos 
390e271dbb8Schristos /* Translate a key code into an output key sequence for a pane. */
391e271dbb8Schristos int
392e271dbb8Schristos input_key_pane(struct window_pane *wp, key_code key, struct mouse_event *m)
393e271dbb8Schristos {
394e271dbb8Schristos 	if (log_get_level() != 0) {
395f26e8bc9Schristos 		log_debug("writing key 0x%llx (%s) to %%%u", key,
396e271dbb8Schristos 		    key_string_lookup_key(key, 1), wp->id);
397e271dbb8Schristos 	}
39899e242abSchristos 
39999e242abSchristos 	if (KEYC_IS_MOUSE(key)) {
40099e242abSchristos 		if (m != NULL && m->wp != -1 && (u_int)m->wp == wp->id)
40199e242abSchristos 			input_key_mouse(wp, m);
40268e6ba84Schristos 		return (0);
40399e242abSchristos 	}
404e271dbb8Schristos 	return (input_key(wp->screen, wp->event, key));
405e271dbb8Schristos }
406e271dbb8Schristos 
407e271dbb8Schristos static void
408e271dbb8Schristos input_key_write(const char *from, struct bufferevent *bev, const char *data,
409e271dbb8Schristos     size_t size)
410e271dbb8Schristos {
411e271dbb8Schristos 	log_debug("%s: %.*s", from, (int)size, (const char *)data);
412e271dbb8Schristos 	bufferevent_write(bev, data, size);
413e271dbb8Schristos }
414e271dbb8Schristos 
415*890b6d91Swiz /*
416*890b6d91Swiz  * Encode and write an extended key escape sequence in one of the two
417*890b6d91Swiz  * possible formats, depending on the configured output mode.
418*890b6d91Swiz  */
419*890b6d91Swiz static int
420*890b6d91Swiz input_key_extended(struct bufferevent *bev, key_code key)
421e271dbb8Schristos {
422e271dbb8Schristos 	char		 tmp[64], modifier;
423*890b6d91Swiz 	struct utf8_data ud;
424*890b6d91Swiz 	wchar_t		 wc;
425e271dbb8Schristos 
426*890b6d91Swiz 	switch (key & KEYC_MASK_MODIFIERS) {
427e271dbb8Schristos 	case KEYC_SHIFT:
428e271dbb8Schristos 		modifier = '2';
429e271dbb8Schristos 		break;
430e271dbb8Schristos 	case KEYC_META:
431e271dbb8Schristos 		modifier = '3';
432e271dbb8Schristos 		break;
433e271dbb8Schristos 	case KEYC_SHIFT|KEYC_META:
434e271dbb8Schristos 		modifier = '4';
435e271dbb8Schristos 		break;
436e271dbb8Schristos 	case KEYC_CTRL:
437e271dbb8Schristos 		modifier = '5';
438e271dbb8Schristos 		break;
439e271dbb8Schristos 	case KEYC_SHIFT|KEYC_CTRL:
440e271dbb8Schristos 		modifier = '6';
441e271dbb8Schristos 		break;
442e271dbb8Schristos 	case KEYC_META|KEYC_CTRL:
443e271dbb8Schristos 		modifier = '7';
444e271dbb8Schristos 		break;
445e271dbb8Schristos 	case KEYC_SHIFT|KEYC_META|KEYC_CTRL:
446e271dbb8Schristos 		modifier = '8';
447e271dbb8Schristos 		break;
448e271dbb8Schristos 	default:
449*890b6d91Swiz 		return (-1);
450e271dbb8Schristos 	}
451*890b6d91Swiz 
452*890b6d91Swiz 	if (KEYC_IS_UNICODE(key)) {
453*890b6d91Swiz 		utf8_to_data(key & KEYC_MASK_KEY, &ud);
454*890b6d91Swiz 		if (utf8_towc(&ud, &wc) == UTF8_DONE)
455*890b6d91Swiz 			key = wc;
456*890b6d91Swiz 		else
457*890b6d91Swiz 			return (-1);
458*890b6d91Swiz 	} else
459*890b6d91Swiz 		key &= KEYC_MASK_KEY;
460*890b6d91Swiz 
461*890b6d91Swiz 	if (options_get_number(global_options, "extended-keys-format") == 1)
462*890b6d91Swiz 		xsnprintf(tmp, sizeof tmp, "\033[27;%c;%llu~", modifier, key);
463*890b6d91Swiz 	else
464*890b6d91Swiz 		xsnprintf(tmp, sizeof tmp, "\033[%llu;%cu", key, modifier);
465*890b6d91Swiz 
466e271dbb8Schristos 	input_key_write(__func__, bev, tmp, strlen(tmp));
467e271dbb8Schristos 	return (0);
468*890b6d91Swiz }
469e271dbb8Schristos 
470*890b6d91Swiz /*
471*890b6d91Swiz  * Outputs the key in the "standard" mode. This is by far the most
472*890b6d91Swiz  * complicated output mode, with a lot of remapping in order to
473*890b6d91Swiz  * emulate quirks of terminals that today can be only found in museums.
474*890b6d91Swiz  */
475*890b6d91Swiz static int
476*890b6d91Swiz input_key_vt10x(struct bufferevent *bev, key_code key)
477*890b6d91Swiz {
478*890b6d91Swiz 	struct utf8_data	 ud;
479*890b6d91Swiz 	key_code		 onlykey;
480*890b6d91Swiz 	char			*p;
481*890b6d91Swiz 	static const char	*standard_map[2] = {
482*890b6d91Swiz 		"1!9(0)=+;:'\",<.>/-8? 2",
483*890b6d91Swiz 		"119900=+;;'',,..\x1f\x1f\x7f\x7f\0\0",
484*890b6d91Swiz 	};
485*890b6d91Swiz 
486*890b6d91Swiz 	log_debug("%s: key in %llx", __func__, key);
487*890b6d91Swiz 
488*890b6d91Swiz 	if (key & KEYC_META)
489*890b6d91Swiz 		input_key_write(__func__, bev, "\033", 1);
490*890b6d91Swiz 
491*890b6d91Swiz 	/*
492*890b6d91Swiz 	 * There's no way to report modifiers for unicode keys in standard mode
493*890b6d91Swiz 	 * so lose the modifiers.
494*890b6d91Swiz 	 */
495*890b6d91Swiz 	if (KEYC_IS_UNICODE(key)) {
496*890b6d91Swiz 		utf8_to_data(key, &ud);
497*890b6d91Swiz                 input_key_write(__func__, bev, (const char *)ud.data, ud.size);
498*890b6d91Swiz 		return (0);
499*890b6d91Swiz 	}
500*890b6d91Swiz 
501*890b6d91Swiz 	/* Prevent TAB and RET from being swallowed by C0 remapping logic. */
502*890b6d91Swiz 	onlykey = key & KEYC_MASK_KEY;
503*890b6d91Swiz 	if (onlykey == '\r' || onlykey == '\t')
504*890b6d91Swiz 		key &= ~KEYC_CTRL;
505*890b6d91Swiz 
506*890b6d91Swiz 	/*
507*890b6d91Swiz 	 * Convert keys with Ctrl modifier into corresponding C0 control codes,
508*890b6d91Swiz 	 * with the exception of *some* keys, which are remapped into printable
509*890b6d91Swiz 	 * ASCII characters.
510*890b6d91Swiz 	 *
511*890b6d91Swiz 	 * There is no special handling for Shift modifier, which is pretty
512*890b6d91Swiz 	 * much redundant anyway, as no terminal will send <base key>|SHIFT,
513*890b6d91Swiz 	 * but only <shifted key>|SHIFT.
514*890b6d91Swiz 	 */
515*890b6d91Swiz 	if (key & KEYC_CTRL) {
516*890b6d91Swiz 		p = strchr(standard_map[0], onlykey);
517*890b6d91Swiz 		if (p != NULL)
518*890b6d91Swiz 			key = standard_map[1][p - standard_map[0]];
519*890b6d91Swiz 		else if (onlykey >= '3' && onlykey <= '7')
520*890b6d91Swiz 			key = onlykey - '\030';
521*890b6d91Swiz 		else if (onlykey >= '@' && onlykey <= '~')
522*890b6d91Swiz 			key = onlykey & 0x1f;
523*890b6d91Swiz 		else
52468e6ba84Schristos 			return (-1);
525698d5317Sjmmv 	}
526698d5317Sjmmv 
527*890b6d91Swiz 	log_debug("%s: key out %llx", __func__, key);
528*890b6d91Swiz 
529*890b6d91Swiz 	ud.data[0] = key & 0x7f;
530*890b6d91Swiz 	input_key_write(__func__, bev, (const char *)&ud.data[0], 1);
531*890b6d91Swiz 	return (0);
532*890b6d91Swiz }
533*890b6d91Swiz 
534*890b6d91Swiz /* Pick keys that are reported as vt10x keys in modifyOtherKeys=1 mode. */
535*890b6d91Swiz static int
536*890b6d91Swiz input_key_mode1(struct bufferevent *bev, key_code key)
537*890b6d91Swiz {
538*890b6d91Swiz 	key_code	 onlykey;
539*890b6d91Swiz 
540*890b6d91Swiz 	log_debug("%s: key in %llx", __func__, key);
541*890b6d91Swiz 
542*890b6d91Swiz 	/*
543*890b6d91Swiz 	 * As per
544*890b6d91Swiz 	 * https://invisible-island.net/xterm/modified-keys-us-pc105.html.
545*890b6d91Swiz 	 */
546*890b6d91Swiz 	onlykey = key & KEYC_MASK_KEY;
547*890b6d91Swiz 	if ((key & (KEYC_META | KEYC_CTRL)) == KEYC_CTRL &&
548*890b6d91Swiz 	    (onlykey == ' ' ||
549*890b6d91Swiz 	     onlykey == '/' ||
550*890b6d91Swiz 	     onlykey == '@' ||
551*890b6d91Swiz 	     onlykey == '^' ||
552*890b6d91Swiz 	     (onlykey >= '2' && onlykey <= '8') ||
553*890b6d91Swiz 	     (onlykey >= '@' && onlykey <= '~')))
554*890b6d91Swiz 		return (input_key_vt10x(bev, key));
555*890b6d91Swiz 
556*890b6d91Swiz 	/*
557*890b6d91Swiz 	 * A regular key + Meta. In the absence of a standard to back this, we
558*890b6d91Swiz 	 * mimic what iTerm 2 does.
559*890b6d91Swiz 	 */
560*890b6d91Swiz 	if ((key & (KEYC_CTRL | KEYC_META)) == KEYC_META)
561*890b6d91Swiz 		return (input_key_vt10x(bev, key));
562*890b6d91Swiz 
563*890b6d91Swiz 	return (-1);
564*890b6d91Swiz }
565*890b6d91Swiz 
566*890b6d91Swiz /* Translate a key code into an output key sequence. */
567*890b6d91Swiz int
568*890b6d91Swiz input_key(struct screen *s, struct bufferevent *bev, key_code key)
569*890b6d91Swiz {
570*890b6d91Swiz 	struct input_key_entry	*ike = NULL;
571*890b6d91Swiz 	key_code		 newkey;
572*890b6d91Swiz 	struct utf8_data	 ud;
573*890b6d91Swiz 
574*890b6d91Swiz 	/* Mouse keys need a pane. */
575*890b6d91Swiz 	if (KEYC_IS_MOUSE(key))
576*890b6d91Swiz 		return (0);
577*890b6d91Swiz 
578*890b6d91Swiz 	/* Literal keys go as themselves (can't be more than eight bits). */
579*890b6d91Swiz 	if (key & KEYC_LITERAL) {
580*890b6d91Swiz 		ud.data[0] = (u_char)key;
581*890b6d91Swiz 		input_key_write(__func__, bev, (const char *)ud.data, 1);
582*890b6d91Swiz 		return (0);
583*890b6d91Swiz 	}
584*890b6d91Swiz 
585*890b6d91Swiz 	/* Is this backspace? */
586*890b6d91Swiz 	if ((key & KEYC_MASK_KEY) == KEYC_BSPACE) {
587*890b6d91Swiz 		newkey = options_get_number(global_options, "backspace");
588*890b6d91Swiz 		if (newkey >= 0x7f)
589*890b6d91Swiz 			newkey = '\177';
590*890b6d91Swiz 		key = newkey|(key & (KEYC_MASK_MODIFIERS|KEYC_MASK_FLAGS));
591*890b6d91Swiz 	}
592*890b6d91Swiz 
593*890b6d91Swiz 	/* Is this backtab? */
594*890b6d91Swiz 	if ((key & KEYC_MASK_KEY) == KEYC_BTAB) {
595*890b6d91Swiz 		if ((s->mode & EXTENDED_KEY_MODES) != 0) {
596*890b6d91Swiz 			/* When in xterm extended mode, remap into S-Tab. */
597*890b6d91Swiz 			key = '\011' | (key & ~KEYC_MASK_KEY) | KEYC_SHIFT;
598*890b6d91Swiz 		} else {
599*890b6d91Swiz 			/* Otherwise clear modifiers. */
600*890b6d91Swiz 			key &= ~KEYC_MASK_MODIFIERS;
601*890b6d91Swiz 		}
602*890b6d91Swiz 	}
603*890b6d91Swiz 
604*890b6d91Swiz 	/*
605*890b6d91Swiz 	 * A trivial case, that is a 7-bit key, excluding C0 control characters
606*890b6d91Swiz 	 * that can't be entered from the keyboard, and no modifiers; or a UTF-8
607*890b6d91Swiz 	 * key and no modifiers.
608*890b6d91Swiz 	 */
609*890b6d91Swiz 	if (!(key & ~KEYC_MASK_KEY)) {
610*890b6d91Swiz 		if (key == C0_HT ||
611*890b6d91Swiz 		    key == C0_CR ||
612*890b6d91Swiz 		    key == C0_ESC ||
613*890b6d91Swiz 		    (key >= 0x20 && key <= 0x7f)) {
614*890b6d91Swiz 			ud.data[0] = key;
615*890b6d91Swiz 			input_key_write(__func__, bev, (const char *)&ud.data[0], 1);
616*890b6d91Swiz 			return (0);
617*890b6d91Swiz 		}
618*890b6d91Swiz 		if (KEYC_IS_UNICODE(key)) {
619*890b6d91Swiz 			utf8_to_data(key, &ud);
620*890b6d91Swiz 			input_key_write(__func__, bev, (const char *)ud.data, ud.size);
621*890b6d91Swiz 			return (0);
622*890b6d91Swiz 		}
623*890b6d91Swiz 	}
624*890b6d91Swiz 
625*890b6d91Swiz 	/*
626*890b6d91Swiz 	 * Look up the standard VT10x keys in the tree. If not in application
627*890b6d91Swiz 	 * keypad or cursor mode, remove the respective flags from the key.
628*890b6d91Swiz 	 */
629*890b6d91Swiz 	if (~s->mode & MODE_KKEYPAD)
630*890b6d91Swiz 		key &= ~KEYC_KEYPAD;
631*890b6d91Swiz 	if (~s->mode & MODE_KCURSOR)
632*890b6d91Swiz 		key &= ~KEYC_CURSOR;
633*890b6d91Swiz 	if (ike == NULL)
634*890b6d91Swiz 		ike = input_key_get(key);
635*890b6d91Swiz 	if (ike == NULL && (key & KEYC_META) && (~key & KEYC_IMPLIED_META))
636*890b6d91Swiz 		ike = input_key_get(key & ~KEYC_META);
637*890b6d91Swiz 	if (ike == NULL && (key & KEYC_CURSOR))
638*890b6d91Swiz 		ike = input_key_get(key & ~KEYC_CURSOR);
639*890b6d91Swiz 	if (ike == NULL && (key & KEYC_KEYPAD))
640*890b6d91Swiz 		ike = input_key_get(key & ~KEYC_KEYPAD);
641*890b6d91Swiz 	if (ike != NULL) {
642*890b6d91Swiz 		log_debug("%s: found key 0x%llx: \"%s\"", __func__, key,
643*890b6d91Swiz 		    ike->data);
644*890b6d91Swiz 		if ((key == KEYC_PASTE_START || key == KEYC_PASTE_END) &&
645*890b6d91Swiz 		    (~s->mode & MODE_BRACKETPASTE))
646*890b6d91Swiz 			return (0);
647*890b6d91Swiz 		if ((key & KEYC_META) && (~key & KEYC_IMPLIED_META))
648*890b6d91Swiz 			input_key_write(__func__, bev, "\033", 1);
649*890b6d91Swiz 		input_key_write(__func__, bev, ike->data, strlen(ike->data));
650*890b6d91Swiz 		return (0);
651*890b6d91Swiz 	}
652*890b6d91Swiz 
653*890b6d91Swiz 	/* Ignore internal function key codes. */
654*890b6d91Swiz 	if ((key >= KEYC_BASE && key < KEYC_BASE_END) ||
655*890b6d91Swiz 	    (key >= KEYC_USER && key < KEYC_USER_END)) {
656*890b6d91Swiz 		log_debug("%s: ignoring key 0x%llx", __func__, key);
657*890b6d91Swiz 		return (0);
658*890b6d91Swiz 	}
659*890b6d91Swiz 
660*890b6d91Swiz 	/*
661*890b6d91Swiz 	 * No builtin key sequence; construct an extended key sequence
662*890b6d91Swiz 	 * depending on the client mode.
663*890b6d91Swiz 	 *
664*890b6d91Swiz 	 * If something invalid reaches here, an invalid output may be
665*890b6d91Swiz 	 * produced. For example Ctrl-Shift-2 is invalid (as there's
666*890b6d91Swiz 	 * no way to enter it). The correct form is Ctrl-Shift-@, at
667*890b6d91Swiz 	 * least in US English keyboard layout.
668*890b6d91Swiz 	 */
669*890b6d91Swiz 	switch (s->mode & EXTENDED_KEY_MODES) {
670*890b6d91Swiz 	case MODE_KEYS_EXTENDED_2:
671*890b6d91Swiz 		/*
672*890b6d91Swiz 		 * The simplest mode to handle - *all* modified keys are
673*890b6d91Swiz 		 * reported in the extended form.
674*890b6d91Swiz 		 */
675*890b6d91Swiz 		return (input_key_extended(bev, key));
676*890b6d91Swiz         case MODE_KEYS_EXTENDED:
677*890b6d91Swiz 		/*
678*890b6d91Swiz 		 * Some keys are still reported in standard mode, to maintain
679*890b6d91Swiz 		 * compatibility with applications unaware of extended keys.
680*890b6d91Swiz 		 */
681*890b6d91Swiz 		if (input_key_mode1(bev, key) == -1)
682*890b6d91Swiz 			return (input_key_extended(bev, key));
683*890b6d91Swiz 		return (0);
684*890b6d91Swiz 	default:
685*890b6d91Swiz 		/* The standard mode. */
686*890b6d91Swiz 		return (input_key_vt10x(bev, key));
687*890b6d91Swiz 	}
688*890b6d91Swiz }
689*890b6d91Swiz 
690e271dbb8Schristos /* Get mouse event string. */
691e271dbb8Schristos int
692e271dbb8Schristos input_key_get_mouse(struct screen *s, struct mouse_event *m, u_int x, u_int y,
693e271dbb8Schristos     const char **rbuf, size_t *rlen)
694698d5317Sjmmv {
695e271dbb8Schristos 	static char	 buf[40];
696d530c4d0Sjmmv 	size_t		 len;
697698d5317Sjmmv 
698e271dbb8Schristos 	*rbuf = NULL;
699e271dbb8Schristos 	*rlen = 0;
70099e242abSchristos 
701e9a2d6faSchristos 	/* If this pane is not in button or all mode, discard motion events. */
702e271dbb8Schristos 	if (MOUSE_DRAG(m->b) && (s->mode & MOTION_MOUSE_MODES) == 0)
703e271dbb8Schristos 		return (0);
704e271dbb8Schristos 	if ((s->mode & ALL_MOUSE_MODES) == 0)
705e271dbb8Schristos 		return (0);
70699e242abSchristos 
70761fba46bSchristos 	/*
708e9a2d6faSchristos 	 * If this event is a release event and not in all mode, discard it.
709e9a2d6faSchristos 	 * In SGR mode we can tell absolutely because a release is normally
710e9a2d6faSchristos 	 * shown by the last character. Without SGR, we check if the last
711e9a2d6faSchristos 	 * buttons was also a release.
712e9a2d6faSchristos 	 */
713e9a2d6faSchristos 	if (m->sgr_type != ' ') {
714e9a2d6faSchristos 		if (MOUSE_DRAG(m->sgr_b) &&
71546548964Swiz 		    MOUSE_RELEASE(m->sgr_b) &&
716e271dbb8Schristos 		    (~s->mode & MODE_MOUSE_ALL))
717e271dbb8Schristos 			return (0);
718e9a2d6faSchristos 	} else {
719e9a2d6faSchristos 		if (MOUSE_DRAG(m->b) &&
72046548964Swiz 		    MOUSE_RELEASE(m->b) &&
72146548964Swiz 		    MOUSE_RELEASE(m->lb) &&
722e271dbb8Schristos 		    (~s->mode & MODE_MOUSE_ALL))
723e271dbb8Schristos 			return (0);
724e9a2d6faSchristos 	}
725e9a2d6faSchristos 
726e9a2d6faSchristos 	/*
72799e242abSchristos 	 * Use the SGR (1006) extension only if the application requested it
72899e242abSchristos 	 * and the underlying terminal also sent the event in this format (this
72999e242abSchristos 	 * is because an old style mouse release event cannot be converted into
73099e242abSchristos 	 * the new SGR format, since the released button is unknown). Otherwise
73199e242abSchristos 	 * pretend that tmux doesn't speak this extension, and fall back to the
73299e242abSchristos 	 * UTF-8 (1005) extension if the application requested, or to the
73361fba46bSchristos 	 * legacy format.
73461fba46bSchristos 	 */
735e9a2d6faSchristos 	if (m->sgr_type != ' ' && (s->mode & MODE_MOUSE_SGR)) {
736e9a2d6faSchristos 		len = xsnprintf(buf, sizeof buf, "\033[<%u;%u;%u%c",
73799e242abSchristos 		    m->sgr_b, x + 1, y + 1, m->sgr_type);
738e9a2d6faSchristos 	} else if (s->mode & MODE_MOUSE_UTF8) {
73946548964Swiz 		if (m->b > MOUSE_PARAM_UTF8_MAX - MOUSE_PARAM_BTN_OFF ||
74046548964Swiz 		    x > MOUSE_PARAM_UTF8_MAX - MOUSE_PARAM_POS_OFF ||
74146548964Swiz 		    y > MOUSE_PARAM_UTF8_MAX - MOUSE_PARAM_POS_OFF)
742e271dbb8Schristos 			return (0);
743e271dbb8Schristos 		len = xsnprintf(buf, sizeof buf, "\033[M");
74446548964Swiz 		len += input_key_split2(m->b + MOUSE_PARAM_BTN_OFF, &buf[len]);
74546548964Swiz 		len += input_key_split2(x + MOUSE_PARAM_POS_OFF, &buf[len]);
74646548964Swiz 		len += input_key_split2(y + MOUSE_PARAM_POS_OFF, &buf[len]);
747d530c4d0Sjmmv 	} else {
74846548964Swiz 		if (m->b + MOUSE_PARAM_BTN_OFF > MOUSE_PARAM_MAX)
749e271dbb8Schristos 			return (0);
75046548964Swiz 
751e271dbb8Schristos 		len = xsnprintf(buf, sizeof buf, "\033[M");
75246548964Swiz 		buf[len++] = m->b + MOUSE_PARAM_BTN_OFF;
75346548964Swiz 
75446548964Swiz 		/*
75546548964Swiz 		 * The incoming x and y may be out of the range which can be
75646548964Swiz 		 * supported by the "normal" mouse protocol. Clamp the
75746548964Swiz 		 * coordinates to the supported range.
75846548964Swiz 		 */
75946548964Swiz 		if (x + MOUSE_PARAM_POS_OFF > MOUSE_PARAM_MAX)
76046548964Swiz 			buf[len++] = MOUSE_PARAM_MAX;
76146548964Swiz 		else
76246548964Swiz 			buf[len++] = x + MOUSE_PARAM_POS_OFF;
76346548964Swiz 		if (y + MOUSE_PARAM_POS_OFF > MOUSE_PARAM_MAX)
76446548964Swiz 			buf[len++] = MOUSE_PARAM_MAX;
76546548964Swiz 		else
76646548964Swiz 			buf[len++] = y + MOUSE_PARAM_POS_OFF;
767d530c4d0Sjmmv 	}
768e271dbb8Schristos 
769e271dbb8Schristos 	*rbuf = buf;
770e271dbb8Schristos 	*rlen = len;
771e271dbb8Schristos 	return (1);
772e271dbb8Schristos }
773e271dbb8Schristos 
774e271dbb8Schristos /* Translate mouse and output. */
775e271dbb8Schristos static void
776e271dbb8Schristos input_key_mouse(struct window_pane *wp, struct mouse_event *m)
777e271dbb8Schristos {
778e271dbb8Schristos 	struct screen	*s = wp->screen;
779e271dbb8Schristos 	u_int		 x, y;
780e271dbb8Schristos 	const char	*buf;
781e271dbb8Schristos 	size_t		 len;
782e271dbb8Schristos 
783e271dbb8Schristos 	/* Ignore events if no mouse mode or the pane is not visible. */
784e271dbb8Schristos 	if (m->ignore || (s->mode & ALL_MOUSE_MODES) == 0)
785e271dbb8Schristos 		return;
786e271dbb8Schristos 	if (cmd_mouse_at(wp, m, &x, &y, 0) != 0)
787e271dbb8Schristos 		return;
788e271dbb8Schristos 	if (!window_pane_visible(wp))
789e271dbb8Schristos 		return;
790e271dbb8Schristos 	if (!input_key_get_mouse(s, m, x, y, &buf, &len))
791e271dbb8Schristos 		return;
792f26e8bc9Schristos 	log_debug("writing mouse %.*s to %%%u", (int)len, buf, wp->id);
793e271dbb8Schristos 	input_key_write(__func__, wp->event, buf, len);
794698d5317Sjmmv }
795