4 * Copyright (c) 2009 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>
20 #include <sys/ioctl.h>
35 static void server_client_free(int, short, void *);
36 static void server_client_check_pane_resize(struct window_pane
*);
37 static void server_client_check_pane_buffer(struct window_pane
*);
38 static void server_client_check_window_resize(struct window
*);
39 static key_code
server_client_check_mouse(struct client
*, struct key_event
*);
40 static void server_client_repeat_timer(int, short, void *);
41 static void server_client_click_timer(int, short, void *);
42 static void server_client_check_exit(struct client
*);
43 static void server_client_check_redraw(struct client
*);
44 static void server_client_check_modes(struct client
*);
45 static void server_client_set_title(struct client
*);
46 static void server_client_set_path(struct client
*);
47 static void server_client_reset_state(struct client
*);
48 static int server_client_assume_paste(struct session
*);
49 static void server_client_update_latest(struct client
*);
51 static void server_client_dispatch(struct imsg
*, void *);
52 static void server_client_dispatch_command(struct client
*, struct imsg
*);
53 static void server_client_dispatch_identify(struct client
*, struct imsg
*);
54 static void server_client_dispatch_shell(struct client
*);
56 /* Compare client windows. */
58 server_client_window_cmp(struct client_window
*cw1
,
59 struct client_window
*cw2
)
61 if (cw1
->window
< cw2
->window
)
63 if (cw1
->window
> cw2
->window
)
67 RB_GENERATE(client_windows
, client_window
, entry
, server_client_window_cmp
);
69 /* Number of attached clients. */
71 server_client_how_many(void)
77 TAILQ_FOREACH(c
, &clients
, entry
) {
78 if (c
->session
!= NULL
&& (~c
->flags
& CLIENT_UNATTACHEDFLAGS
))
84 /* Overlay timer callback. */
86 server_client_overlay_timer(__unused
int fd
, __unused
short events
, void *data
)
88 server_client_clear_overlay(data
);
91 /* Set an overlay on client. */
93 server_client_set_overlay(struct client
*c
, u_int delay
,
94 overlay_check_cb checkcb
, overlay_mode_cb modecb
,
95 overlay_draw_cb drawcb
, overlay_key_cb keycb
, overlay_free_cb freecb
,
96 overlay_resize_cb resizecb
, void *data
)
100 if (c
->overlay_draw
!= NULL
)
101 server_client_clear_overlay(c
);
103 tv
.tv_sec
= delay
/ 1000;
104 tv
.tv_usec
= (delay
% 1000) * 1000L;
106 if (event_initialized(&c
->overlay_timer
))
107 evtimer_del(&c
->overlay_timer
);
108 evtimer_set(&c
->overlay_timer
, server_client_overlay_timer
, c
);
110 evtimer_add(&c
->overlay_timer
, &tv
);
112 c
->overlay_check
= checkcb
;
113 c
->overlay_mode
= modecb
;
114 c
->overlay_draw
= drawcb
;
115 c
->overlay_key
= keycb
;
116 c
->overlay_free
= freecb
;
117 c
->overlay_resize
= resizecb
;
118 c
->overlay_data
= data
;
120 if (c
->overlay_check
== NULL
)
121 c
->tty
.flags
|= TTY_FREEZE
;
122 if (c
->overlay_mode
== NULL
)
123 c
->tty
.flags
|= TTY_NOCURSOR
;
124 server_redraw_client(c
);
127 /* Clear overlay mode on client. */
129 server_client_clear_overlay(struct client
*c
)
131 if (c
->overlay_draw
== NULL
)
134 if (event_initialized(&c
->overlay_timer
))
135 evtimer_del(&c
->overlay_timer
);
137 if (c
->overlay_free
!= NULL
)
138 c
->overlay_free(c
, c
->overlay_data
);
140 c
->overlay_check
= NULL
;
141 c
->overlay_mode
= NULL
;
142 c
->overlay_draw
= NULL
;
143 c
->overlay_key
= NULL
;
144 c
->overlay_free
= NULL
;
145 c
->overlay_data
= NULL
;
147 c
->tty
.flags
&= ~(TTY_FREEZE
|TTY_NOCURSOR
);
148 server_redraw_client(c
);
152 * Given overlay position and dimensions, return parts of the input range which
156 server_client_overlay_range(u_int x
, u_int y
, u_int sx
, u_int sy
, u_int px
,
157 u_int py
, u_int nx
, struct overlay_ranges
*r
)
161 /* Return up to 2 ranges. */
165 /* Trivial case of no overlap in the y direction. */
166 if (py
< y
|| py
> y
+ sy
- 1) {
174 /* Visible bit to the left of the popup. */
185 /* Visible bit to the right of the popup. */
199 /* Check if this client is inside this server. */
201 server_client_check_nested(struct client
*c
)
203 struct environ_entry
*envent
;
204 struct window_pane
*wp
;
206 envent
= environ_find(c
->environ
, "TMUX");
207 if (envent
== NULL
|| *envent
->value
== '\0')
210 RB_FOREACH(wp
, window_pane_tree
, &all_window_panes
) {
211 if (strcmp(wp
->tty
, c
->ttyname
) == 0)
217 /* Set client key table. */
219 server_client_set_key_table(struct client
*c
, const char *name
)
222 name
= server_client_get_key_table(c
);
224 key_bindings_unref_table(c
->keytable
);
225 c
->keytable
= key_bindings_get_table(name
, 1);
226 c
->keytable
->references
++;
229 /* Get default key table. */
231 server_client_get_key_table(struct client
*c
)
233 struct session
*s
= c
->session
;
239 name
= options_get_string(s
->options
, "key-table");
245 /* Is this table the default key table? */
247 server_client_is_default_key_table(struct client
*c
, struct key_table
*table
)
249 return (strcmp(table
->name
, server_client_get_key_table(c
)) == 0);
252 /* Create a new client. */
254 server_client_create(int fd
)
260 c
= xcalloc(1, sizeof *c
);
262 c
->peer
= proc_add_peer(server_proc
, fd
, server_client_dispatch
, c
);
264 if (gettimeofday(&c
->creation_time
, NULL
) != 0)
265 fatal("gettimeofday failed");
266 memcpy(&c
->activity_time
, &c
->creation_time
, sizeof c
->activity_time
);
268 c
->environ
= environ_create();
273 c
->queue
= cmdq_new();
274 RB_INIT(&c
->windows
);
281 c
->flags
|= CLIENT_FOCUSED
;
283 c
->keytable
= key_bindings_get_table("root", 1);
284 c
->keytable
->references
++;
286 evtimer_set(&c
->repeat_timer
, server_client_repeat_timer
, c
);
287 evtimer_set(&c
->click_timer
, server_client_click_timer
, c
);
289 TAILQ_INSERT_TAIL(&clients
, c
, entry
);
290 log_debug("new client %p", c
);
294 /* Open client terminal if needed. */
296 server_client_open(struct client
*c
, char **cause
)
298 const char *ttynam
= _PATH_TTY
;
300 if (c
->flags
& CLIENT_CONTROL
)
303 if (strcmp(c
->ttyname
, ttynam
) == 0||
304 ((isatty(STDIN_FILENO
) &&
305 (ttynam
= ttyname(STDIN_FILENO
)) != NULL
&&
306 strcmp(c
->ttyname
, ttynam
) == 0) ||
307 (isatty(STDOUT_FILENO
) &&
308 (ttynam
= ttyname(STDOUT_FILENO
)) != NULL
&&
309 strcmp(c
->ttyname
, ttynam
) == 0) ||
310 (isatty(STDERR_FILENO
) &&
311 (ttynam
= ttyname(STDERR_FILENO
)) != NULL
&&
312 strcmp(c
->ttyname
, ttynam
) == 0))) {
313 xasprintf(cause
, "can't use %s", c
->ttyname
);
317 if (!(c
->flags
& CLIENT_TERMINAL
)) {
318 *cause
= xstrdup("not a terminal");
322 if (tty_open(&c
->tty
, cause
) != 0)
328 /* Lost an attached client. */
330 server_client_attached_lost(struct client
*c
)
335 struct client
*found
;
337 log_debug("lost attached client %p", c
);
340 * By this point the session in the client has been cleared so walk all
341 * windows to find any with this client as the latest.
343 RB_FOREACH(w
, windows
, &windows
) {
348 TAILQ_FOREACH(loop
, &clients
, entry
) {
350 if (loop
== c
|| s
== NULL
|| s
->curw
->window
!= w
)
352 if (found
== NULL
|| timercmp(&loop
->activity_time
,
353 &found
->activity_time
, >))
357 server_client_update_latest(found
);
361 /* Set client session. */
363 server_client_set_session(struct client
*c
, struct session
*s
)
365 struct session
*old
= c
->session
;
367 if (s
!= NULL
&& c
->session
!= NULL
&& c
->session
!= s
)
368 c
->last_session
= c
->session
;
370 c
->last_session
= NULL
;
372 c
->flags
|= CLIENT_FOCUSED
;
374 if (old
!= NULL
&& old
->curw
!= NULL
)
375 window_update_focus(old
->curw
->window
);
378 window_update_focus(s
->curw
->window
);
379 session_update_activity(s
, NULL
);
380 gettimeofday(&s
->last_attached_time
, NULL
);
381 s
->curw
->flags
&= ~WINLINK_ALERTFLAGS
;
382 s
->curw
->window
->latest
= c
;
383 alerts_check_session(s
);
384 tty_update_client_offset(c
);
385 status_timer_start(c
);
386 notify_client("client-session-changed", c
);
387 server_redraw_client(c
);
390 server_check_unattached();
391 server_update_socket();
396 server_client_lost(struct client
*c
)
398 struct client_file
*cf
, *cf1
;
399 struct client_window
*cw
, *cw1
;
401 c
->flags
|= CLIENT_DEAD
;
403 server_client_clear_overlay(c
);
404 status_prompt_clear(c
);
405 status_message_clear(c
);
407 RB_FOREACH_SAFE(cf
, client_files
, &c
->files
, cf1
) {
411 RB_FOREACH_SAFE(cw
, client_windows
, &c
->windows
, cw1
) {
412 RB_REMOVE(client_windows
, &c
->windows
, cw
);
416 TAILQ_REMOVE(&clients
, c
, entry
);
417 log_debug("lost client %p", c
);
419 if (c
->flags
& CLIENT_ATTACHED
) {
420 server_client_attached_lost(c
);
421 notify_client("client-detached", c
);
424 if (c
->flags
& CLIENT_CONTROL
)
426 if (c
->flags
& CLIENT_TERMINAL
)
429 free(c
->clipboard_panes
);
433 tty_term_free_list(c
->term_caps
, c
->term_ncaps
);
438 free((void *)c
->cwd
);
440 evtimer_del(&c
->repeat_timer
);
441 evtimer_del(&c
->click_timer
);
443 key_bindings_unref_table(c
->keytable
);
445 free(c
->message_string
);
446 if (event_initialized(&c
->message_timer
))
447 evtimer_del(&c
->message_timer
);
449 free(c
->prompt_saved
);
450 free(c
->prompt_string
);
451 free(c
->prompt_buffer
);
453 format_lost_client(c
);
454 environ_free(c
->environ
);
456 proc_remove_peer(c
->peer
);
465 server_client_unref(c
);
467 server_add_accept(0); /* may be more file descriptors now */
470 server_check_unattached();
471 server_update_socket();
474 /* Remove reference from a client. */
476 server_client_unref(struct client
*c
)
478 log_debug("unref client %p (%d references)", c
, c
->references
);
481 if (c
->references
== 0)
482 event_once(-1, EV_TIMEOUT
, server_client_free
, c
, NULL
);
485 /* Free dead client. */
487 server_client_free(__unused
int fd
, __unused
short events
, void *arg
)
489 struct client
*c
= arg
;
491 log_debug("free client %p (%d references)", c
, c
->references
);
495 if (c
->references
== 0) {
496 free((void *)c
->name
);
501 /* Suspend a client. */
503 server_client_suspend(struct client
*c
)
505 struct session
*s
= c
->session
;
507 if (s
== NULL
|| (c
->flags
& CLIENT_UNATTACHEDFLAGS
))
510 tty_stop_tty(&c
->tty
);
511 c
->flags
|= CLIENT_SUSPENDED
;
512 proc_send(c
->peer
, MSG_SUSPEND
, -1, NULL
, 0);
515 /* Detach a client. */
517 server_client_detach(struct client
*c
, enum msgtype msgtype
)
519 struct session
*s
= c
->session
;
521 if (s
== NULL
|| (c
->flags
& CLIENT_NODETACHFLAGS
))
524 c
->flags
|= CLIENT_EXIT
;
526 c
->exit_type
= CLIENT_EXIT_DETACH
;
527 c
->exit_msgtype
= msgtype
;
528 c
->exit_session
= xstrdup(s
->name
);
531 /* Execute command to replace a client. */
533 server_client_exec(struct client
*c
, const char *cmd
)
535 struct session
*s
= c
->session
;
538 size_t cmdsize
, shellsize
;
542 cmdsize
= strlen(cmd
) + 1;
545 shell
= options_get_string(s
->options
, "default-shell");
547 shell
= options_get_string(global_s_options
, "default-shell");
548 if (!checkshell(shell
))
549 shell
= _PATH_BSHELL
;
550 shellsize
= strlen(shell
) + 1;
552 msg
= xmalloc(cmdsize
+ shellsize
);
553 memcpy(msg
, cmd
, cmdsize
);
554 memcpy(msg
+ cmdsize
, shell
, shellsize
);
556 proc_send(c
->peer
, MSG_EXEC
, -1, msg
, cmdsize
+ shellsize
);
560 /* Check for mouse keys. */
562 server_client_check_mouse(struct client
*c
, struct key_event
*event
)
564 struct mouse_event
*m
= &event
->m
;
565 struct session
*s
= c
->session
;
567 struct window_pane
*wp
;
568 u_int x
, y
, b
, sx
, sy
, px
, py
;
572 struct style_range
*sr
;
581 TRIPLE
} type
= NOTYPE
;
588 BORDER
} where
= NOWHERE
;
590 log_debug("%s mouse %02x at %u,%u (last %u,%u) (%d)", c
->name
, m
->b
,
591 m
->x
, m
->y
, m
->lx
, m
->ly
, c
->tty
.mouse_drag_flag
);
593 /* What type of event is this? */
594 if (event
->key
== KEYC_DOUBLECLICK
) {
596 x
= m
->x
, y
= m
->y
, b
= m
->b
;
598 log_debug("double-click at %u,%u", x
, y
);
599 } else if ((m
->sgr_type
!= ' ' &&
600 MOUSE_DRAG(m
->sgr_b
) &&
601 MOUSE_RELEASE(m
->sgr_b
)) ||
602 (m
->sgr_type
== ' ' &&
604 MOUSE_RELEASE(m
->b
) &&
605 MOUSE_RELEASE(m
->lb
))) {
607 x
= m
->x
, y
= m
->y
, b
= 0;
608 log_debug("move at %u,%u", x
, y
);
609 } else if (MOUSE_DRAG(m
->b
)) {
611 if (c
->tty
.mouse_drag_flag
) {
612 x
= m
->x
, y
= m
->y
, b
= m
->b
;
613 if (x
== m
->lx
&& y
== m
->ly
)
614 return (KEYC_UNKNOWN
);
615 log_debug("drag update at %u,%u", x
, y
);
617 x
= m
->lx
, y
= m
->ly
, b
= m
->lb
;
618 log_debug("drag start at %u,%u", x
, y
);
620 } else if (MOUSE_WHEEL(m
->b
)) {
622 x
= m
->x
, y
= m
->y
, b
= m
->b
;
623 log_debug("wheel at %u,%u", x
, y
);
624 } else if (MOUSE_RELEASE(m
->b
)) {
626 x
= m
->x
, y
= m
->y
, b
= m
->lb
;
627 log_debug("up at %u,%u", x
, y
);
629 if (c
->flags
& CLIENT_DOUBLECLICK
) {
630 evtimer_del(&c
->click_timer
);
631 c
->flags
&= ~CLIENT_DOUBLECLICK
;
632 if (m
->b
== c
->click_button
) {
634 x
= m
->x
, y
= m
->y
, b
= m
->b
;
635 log_debug("second-click at %u,%u", x
, y
);
636 c
->flags
|= CLIENT_TRIPLECLICK
;
638 } else if (c
->flags
& CLIENT_TRIPLECLICK
) {
639 evtimer_del(&c
->click_timer
);
640 c
->flags
&= ~CLIENT_TRIPLECLICK
;
641 if (m
->b
== c
->click_button
) {
643 x
= m
->x
, y
= m
->y
, b
= m
->b
;
644 log_debug("triple-click at %u,%u", x
, y
);
649 x
= m
->x
, y
= m
->y
, b
= m
->b
;
650 log_debug("down at %u,%u", x
, y
);
651 c
->flags
|= CLIENT_DOUBLECLICK
;
654 if (KEYC_CLICK_TIMEOUT
!= 0) {
655 memcpy(&c
->click_event
, m
, sizeof c
->click_event
);
656 c
->click_button
= m
->b
;
658 log_debug("click timer started");
659 tv
.tv_sec
= KEYC_CLICK_TIMEOUT
/ 1000;
660 tv
.tv_usec
= (KEYC_CLICK_TIMEOUT
% 1000) * 1000L;
661 evtimer_del(&c
->click_timer
);
662 evtimer_add(&c
->click_timer
, &tv
);
668 return (KEYC_UNKNOWN
);
670 /* Save the session. */
675 /* Is this on the status line? */
676 m
->statusat
= status_at_line(c
);
677 m
->statuslines
= status_line_size(c
);
678 if (m
->statusat
!= -1 &&
679 y
>= (u_int
)m
->statusat
&&
680 y
< m
->statusat
+ m
->statuslines
) {
681 sr
= status_get_range(c
, x
, y
- m
->statusat
);
683 where
= STATUS_DEFAULT
;
686 case STYLE_RANGE_NONE
:
687 return (KEYC_UNKNOWN
);
688 case STYLE_RANGE_LEFT
:
691 case STYLE_RANGE_RIGHT
:
692 where
= STATUS_RIGHT
;
694 case STYLE_RANGE_WINDOW
:
695 wl
= winlink_find_by_index(&s
->windows
,
698 return (KEYC_UNKNOWN
);
699 m
->w
= wl
->window
->id
;
707 /* Not on status line. Adjust position and check for border or pane. */
708 if (where
== NOWHERE
) {
710 if (m
->statusat
== 0 && y
>= m
->statuslines
)
711 py
= y
- m
->statuslines
;
712 else if (m
->statusat
> 0 && y
>= (u_int
)m
->statusat
)
713 py
= m
->statusat
- 1;
717 tty_window_offset(&c
->tty
, &m
->ox
, &m
->oy
, &sx
, &sy
);
718 log_debug("mouse window @%u at %u,%u (%ux%u)",
719 s
->curw
->window
->id
, m
->ox
, m
->oy
, sx
, sy
);
720 if (px
> sx
|| py
> sy
)
721 return (KEYC_UNKNOWN
);
725 /* Try the pane borders if not zoomed. */
726 if (~s
->curw
->window
->flags
& WINDOW_ZOOMED
) {
727 TAILQ_FOREACH(wp
, &s
->curw
->window
->panes
, entry
) {
728 if ((wp
->xoff
+ wp
->sx
== px
&&
729 wp
->yoff
<= 1 + py
&&
730 wp
->yoff
+ wp
->sy
>= py
) ||
731 (wp
->yoff
+ wp
->sy
== py
&&
732 wp
->xoff
<= 1 + px
&&
733 wp
->xoff
+ wp
->sx
>= px
))
740 /* Otherwise try inside the pane. */
741 if (where
== NOWHERE
) {
742 wp
= window_get_active_at(s
->curw
->window
, px
, py
);
746 return (KEYC_UNKNOWN
);
749 log_debug("mouse %u,%u on pane %%%u", x
, y
, wp
->id
);
750 else if (where
== BORDER
)
751 log_debug("mouse on pane %%%u border", wp
->id
);
753 m
->w
= wp
->window
->id
;
757 /* Stop dragging if needed. */
758 if (type
!= DRAG
&& type
!= WHEEL
&& c
->tty
.mouse_drag_flag
!= 0) {
759 if (c
->tty
.mouse_drag_release
!= NULL
)
760 c
->tty
.mouse_drag_release(c
, m
);
762 c
->tty
.mouse_drag_update
= NULL
;
763 c
->tty
.mouse_drag_release
= NULL
;
766 * End a mouse drag by passing a MouseDragEnd key corresponding
767 * to the button that started the drag.
769 switch (c
->tty
.mouse_drag_flag
- 1) {
772 key
= KEYC_MOUSEDRAGEND1_PANE
;
774 key
= KEYC_MOUSEDRAGEND1_STATUS
;
775 if (where
== STATUS_LEFT
)
776 key
= KEYC_MOUSEDRAGEND1_STATUS_LEFT
;
777 if (where
== STATUS_RIGHT
)
778 key
= KEYC_MOUSEDRAGEND1_STATUS_RIGHT
;
779 if (where
== STATUS_DEFAULT
)
780 key
= KEYC_MOUSEDRAGEND1_STATUS_DEFAULT
;
782 key
= KEYC_MOUSEDRAGEND1_BORDER
;
786 key
= KEYC_MOUSEDRAGEND2_PANE
;
788 key
= KEYC_MOUSEDRAGEND2_STATUS
;
789 if (where
== STATUS_LEFT
)
790 key
= KEYC_MOUSEDRAGEND2_STATUS_LEFT
;
791 if (where
== STATUS_RIGHT
)
792 key
= KEYC_MOUSEDRAGEND2_STATUS_RIGHT
;
793 if (where
== STATUS_DEFAULT
)
794 key
= KEYC_MOUSEDRAGEND2_STATUS_DEFAULT
;
796 key
= KEYC_MOUSEDRAGEND2_BORDER
;
800 key
= KEYC_MOUSEDRAGEND3_PANE
;
802 key
= KEYC_MOUSEDRAGEND3_STATUS
;
803 if (where
== STATUS_LEFT
)
804 key
= KEYC_MOUSEDRAGEND3_STATUS_LEFT
;
805 if (where
== STATUS_RIGHT
)
806 key
= KEYC_MOUSEDRAGEND3_STATUS_RIGHT
;
807 if (where
== STATUS_DEFAULT
)
808 key
= KEYC_MOUSEDRAGEND3_STATUS_DEFAULT
;
810 key
= KEYC_MOUSEDRAGEND3_BORDER
;
814 key
= KEYC_MOUSEDRAGEND6_PANE
;
816 key
= KEYC_MOUSEDRAGEND6_STATUS
;
817 if (where
== STATUS_LEFT
)
818 key
= KEYC_MOUSEDRAGEND6_STATUS_LEFT
;
819 if (where
== STATUS_RIGHT
)
820 key
= KEYC_MOUSEDRAGEND6_STATUS_RIGHT
;
821 if (where
== STATUS_DEFAULT
)
822 key
= KEYC_MOUSEDRAGEND6_STATUS_DEFAULT
;
824 key
= KEYC_MOUSEDRAGEND6_BORDER
;
828 key
= KEYC_MOUSEDRAGEND7_PANE
;
830 key
= KEYC_MOUSEDRAGEND7_STATUS
;
831 if (where
== STATUS_LEFT
)
832 key
= KEYC_MOUSEDRAGEND7_STATUS_LEFT
;
833 if (where
== STATUS_RIGHT
)
834 key
= KEYC_MOUSEDRAGEND7_STATUS_RIGHT
;
835 if (where
== STATUS_DEFAULT
)
836 key
= KEYC_MOUSEDRAGEND7_STATUS_DEFAULT
;
838 key
= KEYC_MOUSEDRAGEND7_BORDER
;
842 key
= KEYC_MOUSEDRAGEND8_PANE
;
844 key
= KEYC_MOUSEDRAGEND8_STATUS
;
845 if (where
== STATUS_LEFT
)
846 key
= KEYC_MOUSEDRAGEND8_STATUS_LEFT
;
847 if (where
== STATUS_RIGHT
)
848 key
= KEYC_MOUSEDRAGEND8_STATUS_RIGHT
;
849 if (where
== STATUS_DEFAULT
)
850 key
= KEYC_MOUSEDRAGEND8_STATUS_DEFAULT
;
852 key
= KEYC_MOUSEDRAGEND8_BORDER
;
856 key
= KEYC_MOUSEDRAGEND9_PANE
;
858 key
= KEYC_MOUSEDRAGEND9_STATUS
;
859 if (where
== STATUS_LEFT
)
860 key
= KEYC_MOUSEDRAGEND9_STATUS_LEFT
;
861 if (where
== STATUS_RIGHT
)
862 key
= KEYC_MOUSEDRAGEND9_STATUS_RIGHT
;
863 if (where
== STATUS_DEFAULT
)
864 key
= KEYC_MOUSEDRAGEND9_STATUS_DEFAULT
;
866 key
= KEYC_MOUSEDRAGEND9_BORDER
;
868 case MOUSE_BUTTON_10
:
870 key
= KEYC_MOUSEDRAGEND10_PANE
;
872 key
= KEYC_MOUSEDRAGEND10_STATUS
;
873 if (where
== STATUS_LEFT
)
874 key
= KEYC_MOUSEDRAGEND10_STATUS_LEFT
;
875 if (where
== STATUS_RIGHT
)
876 key
= KEYC_MOUSEDRAGEND10_STATUS_RIGHT
;
877 if (where
== STATUS_DEFAULT
)
878 key
= KEYC_MOUSEDRAGEND10_STATUS_DEFAULT
;
880 key
= KEYC_MOUSEDRAGEND10_BORDER
;
882 case MOUSE_BUTTON_11
:
884 key
= KEYC_MOUSEDRAGEND11_PANE
;
886 key
= KEYC_MOUSEDRAGEND11_STATUS
;
887 if (where
== STATUS_LEFT
)
888 key
= KEYC_MOUSEDRAGEND11_STATUS_LEFT
;
889 if (where
== STATUS_RIGHT
)
890 key
= KEYC_MOUSEDRAGEND11_STATUS_RIGHT
;
891 if (where
== STATUS_DEFAULT
)
892 key
= KEYC_MOUSEDRAGEND11_STATUS_DEFAULT
;
894 key
= KEYC_MOUSEDRAGEND11_BORDER
;
900 c
->tty
.mouse_drag_flag
= 0;
904 /* Convert to a key binding. */
911 key
= KEYC_MOUSEMOVE_PANE
;
913 key
= KEYC_MOUSEMOVE_STATUS
;
914 if (where
== STATUS_LEFT
)
915 key
= KEYC_MOUSEMOVE_STATUS_LEFT
;
916 if (where
== STATUS_RIGHT
)
917 key
= KEYC_MOUSEMOVE_STATUS_RIGHT
;
918 if (where
== STATUS_DEFAULT
)
919 key
= KEYC_MOUSEMOVE_STATUS_DEFAULT
;
921 key
= KEYC_MOUSEMOVE_BORDER
;
924 if (c
->tty
.mouse_drag_update
!= NULL
)
927 switch (MOUSE_BUTTONS(b
)) {
930 key
= KEYC_MOUSEDRAG1_PANE
;
932 key
= KEYC_MOUSEDRAG1_STATUS
;
933 if (where
== STATUS_LEFT
)
934 key
= KEYC_MOUSEDRAG1_STATUS_LEFT
;
935 if (where
== STATUS_RIGHT
)
936 key
= KEYC_MOUSEDRAG1_STATUS_RIGHT
;
937 if (where
== STATUS_DEFAULT
)
938 key
= KEYC_MOUSEDRAG1_STATUS_DEFAULT
;
940 key
= KEYC_MOUSEDRAG1_BORDER
;
944 key
= KEYC_MOUSEDRAG2_PANE
;
946 key
= KEYC_MOUSEDRAG2_STATUS
;
947 if (where
== STATUS_LEFT
)
948 key
= KEYC_MOUSEDRAG2_STATUS_LEFT
;
949 if (where
== STATUS_RIGHT
)
950 key
= KEYC_MOUSEDRAG2_STATUS_RIGHT
;
951 if (where
== STATUS_DEFAULT
)
952 key
= KEYC_MOUSEDRAG2_STATUS_DEFAULT
;
954 key
= KEYC_MOUSEDRAG2_BORDER
;
958 key
= KEYC_MOUSEDRAG3_PANE
;
960 key
= KEYC_MOUSEDRAG3_STATUS
;
961 if (where
== STATUS_LEFT
)
962 key
= KEYC_MOUSEDRAG3_STATUS_LEFT
;
963 if (where
== STATUS_RIGHT
)
964 key
= KEYC_MOUSEDRAG3_STATUS_RIGHT
;
965 if (where
== STATUS_DEFAULT
)
966 key
= KEYC_MOUSEDRAG3_STATUS_DEFAULT
;
968 key
= KEYC_MOUSEDRAG3_BORDER
;
972 key
= KEYC_MOUSEDRAG6_PANE
;
974 key
= KEYC_MOUSEDRAG6_STATUS
;
975 if (where
== STATUS_LEFT
)
976 key
= KEYC_MOUSEDRAG6_STATUS_LEFT
;
977 if (where
== STATUS_RIGHT
)
978 key
= KEYC_MOUSEDRAG6_STATUS_RIGHT
;
979 if (where
== STATUS_DEFAULT
)
980 key
= KEYC_MOUSEDRAG6_STATUS_DEFAULT
;
982 key
= KEYC_MOUSEDRAG6_BORDER
;
986 key
= KEYC_MOUSEDRAG7_PANE
;
988 key
= KEYC_MOUSEDRAG7_STATUS
;
989 if (where
== STATUS_LEFT
)
990 key
= KEYC_MOUSEDRAG7_STATUS_LEFT
;
991 if (where
== STATUS_RIGHT
)
992 key
= KEYC_MOUSEDRAG7_STATUS_RIGHT
;
993 if (where
== STATUS_DEFAULT
)
994 key
= KEYC_MOUSEDRAG7_STATUS_DEFAULT
;
996 key
= KEYC_MOUSEDRAG7_BORDER
;
1000 key
= KEYC_MOUSEDRAG8_PANE
;
1001 if (where
== STATUS
)
1002 key
= KEYC_MOUSEDRAG8_STATUS
;
1003 if (where
== STATUS_LEFT
)
1004 key
= KEYC_MOUSEDRAG8_STATUS_LEFT
;
1005 if (where
== STATUS_RIGHT
)
1006 key
= KEYC_MOUSEDRAG8_STATUS_RIGHT
;
1007 if (where
== STATUS_DEFAULT
)
1008 key
= KEYC_MOUSEDRAG8_STATUS_DEFAULT
;
1009 if (where
== BORDER
)
1010 key
= KEYC_MOUSEDRAG8_BORDER
;
1012 case MOUSE_BUTTON_9
:
1014 key
= KEYC_MOUSEDRAG9_PANE
;
1015 if (where
== STATUS
)
1016 key
= KEYC_MOUSEDRAG9_STATUS
;
1017 if (where
== STATUS_LEFT
)
1018 key
= KEYC_MOUSEDRAG9_STATUS_LEFT
;
1019 if (where
== STATUS_RIGHT
)
1020 key
= KEYC_MOUSEDRAG9_STATUS_RIGHT
;
1021 if (where
== STATUS_DEFAULT
)
1022 key
= KEYC_MOUSEDRAG9_STATUS_DEFAULT
;
1023 if (where
== BORDER
)
1024 key
= KEYC_MOUSEDRAG9_BORDER
;
1026 case MOUSE_BUTTON_10
:
1028 key
= KEYC_MOUSEDRAG10_PANE
;
1029 if (where
== STATUS
)
1030 key
= KEYC_MOUSEDRAG10_STATUS
;
1031 if (where
== STATUS_LEFT
)
1032 key
= KEYC_MOUSEDRAG10_STATUS_LEFT
;
1033 if (where
== STATUS_RIGHT
)
1034 key
= KEYC_MOUSEDRAG10_STATUS_RIGHT
;
1035 if (where
== STATUS_DEFAULT
)
1036 key
= KEYC_MOUSEDRAG10_STATUS_DEFAULT
;
1037 if (where
== BORDER
)
1038 key
= KEYC_MOUSEDRAG10_BORDER
;
1040 case MOUSE_BUTTON_11
:
1042 key
= KEYC_MOUSEDRAG11_PANE
;
1043 if (where
== STATUS
)
1044 key
= KEYC_MOUSEDRAG11_STATUS
;
1045 if (where
== STATUS_LEFT
)
1046 key
= KEYC_MOUSEDRAG11_STATUS_LEFT
;
1047 if (where
== STATUS_RIGHT
)
1048 key
= KEYC_MOUSEDRAG11_STATUS_RIGHT
;
1049 if (where
== STATUS_DEFAULT
)
1050 key
= KEYC_MOUSEDRAG11_STATUS_DEFAULT
;
1051 if (where
== BORDER
)
1052 key
= KEYC_MOUSEDRAG11_BORDER
;
1058 * Begin a drag by setting the flag to a non-zero value that
1059 * corresponds to the mouse button in use.
1061 c
->tty
.mouse_drag_flag
= MOUSE_BUTTONS(b
) + 1;
1064 if (MOUSE_BUTTONS(b
) == MOUSE_WHEEL_UP
) {
1066 key
= KEYC_WHEELUP_PANE
;
1067 if (where
== STATUS
)
1068 key
= KEYC_WHEELUP_STATUS
;
1069 if (where
== STATUS_LEFT
)
1070 key
= KEYC_WHEELUP_STATUS_LEFT
;
1071 if (where
== STATUS_RIGHT
)
1072 key
= KEYC_WHEELUP_STATUS_RIGHT
;
1073 if (where
== STATUS_DEFAULT
)
1074 key
= KEYC_WHEELUP_STATUS_DEFAULT
;
1075 if (where
== BORDER
)
1076 key
= KEYC_WHEELUP_BORDER
;
1079 key
= KEYC_WHEELDOWN_PANE
;
1080 if (where
== STATUS
)
1081 key
= KEYC_WHEELDOWN_STATUS
;
1082 if (where
== STATUS_LEFT
)
1083 key
= KEYC_WHEELDOWN_STATUS_LEFT
;
1084 if (where
== STATUS_RIGHT
)
1085 key
= KEYC_WHEELDOWN_STATUS_RIGHT
;
1086 if (where
== STATUS_DEFAULT
)
1087 key
= KEYC_WHEELDOWN_STATUS_DEFAULT
;
1088 if (where
== BORDER
)
1089 key
= KEYC_WHEELDOWN_BORDER
;
1093 switch (MOUSE_BUTTONS(b
)) {
1094 case MOUSE_BUTTON_1
:
1096 key
= KEYC_MOUSEUP1_PANE
;
1097 if (where
== STATUS
)
1098 key
= KEYC_MOUSEUP1_STATUS
;
1099 if (where
== STATUS_LEFT
)
1100 key
= KEYC_MOUSEUP1_STATUS_LEFT
;
1101 if (where
== STATUS_RIGHT
)
1102 key
= KEYC_MOUSEUP1_STATUS_RIGHT
;
1103 if (where
== STATUS_DEFAULT
)
1104 key
= KEYC_MOUSEUP1_STATUS_DEFAULT
;
1105 if (where
== BORDER
)
1106 key
= KEYC_MOUSEUP1_BORDER
;
1108 case MOUSE_BUTTON_2
:
1110 key
= KEYC_MOUSEUP2_PANE
;
1111 if (where
== STATUS
)
1112 key
= KEYC_MOUSEUP2_STATUS
;
1113 if (where
== STATUS_LEFT
)
1114 key
= KEYC_MOUSEUP2_STATUS_LEFT
;
1115 if (where
== STATUS_RIGHT
)
1116 key
= KEYC_MOUSEUP2_STATUS_RIGHT
;
1117 if (where
== STATUS_DEFAULT
)
1118 key
= KEYC_MOUSEUP2_STATUS_DEFAULT
;
1119 if (where
== BORDER
)
1120 key
= KEYC_MOUSEUP2_BORDER
;
1122 case MOUSE_BUTTON_3
:
1124 key
= KEYC_MOUSEUP3_PANE
;
1125 if (where
== STATUS
)
1126 key
= KEYC_MOUSEUP3_STATUS
;
1127 if (where
== STATUS_LEFT
)
1128 key
= KEYC_MOUSEUP3_STATUS_LEFT
;
1129 if (where
== STATUS_RIGHT
)
1130 key
= KEYC_MOUSEUP3_STATUS_RIGHT
;
1131 if (where
== STATUS_DEFAULT
)
1132 key
= KEYC_MOUSEUP3_STATUS_DEFAULT
;
1133 if (where
== BORDER
)
1134 key
= KEYC_MOUSEUP3_BORDER
;
1136 case MOUSE_BUTTON_6
:
1138 key
= KEYC_MOUSEUP6_PANE
;
1139 if (where
== STATUS
)
1140 key
= KEYC_MOUSEUP6_STATUS
;
1141 if (where
== STATUS_LEFT
)
1142 key
= KEYC_MOUSEUP6_STATUS_LEFT
;
1143 if (where
== STATUS_RIGHT
)
1144 key
= KEYC_MOUSEUP6_STATUS_RIGHT
;
1145 if (where
== STATUS_DEFAULT
)
1146 key
= KEYC_MOUSEUP6_STATUS_DEFAULT
;
1147 if (where
== BORDER
)
1148 key
= KEYC_MOUSEUP6_BORDER
;
1150 case MOUSE_BUTTON_7
:
1152 key
= KEYC_MOUSEUP7_PANE
;
1153 if (where
== STATUS
)
1154 key
= KEYC_MOUSEUP7_STATUS
;
1155 if (where
== STATUS_LEFT
)
1156 key
= KEYC_MOUSEUP7_STATUS_LEFT
;
1157 if (where
== STATUS_RIGHT
)
1158 key
= KEYC_MOUSEUP7_STATUS_RIGHT
;
1159 if (where
== STATUS_DEFAULT
)
1160 key
= KEYC_MOUSEUP7_STATUS_DEFAULT
;
1161 if (where
== BORDER
)
1162 key
= KEYC_MOUSEUP7_BORDER
;
1164 case MOUSE_BUTTON_8
:
1166 key
= KEYC_MOUSEUP8_PANE
;
1167 if (where
== STATUS
)
1168 key
= KEYC_MOUSEUP8_STATUS
;
1169 if (where
== STATUS_LEFT
)
1170 key
= KEYC_MOUSEUP8_STATUS_LEFT
;
1171 if (where
== STATUS_RIGHT
)
1172 key
= KEYC_MOUSEUP8_STATUS_RIGHT
;
1173 if (where
== STATUS_DEFAULT
)
1174 key
= KEYC_MOUSEUP8_STATUS_DEFAULT
;
1175 if (where
== BORDER
)
1176 key
= KEYC_MOUSEUP8_BORDER
;
1178 case MOUSE_BUTTON_9
:
1180 key
= KEYC_MOUSEUP9_PANE
;
1181 if (where
== STATUS
)
1182 key
= KEYC_MOUSEUP9_STATUS
;
1183 if (where
== STATUS_LEFT
)
1184 key
= KEYC_MOUSEUP9_STATUS_LEFT
;
1185 if (where
== STATUS_RIGHT
)
1186 key
= KEYC_MOUSEUP9_STATUS_RIGHT
;
1187 if (where
== STATUS_DEFAULT
)
1188 key
= KEYC_MOUSEUP9_STATUS_DEFAULT
;
1189 if (where
== BORDER
)
1190 key
= KEYC_MOUSEUP9_BORDER
;
1192 case MOUSE_BUTTON_10
:
1194 key
= KEYC_MOUSEUP1_PANE
;
1195 if (where
== STATUS
)
1196 key
= KEYC_MOUSEUP1_STATUS
;
1197 if (where
== STATUS_LEFT
)
1198 key
= KEYC_MOUSEUP1_STATUS_LEFT
;
1199 if (where
== STATUS_RIGHT
)
1200 key
= KEYC_MOUSEUP1_STATUS_RIGHT
;
1201 if (where
== STATUS_DEFAULT
)
1202 key
= KEYC_MOUSEUP1_STATUS_DEFAULT
;
1203 if (where
== BORDER
)
1204 key
= KEYC_MOUSEUP1_BORDER
;
1206 case MOUSE_BUTTON_11
:
1208 key
= KEYC_MOUSEUP11_PANE
;
1209 if (where
== STATUS
)
1210 key
= KEYC_MOUSEUP11_STATUS
;
1211 if (where
== STATUS_LEFT
)
1212 key
= KEYC_MOUSEUP11_STATUS_LEFT
;
1213 if (where
== STATUS_RIGHT
)
1214 key
= KEYC_MOUSEUP11_STATUS_RIGHT
;
1215 if (where
== STATUS_DEFAULT
)
1216 key
= KEYC_MOUSEUP11_STATUS_DEFAULT
;
1217 if (where
== BORDER
)
1218 key
= KEYC_MOUSEUP11_BORDER
;
1223 switch (MOUSE_BUTTONS(b
)) {
1224 case MOUSE_BUTTON_1
:
1226 key
= KEYC_MOUSEDOWN1_PANE
;
1227 if (where
== STATUS
)
1228 key
= KEYC_MOUSEDOWN1_STATUS
;
1229 if (where
== STATUS_LEFT
)
1230 key
= KEYC_MOUSEDOWN1_STATUS_LEFT
;
1231 if (where
== STATUS_RIGHT
)
1232 key
= KEYC_MOUSEDOWN1_STATUS_RIGHT
;
1233 if (where
== STATUS_DEFAULT
)
1234 key
= KEYC_MOUSEDOWN1_STATUS_DEFAULT
;
1235 if (where
== BORDER
)
1236 key
= KEYC_MOUSEDOWN1_BORDER
;
1238 case MOUSE_BUTTON_2
:
1240 key
= KEYC_MOUSEDOWN2_PANE
;
1241 if (where
== STATUS
)
1242 key
= KEYC_MOUSEDOWN2_STATUS
;
1243 if (where
== STATUS_LEFT
)
1244 key
= KEYC_MOUSEDOWN2_STATUS_LEFT
;
1245 if (where
== STATUS_RIGHT
)
1246 key
= KEYC_MOUSEDOWN2_STATUS_RIGHT
;
1247 if (where
== STATUS_DEFAULT
)
1248 key
= KEYC_MOUSEDOWN2_STATUS_DEFAULT
;
1249 if (where
== BORDER
)
1250 key
= KEYC_MOUSEDOWN2_BORDER
;
1252 case MOUSE_BUTTON_3
:
1254 key
= KEYC_MOUSEDOWN3_PANE
;
1255 if (where
== STATUS
)
1256 key
= KEYC_MOUSEDOWN3_STATUS
;
1257 if (where
== STATUS_LEFT
)
1258 key
= KEYC_MOUSEDOWN3_STATUS_LEFT
;
1259 if (where
== STATUS_RIGHT
)
1260 key
= KEYC_MOUSEDOWN3_STATUS_RIGHT
;
1261 if (where
== STATUS_DEFAULT
)
1262 key
= KEYC_MOUSEDOWN3_STATUS_DEFAULT
;
1263 if (where
== BORDER
)
1264 key
= KEYC_MOUSEDOWN3_BORDER
;
1266 case MOUSE_BUTTON_6
:
1268 key
= KEYC_MOUSEDOWN6_PANE
;
1269 if (where
== STATUS
)
1270 key
= KEYC_MOUSEDOWN6_STATUS
;
1271 if (where
== STATUS_LEFT
)
1272 key
= KEYC_MOUSEDOWN6_STATUS_LEFT
;
1273 if (where
== STATUS_RIGHT
)
1274 key
= KEYC_MOUSEDOWN6_STATUS_RIGHT
;
1275 if (where
== STATUS_DEFAULT
)
1276 key
= KEYC_MOUSEDOWN6_STATUS_DEFAULT
;
1277 if (where
== BORDER
)
1278 key
= KEYC_MOUSEDOWN6_BORDER
;
1280 case MOUSE_BUTTON_7
:
1282 key
= KEYC_MOUSEDOWN7_PANE
;
1283 if (where
== STATUS
)
1284 key
= KEYC_MOUSEDOWN7_STATUS
;
1285 if (where
== STATUS_LEFT
)
1286 key
= KEYC_MOUSEDOWN7_STATUS_LEFT
;
1287 if (where
== STATUS_RIGHT
)
1288 key
= KEYC_MOUSEDOWN7_STATUS_RIGHT
;
1289 if (where
== STATUS_DEFAULT
)
1290 key
= KEYC_MOUSEDOWN7_STATUS_DEFAULT
;
1291 if (where
== BORDER
)
1292 key
= KEYC_MOUSEDOWN7_BORDER
;
1294 case MOUSE_BUTTON_8
:
1296 key
= KEYC_MOUSEDOWN8_PANE
;
1297 if (where
== STATUS
)
1298 key
= KEYC_MOUSEDOWN8_STATUS
;
1299 if (where
== STATUS_LEFT
)
1300 key
= KEYC_MOUSEDOWN8_STATUS_LEFT
;
1301 if (where
== STATUS_RIGHT
)
1302 key
= KEYC_MOUSEDOWN8_STATUS_RIGHT
;
1303 if (where
== STATUS_DEFAULT
)
1304 key
= KEYC_MOUSEDOWN8_STATUS_DEFAULT
;
1305 if (where
== BORDER
)
1306 key
= KEYC_MOUSEDOWN8_BORDER
;
1308 case MOUSE_BUTTON_9
:
1310 key
= KEYC_MOUSEDOWN9_PANE
;
1311 if (where
== STATUS
)
1312 key
= KEYC_MOUSEDOWN9_STATUS
;
1313 if (where
== STATUS_LEFT
)
1314 key
= KEYC_MOUSEDOWN9_STATUS_LEFT
;
1315 if (where
== STATUS_RIGHT
)
1316 key
= KEYC_MOUSEDOWN9_STATUS_RIGHT
;
1317 if (where
== STATUS_DEFAULT
)
1318 key
= KEYC_MOUSEDOWN9_STATUS_DEFAULT
;
1319 if (where
== BORDER
)
1320 key
= KEYC_MOUSEDOWN9_BORDER
;
1322 case MOUSE_BUTTON_10
:
1324 key
= KEYC_MOUSEDOWN10_PANE
;
1325 if (where
== STATUS
)
1326 key
= KEYC_MOUSEDOWN10_STATUS
;
1327 if (where
== STATUS_LEFT
)
1328 key
= KEYC_MOUSEDOWN10_STATUS_LEFT
;
1329 if (where
== STATUS_RIGHT
)
1330 key
= KEYC_MOUSEDOWN10_STATUS_RIGHT
;
1331 if (where
== STATUS_DEFAULT
)
1332 key
= KEYC_MOUSEDOWN10_STATUS_DEFAULT
;
1333 if (where
== BORDER
)
1334 key
= KEYC_MOUSEDOWN10_BORDER
;
1336 case MOUSE_BUTTON_11
:
1338 key
= KEYC_MOUSEDOWN11_PANE
;
1339 if (where
== STATUS
)
1340 key
= KEYC_MOUSEDOWN11_STATUS
;
1341 if (where
== STATUS_LEFT
)
1342 key
= KEYC_MOUSEDOWN11_STATUS_LEFT
;
1343 if (where
== STATUS_RIGHT
)
1344 key
= KEYC_MOUSEDOWN11_STATUS_RIGHT
;
1345 if (where
== STATUS_DEFAULT
)
1346 key
= KEYC_MOUSEDOWN11_STATUS_DEFAULT
;
1347 if (where
== BORDER
)
1348 key
= KEYC_MOUSEDOWN11_BORDER
;
1353 switch (MOUSE_BUTTONS(b
)) {
1354 case MOUSE_BUTTON_1
:
1356 key
= KEYC_SECONDCLICK1_PANE
;
1357 if (where
== STATUS
)
1358 key
= KEYC_SECONDCLICK1_STATUS
;
1359 if (where
== STATUS_LEFT
)
1360 key
= KEYC_SECONDCLICK1_STATUS_LEFT
;
1361 if (where
== STATUS_RIGHT
)
1362 key
= KEYC_SECONDCLICK1_STATUS_RIGHT
;
1363 if (where
== STATUS_DEFAULT
)
1364 key
= KEYC_SECONDCLICK1_STATUS_DEFAULT
;
1365 if (where
== BORDER
)
1366 key
= KEYC_SECONDCLICK1_BORDER
;
1368 case MOUSE_BUTTON_2
:
1370 key
= KEYC_SECONDCLICK2_PANE
;
1371 if (where
== STATUS
)
1372 key
= KEYC_SECONDCLICK2_STATUS
;
1373 if (where
== STATUS_LEFT
)
1374 key
= KEYC_SECONDCLICK2_STATUS_LEFT
;
1375 if (where
== STATUS_RIGHT
)
1376 key
= KEYC_SECONDCLICK2_STATUS_RIGHT
;
1377 if (where
== STATUS_DEFAULT
)
1378 key
= KEYC_SECONDCLICK2_STATUS_DEFAULT
;
1379 if (where
== BORDER
)
1380 key
= KEYC_SECONDCLICK2_BORDER
;
1382 case MOUSE_BUTTON_3
:
1384 key
= KEYC_SECONDCLICK3_PANE
;
1385 if (where
== STATUS
)
1386 key
= KEYC_SECONDCLICK3_STATUS
;
1387 if (where
== STATUS_LEFT
)
1388 key
= KEYC_SECONDCLICK3_STATUS_LEFT
;
1389 if (where
== STATUS_RIGHT
)
1390 key
= KEYC_SECONDCLICK3_STATUS_RIGHT
;
1391 if (where
== STATUS_DEFAULT
)
1392 key
= KEYC_SECONDCLICK3_STATUS_DEFAULT
;
1393 if (where
== BORDER
)
1394 key
= KEYC_SECONDCLICK3_BORDER
;
1396 case MOUSE_BUTTON_6
:
1398 key
= KEYC_SECONDCLICK6_PANE
;
1399 if (where
== STATUS
)
1400 key
= KEYC_SECONDCLICK6_STATUS
;
1401 if (where
== STATUS_LEFT
)
1402 key
= KEYC_SECONDCLICK6_STATUS_LEFT
;
1403 if (where
== STATUS_RIGHT
)
1404 key
= KEYC_SECONDCLICK6_STATUS_RIGHT
;
1405 if (where
== STATUS_DEFAULT
)
1406 key
= KEYC_SECONDCLICK6_STATUS_DEFAULT
;
1407 if (where
== BORDER
)
1408 key
= KEYC_SECONDCLICK6_BORDER
;
1410 case MOUSE_BUTTON_7
:
1412 key
= KEYC_SECONDCLICK7_PANE
;
1413 if (where
== STATUS
)
1414 key
= KEYC_SECONDCLICK7_STATUS
;
1415 if (where
== STATUS_LEFT
)
1416 key
= KEYC_SECONDCLICK7_STATUS_LEFT
;
1417 if (where
== STATUS_RIGHT
)
1418 key
= KEYC_SECONDCLICK7_STATUS_RIGHT
;
1419 if (where
== STATUS_DEFAULT
)
1420 key
= KEYC_SECONDCLICK7_STATUS_DEFAULT
;
1421 if (where
== BORDER
)
1422 key
= KEYC_SECONDCLICK7_BORDER
;
1424 case MOUSE_BUTTON_8
:
1426 key
= KEYC_SECONDCLICK8_PANE
;
1427 if (where
== STATUS
)
1428 key
= KEYC_SECONDCLICK8_STATUS
;
1429 if (where
== STATUS_LEFT
)
1430 key
= KEYC_SECONDCLICK8_STATUS_LEFT
;
1431 if (where
== STATUS_RIGHT
)
1432 key
= KEYC_SECONDCLICK8_STATUS_RIGHT
;
1433 if (where
== STATUS_DEFAULT
)
1434 key
= KEYC_SECONDCLICK8_STATUS_DEFAULT
;
1435 if (where
== BORDER
)
1436 key
= KEYC_SECONDCLICK8_BORDER
;
1438 case MOUSE_BUTTON_9
:
1440 key
= KEYC_SECONDCLICK9_PANE
;
1441 if (where
== STATUS
)
1442 key
= KEYC_SECONDCLICK9_STATUS
;
1443 if (where
== STATUS_LEFT
)
1444 key
= KEYC_SECONDCLICK9_STATUS_LEFT
;
1445 if (where
== STATUS_RIGHT
)
1446 key
= KEYC_SECONDCLICK9_STATUS_RIGHT
;
1447 if (where
== STATUS_DEFAULT
)
1448 key
= KEYC_SECONDCLICK9_STATUS_DEFAULT
;
1449 if (where
== BORDER
)
1450 key
= KEYC_SECONDCLICK9_BORDER
;
1452 case MOUSE_BUTTON_10
:
1454 key
= KEYC_SECONDCLICK10_PANE
;
1455 if (where
== STATUS
)
1456 key
= KEYC_SECONDCLICK10_STATUS
;
1457 if (where
== STATUS_LEFT
)
1458 key
= KEYC_SECONDCLICK10_STATUS_LEFT
;
1459 if (where
== STATUS_RIGHT
)
1460 key
= KEYC_SECONDCLICK10_STATUS_RIGHT
;
1461 if (where
== STATUS_DEFAULT
)
1462 key
= KEYC_SECONDCLICK10_STATUS_DEFAULT
;
1463 if (where
== BORDER
)
1464 key
= KEYC_SECONDCLICK10_BORDER
;
1466 case MOUSE_BUTTON_11
:
1468 key
= KEYC_SECONDCLICK11_PANE
;
1469 if (where
== STATUS
)
1470 key
= KEYC_SECONDCLICK11_STATUS
;
1471 if (where
== STATUS_LEFT
)
1472 key
= KEYC_SECONDCLICK11_STATUS_LEFT
;
1473 if (where
== STATUS_RIGHT
)
1474 key
= KEYC_SECONDCLICK11_STATUS_RIGHT
;
1475 if (where
== STATUS_DEFAULT
)
1476 key
= KEYC_SECONDCLICK11_STATUS_DEFAULT
;
1477 if (where
== BORDER
)
1478 key
= KEYC_SECONDCLICK11_BORDER
;
1483 switch (MOUSE_BUTTONS(b
)) {
1484 case MOUSE_BUTTON_1
:
1486 key
= KEYC_DOUBLECLICK1_PANE
;
1487 if (where
== STATUS
)
1488 key
= KEYC_DOUBLECLICK1_STATUS
;
1489 if (where
== STATUS_LEFT
)
1490 key
= KEYC_DOUBLECLICK1_STATUS_LEFT
;
1491 if (where
== STATUS_RIGHT
)
1492 key
= KEYC_DOUBLECLICK1_STATUS_RIGHT
;
1493 if (where
== STATUS_DEFAULT
)
1494 key
= KEYC_DOUBLECLICK1_STATUS_DEFAULT
;
1495 if (where
== BORDER
)
1496 key
= KEYC_DOUBLECLICK1_BORDER
;
1498 case MOUSE_BUTTON_2
:
1500 key
= KEYC_DOUBLECLICK2_PANE
;
1501 if (where
== STATUS
)
1502 key
= KEYC_DOUBLECLICK2_STATUS
;
1503 if (where
== STATUS_LEFT
)
1504 key
= KEYC_DOUBLECLICK2_STATUS_LEFT
;
1505 if (where
== STATUS_RIGHT
)
1506 key
= KEYC_DOUBLECLICK2_STATUS_RIGHT
;
1507 if (where
== STATUS_DEFAULT
)
1508 key
= KEYC_DOUBLECLICK2_STATUS_DEFAULT
;
1509 if (where
== BORDER
)
1510 key
= KEYC_DOUBLECLICK2_BORDER
;
1512 case MOUSE_BUTTON_3
:
1514 key
= KEYC_DOUBLECLICK3_PANE
;
1515 if (where
== STATUS
)
1516 key
= KEYC_DOUBLECLICK3_STATUS
;
1517 if (where
== STATUS_LEFT
)
1518 key
= KEYC_DOUBLECLICK3_STATUS_LEFT
;
1519 if (where
== STATUS_RIGHT
)
1520 key
= KEYC_DOUBLECLICK3_STATUS_RIGHT
;
1521 if (where
== STATUS_DEFAULT
)
1522 key
= KEYC_DOUBLECLICK3_STATUS_DEFAULT
;
1523 if (where
== BORDER
)
1524 key
= KEYC_DOUBLECLICK3_BORDER
;
1526 case MOUSE_BUTTON_6
:
1528 key
= KEYC_DOUBLECLICK6_PANE
;
1529 if (where
== STATUS
)
1530 key
= KEYC_DOUBLECLICK6_STATUS
;
1531 if (where
== STATUS_LEFT
)
1532 key
= KEYC_DOUBLECLICK6_STATUS_LEFT
;
1533 if (where
== STATUS_RIGHT
)
1534 key
= KEYC_DOUBLECLICK6_STATUS_RIGHT
;
1535 if (where
== STATUS_DEFAULT
)
1536 key
= KEYC_DOUBLECLICK6_STATUS_DEFAULT
;
1537 if (where
== BORDER
)
1538 key
= KEYC_DOUBLECLICK6_BORDER
;
1540 case MOUSE_BUTTON_7
:
1542 key
= KEYC_DOUBLECLICK7_PANE
;
1543 if (where
== STATUS
)
1544 key
= KEYC_DOUBLECLICK7_STATUS
;
1545 if (where
== STATUS_LEFT
)
1546 key
= KEYC_DOUBLECLICK7_STATUS_LEFT
;
1547 if (where
== STATUS_RIGHT
)
1548 key
= KEYC_DOUBLECLICK7_STATUS_RIGHT
;
1549 if (where
== STATUS_DEFAULT
)
1550 key
= KEYC_DOUBLECLICK7_STATUS_DEFAULT
;
1551 if (where
== BORDER
)
1552 key
= KEYC_DOUBLECLICK7_BORDER
;
1554 case MOUSE_BUTTON_8
:
1556 key
= KEYC_DOUBLECLICK8_PANE
;
1557 if (where
== STATUS
)
1558 key
= KEYC_DOUBLECLICK8_STATUS
;
1559 if (where
== STATUS_LEFT
)
1560 key
= KEYC_DOUBLECLICK8_STATUS_LEFT
;
1561 if (where
== STATUS_RIGHT
)
1562 key
= KEYC_DOUBLECLICK8_STATUS_RIGHT
;
1563 if (where
== STATUS_DEFAULT
)
1564 key
= KEYC_DOUBLECLICK8_STATUS_DEFAULT
;
1565 if (where
== BORDER
)
1566 key
= KEYC_DOUBLECLICK8_BORDER
;
1568 case MOUSE_BUTTON_9
:
1570 key
= KEYC_DOUBLECLICK9_PANE
;
1571 if (where
== STATUS
)
1572 key
= KEYC_DOUBLECLICK9_STATUS
;
1573 if (where
== STATUS_LEFT
)
1574 key
= KEYC_DOUBLECLICK9_STATUS_LEFT
;
1575 if (where
== STATUS_RIGHT
)
1576 key
= KEYC_DOUBLECLICK9_STATUS_RIGHT
;
1577 if (where
== STATUS_DEFAULT
)
1578 key
= KEYC_DOUBLECLICK9_STATUS_DEFAULT
;
1579 if (where
== BORDER
)
1580 key
= KEYC_DOUBLECLICK9_BORDER
;
1582 case MOUSE_BUTTON_10
:
1584 key
= KEYC_DOUBLECLICK10_PANE
;
1585 if (where
== STATUS
)
1586 key
= KEYC_DOUBLECLICK10_STATUS
;
1587 if (where
== STATUS_LEFT
)
1588 key
= KEYC_DOUBLECLICK10_STATUS_LEFT
;
1589 if (where
== STATUS_RIGHT
)
1590 key
= KEYC_DOUBLECLICK10_STATUS_RIGHT
;
1591 if (where
== STATUS_DEFAULT
)
1592 key
= KEYC_DOUBLECLICK10_STATUS_DEFAULT
;
1593 if (where
== BORDER
)
1594 key
= KEYC_DOUBLECLICK10_BORDER
;
1596 case MOUSE_BUTTON_11
:
1598 key
= KEYC_DOUBLECLICK11_PANE
;
1599 if (where
== STATUS
)
1600 key
= KEYC_DOUBLECLICK11_STATUS
;
1601 if (where
== STATUS_LEFT
)
1602 key
= KEYC_DOUBLECLICK11_STATUS_LEFT
;
1603 if (where
== STATUS_RIGHT
)
1604 key
= KEYC_DOUBLECLICK11_STATUS_RIGHT
;
1605 if (where
== STATUS_DEFAULT
)
1606 key
= KEYC_DOUBLECLICK11_STATUS_DEFAULT
;
1607 if (where
== BORDER
)
1608 key
= KEYC_DOUBLECLICK11_BORDER
;
1613 switch (MOUSE_BUTTONS(b
)) {
1614 case MOUSE_BUTTON_1
:
1616 key
= KEYC_TRIPLECLICK1_PANE
;
1617 if (where
== STATUS
)
1618 key
= KEYC_TRIPLECLICK1_STATUS
;
1619 if (where
== STATUS_LEFT
)
1620 key
= KEYC_TRIPLECLICK1_STATUS_LEFT
;
1621 if (where
== STATUS_RIGHT
)
1622 key
= KEYC_TRIPLECLICK1_STATUS_RIGHT
;
1623 if (where
== STATUS_DEFAULT
)
1624 key
= KEYC_TRIPLECLICK1_STATUS_DEFAULT
;
1625 if (where
== BORDER
)
1626 key
= KEYC_TRIPLECLICK1_BORDER
;
1628 case MOUSE_BUTTON_2
:
1630 key
= KEYC_TRIPLECLICK2_PANE
;
1631 if (where
== STATUS
)
1632 key
= KEYC_TRIPLECLICK2_STATUS
;
1633 if (where
== STATUS_LEFT
)
1634 key
= KEYC_TRIPLECLICK2_STATUS_LEFT
;
1635 if (where
== STATUS_RIGHT
)
1636 key
= KEYC_TRIPLECLICK2_STATUS_RIGHT
;
1637 if (where
== STATUS_DEFAULT
)
1638 key
= KEYC_TRIPLECLICK2_STATUS_DEFAULT
;
1639 if (where
== BORDER
)
1640 key
= KEYC_TRIPLECLICK2_BORDER
;
1642 case MOUSE_BUTTON_3
:
1644 key
= KEYC_TRIPLECLICK3_PANE
;
1645 if (where
== STATUS
)
1646 key
= KEYC_TRIPLECLICK3_STATUS
;
1647 if (where
== STATUS_LEFT
)
1648 key
= KEYC_TRIPLECLICK3_STATUS_LEFT
;
1649 if (where
== STATUS_RIGHT
)
1650 key
= KEYC_TRIPLECLICK3_STATUS_RIGHT
;
1651 if (where
== STATUS_DEFAULT
)
1652 key
= KEYC_TRIPLECLICK3_STATUS_DEFAULT
;
1653 if (where
== BORDER
)
1654 key
= KEYC_TRIPLECLICK3_BORDER
;
1656 case MOUSE_BUTTON_6
:
1658 key
= KEYC_TRIPLECLICK6_PANE
;
1659 if (where
== STATUS
)
1660 key
= KEYC_TRIPLECLICK6_STATUS
;
1661 if (where
== STATUS_LEFT
)
1662 key
= KEYC_TRIPLECLICK6_STATUS_LEFT
;
1663 if (where
== STATUS_RIGHT
)
1664 key
= KEYC_TRIPLECLICK6_STATUS_RIGHT
;
1665 if (where
== STATUS_DEFAULT
)
1666 key
= KEYC_TRIPLECLICK6_STATUS_DEFAULT
;
1667 if (where
== BORDER
)
1668 key
= KEYC_TRIPLECLICK6_BORDER
;
1670 case MOUSE_BUTTON_7
:
1672 key
= KEYC_TRIPLECLICK7_PANE
;
1673 if (where
== STATUS
)
1674 key
= KEYC_TRIPLECLICK7_STATUS
;
1675 if (where
== STATUS_LEFT
)
1676 key
= KEYC_TRIPLECLICK7_STATUS_LEFT
;
1677 if (where
== STATUS_RIGHT
)
1678 key
= KEYC_TRIPLECLICK7_STATUS_RIGHT
;
1679 if (where
== STATUS_DEFAULT
)
1680 key
= KEYC_TRIPLECLICK7_STATUS_DEFAULT
;
1681 if (where
== BORDER
)
1682 key
= KEYC_TRIPLECLICK7_BORDER
;
1684 case MOUSE_BUTTON_8
:
1686 key
= KEYC_TRIPLECLICK8_PANE
;
1687 if (where
== STATUS
)
1688 key
= KEYC_TRIPLECLICK8_STATUS
;
1689 if (where
== STATUS_LEFT
)
1690 key
= KEYC_TRIPLECLICK8_STATUS_LEFT
;
1691 if (where
== STATUS_RIGHT
)
1692 key
= KEYC_TRIPLECLICK8_STATUS_RIGHT
;
1693 if (where
== STATUS_DEFAULT
)
1694 key
= KEYC_TRIPLECLICK8_STATUS_DEFAULT
;
1695 if (where
== BORDER
)
1696 key
= KEYC_TRIPLECLICK8_BORDER
;
1698 case MOUSE_BUTTON_9
:
1700 key
= KEYC_TRIPLECLICK9_PANE
;
1701 if (where
== STATUS
)
1702 key
= KEYC_TRIPLECLICK9_STATUS
;
1703 if (where
== STATUS_LEFT
)
1704 key
= KEYC_TRIPLECLICK9_STATUS_LEFT
;
1705 if (where
== STATUS_RIGHT
)
1706 key
= KEYC_TRIPLECLICK9_STATUS_RIGHT
;
1707 if (where
== STATUS_DEFAULT
)
1708 key
= KEYC_TRIPLECLICK9_STATUS_DEFAULT
;
1709 if (where
== BORDER
)
1710 key
= KEYC_TRIPLECLICK9_BORDER
;
1712 case MOUSE_BUTTON_10
:
1714 key
= KEYC_TRIPLECLICK10_PANE
;
1715 if (where
== STATUS
)
1716 key
= KEYC_TRIPLECLICK10_STATUS
;
1717 if (where
== STATUS_LEFT
)
1718 key
= KEYC_TRIPLECLICK10_STATUS_LEFT
;
1719 if (where
== STATUS_RIGHT
)
1720 key
= KEYC_TRIPLECLICK10_STATUS_RIGHT
;
1721 if (where
== STATUS_DEFAULT
)
1722 key
= KEYC_TRIPLECLICK10_STATUS_DEFAULT
;
1723 if (where
== BORDER
)
1724 key
= KEYC_TRIPLECLICK10_BORDER
;
1726 case MOUSE_BUTTON_11
:
1728 key
= KEYC_TRIPLECLICK11_PANE
;
1729 if (where
== STATUS
)
1730 key
= KEYC_TRIPLECLICK11_STATUS
;
1731 if (where
== STATUS_LEFT
)
1732 key
= KEYC_TRIPLECLICK11_STATUS_LEFT
;
1733 if (where
== STATUS_RIGHT
)
1734 key
= KEYC_TRIPLECLICK11_STATUS_RIGHT
;
1735 if (where
== STATUS_DEFAULT
)
1736 key
= KEYC_TRIPLECLICK11_STATUS_DEFAULT
;
1737 if (where
== BORDER
)
1738 key
= KEYC_TRIPLECLICK11_BORDER
;
1743 if (key
== KEYC_UNKNOWN
)
1744 return (KEYC_UNKNOWN
);
1747 /* Apply modifiers if any. */
1748 if (b
& MOUSE_MASK_META
)
1750 if (b
& MOUSE_MASK_CTRL
)
1752 if (b
& MOUSE_MASK_SHIFT
)
1755 if (log_get_level() != 0)
1756 log_debug("mouse key is %s", key_string_lookup_key (key
, 1));
1760 /* Is this fast enough to probably be a paste? */
1762 server_client_assume_paste(struct session
*s
)
1767 if ((t
= options_get_number(s
->options
, "assume-paste-time")) == 0)
1770 timersub(&s
->activity_time
, &s
->last_activity_time
, &tv
);
1771 if (tv
.tv_sec
== 0 && tv
.tv_usec
< t
* 1000) {
1772 log_debug("session %s pasting (flag %d)", s
->name
,
1773 !!(s
->flags
& SESSION_PASTING
));
1774 if (s
->flags
& SESSION_PASTING
)
1776 s
->flags
|= SESSION_PASTING
;
1779 log_debug("session %s not pasting", s
->name
);
1780 s
->flags
&= ~SESSION_PASTING
;
1784 /* Has the latest client changed? */
1786 server_client_update_latest(struct client
*c
)
1790 if (c
->session
== NULL
)
1792 w
= c
->session
->curw
->window
;
1798 if (options_get_number(w
->options
, "window-size") == WINDOW_SIZE_LATEST
)
1799 recalculate_size(w
, 0);
1801 notify_client("client-active", c
);
1805 * Handle data key input from client. This owns and can modify the key event it
1806 * is given and is responsible for freeing it.
1808 static enum cmd_retval
1809 server_client_key_callback(struct cmdq_item
*item
, void *data
)
1811 struct client
*c
= cmdq_get_client(item
);
1812 struct key_event
*event
= data
;
1813 key_code key
= event
->key
;
1814 struct mouse_event
*m
= &event
->m
;
1815 struct session
*s
= c
->session
;
1817 struct window_pane
*wp
;
1818 struct window_mode_entry
*wme
;
1820 struct key_table
*table
, *first
;
1821 struct key_binding
*bd
;
1822 int xtimeout
, flags
;
1823 struct cmd_find_state fs
;
1826 /* Check the client is good to accept input. */
1827 if (s
== NULL
|| (c
->flags
& CLIENT_UNATTACHEDFLAGS
))
1831 /* Update the activity timer. */
1832 if (gettimeofday(&c
->activity_time
, NULL
) != 0)
1833 fatal("gettimeofday failed");
1834 session_update_activity(s
, &c
->activity_time
);
1836 /* Check for mouse keys. */
1838 if (key
== KEYC_MOUSE
|| key
== KEYC_DOUBLECLICK
) {
1839 if (c
->flags
& CLIENT_READONLY
)
1841 key
= server_client_check_mouse(c
, event
);
1842 if (key
== KEYC_UNKNOWN
)
1849 * Mouse drag is in progress, so fire the callback (now that
1850 * the mouse event is valid).
1852 if ((key
& KEYC_MASK_KEY
) == KEYC_DRAGGING
) {
1853 c
->tty
.mouse_drag_update(c
, m
);
1859 /* Find affected pane. */
1860 if (!KEYC_IS_MOUSE(key
) || cmd_find_from_mouse(&fs
, m
, 0) != 0)
1861 cmd_find_from_client(&fs
, c
, 0);
1864 /* Forward mouse keys if disabled. */
1865 if (KEYC_IS_MOUSE(key
) && !options_get_number(s
->options
, "mouse"))
1868 /* Treat everything as a regular key when pasting is detected. */
1869 if (!KEYC_IS_MOUSE(key
) && server_client_assume_paste(s
))
1873 * Work out the current key table. If the pane is in a mode, use
1874 * the mode table instead of the default key table.
1876 if (server_client_is_default_key_table(c
, c
->keytable
) &&
1878 (wme
= TAILQ_FIRST(&wp
->modes
)) != NULL
&&
1879 wme
->mode
->key_table
!= NULL
)
1880 table
= key_bindings_get_table(wme
->mode
->key_table(wme
), 1);
1882 table
= c
->keytable
;
1887 * The prefix always takes precedence and forces a switch to the prefix
1888 * table, unless we are already there.
1890 key0
= (key
& (KEYC_MASK_KEY
|KEYC_MASK_MODIFIERS
));
1891 if ((key0
== (key_code
)options_get_number(s
->options
, "prefix") ||
1892 key0
== (key_code
)options_get_number(s
->options
, "prefix2")) &&
1893 strcmp(table
->name
, "prefix") != 0) {
1894 server_client_set_key_table(c
, "prefix");
1895 server_status_client(c
);
1901 /* Log key table. */
1903 log_debug("key table %s (no pane)", table
->name
);
1905 log_debug("key table %s (pane %%%u)", table
->name
, wp
->id
);
1906 if (c
->flags
& CLIENT_REPEAT
)
1907 log_debug("currently repeating");
1909 /* Try to see if there is a key binding in the current table. */
1910 bd
= key_bindings_get(table
, key0
);
1913 * Key was matched in this table. If currently repeating but a
1914 * non-repeating binding was found, stop repeating and try
1915 * again in the root table.
1917 if ((c
->flags
& CLIENT_REPEAT
) &&
1918 (~bd
->flags
& KEY_BINDING_REPEAT
)) {
1919 log_debug("found in key table %s (not repeating)",
1921 server_client_set_key_table(c
, NULL
);
1922 first
= table
= c
->keytable
;
1923 c
->flags
&= ~CLIENT_REPEAT
;
1924 server_status_client(c
);
1927 log_debug("found in key table %s", table
->name
);
1930 * Take a reference to this table to make sure the key binding
1931 * doesn't disappear.
1933 table
->references
++;
1936 * If this is a repeating key, start the timer. Otherwise reset
1937 * the client back to the root table.
1939 xtimeout
= options_get_number(s
->options
, "repeat-time");
1940 if (xtimeout
!= 0 && (bd
->flags
& KEY_BINDING_REPEAT
)) {
1941 c
->flags
|= CLIENT_REPEAT
;
1943 tv
.tv_sec
= xtimeout
/ 1000;
1944 tv
.tv_usec
= (xtimeout
% 1000) * 1000L;
1945 evtimer_del(&c
->repeat_timer
);
1946 evtimer_add(&c
->repeat_timer
, &tv
);
1948 c
->flags
&= ~CLIENT_REPEAT
;
1949 server_client_set_key_table(c
, NULL
);
1951 server_status_client(c
);
1953 /* Execute the key binding. */
1954 key_bindings_dispatch(bd
, item
, c
, event
, &fs
);
1955 key_bindings_unref_table(table
);
1960 * No match, try the ANY key.
1962 if (key0
!= KEYC_ANY
) {
1968 * No match in this table. If not in the root table or if repeating,
1969 * switch the client back to the root table and try again.
1971 log_debug("not found in key table %s", table
->name
);
1972 if (!server_client_is_default_key_table(c
, table
) ||
1973 (c
->flags
& CLIENT_REPEAT
)) {
1974 log_debug("trying in root table");
1975 server_client_set_key_table(c
, NULL
);
1976 table
= c
->keytable
;
1977 if (c
->flags
& CLIENT_REPEAT
)
1979 c
->flags
&= ~CLIENT_REPEAT
;
1980 server_status_client(c
);
1985 * No match in the root table either. If this wasn't the first table
1986 * tried, don't pass the key to the pane.
1988 if (first
!= table
&& (~flags
& CLIENT_REPEAT
)) {
1989 server_client_set_key_table(c
, NULL
);
1990 server_status_client(c
);
1995 if (c
->flags
& CLIENT_READONLY
)
1998 window_pane_key(wp
, c
, s
, wl
, key
, m
);
2001 if (s
!= NULL
&& key
!= KEYC_FOCUS_OUT
)
2002 server_client_update_latest(c
);
2004 return (CMD_RETURN_NORMAL
);
2007 /* Handle a key event. */
2009 server_client_handle_key(struct client
*c
, struct key_event
*event
)
2011 struct session
*s
= c
->session
;
2012 struct cmdq_item
*item
;
2014 /* Check the client is good to accept input. */
2015 if (s
== NULL
|| (c
->flags
& CLIENT_UNATTACHEDFLAGS
))
2019 * Key presses in overlay mode and the command prompt are a special
2020 * case. The queue might be blocked so they need to be processed
2021 * immediately rather than queued.
2023 if (~c
->flags
& CLIENT_READONLY
) {
2024 if (c
->message_string
!= NULL
) {
2025 if (c
->message_ignore_keys
)
2027 status_message_clear(c
);
2029 if (c
->overlay_key
!= NULL
) {
2030 switch (c
->overlay_key(c
, c
->overlay_data
, event
)) {
2034 server_client_clear_overlay(c
);
2038 server_client_clear_overlay(c
);
2039 if (c
->prompt_string
!= NULL
) {
2040 if (status_prompt_key(c
, event
->key
) == 0)
2046 * Add the key to the queue so it happens after any commands queued by
2049 item
= cmdq_get_callback(server_client_key_callback
, event
);
2050 cmdq_append(c
, item
);
2054 /* Client functions that need to happen every loop. */
2056 server_client_loop(void)
2060 struct window_pane
*wp
;
2062 /* Check for window resize. This is done before redrawing. */
2063 RB_FOREACH(w
, windows
, &windows
)
2064 server_client_check_window_resize(w
);
2066 /* Check clients. */
2067 TAILQ_FOREACH(c
, &clients
, entry
) {
2068 server_client_check_exit(c
);
2069 if (c
->session
!= NULL
) {
2070 server_client_check_modes(c
);
2071 server_client_check_redraw(c
);
2072 server_client_reset_state(c
);
2077 * Any windows will have been redrawn as part of clients, so clear
2080 RB_FOREACH(w
, windows
, &windows
) {
2081 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
2083 server_client_check_pane_resize(wp
);
2084 server_client_check_pane_buffer(wp
);
2086 wp
->flags
&= ~PANE_REDRAW
;
2088 check_window_name(w
);
2092 /* Check if window needs to be resized. */
2094 server_client_check_window_resize(struct window
*w
)
2098 if (~w
->flags
& WINDOW_RESIZE
)
2101 TAILQ_FOREACH(wl
, &w
->winlinks
, wentry
) {
2102 if (wl
->session
->attached
!= 0 && wl
->session
->curw
== wl
)
2108 log_debug("%s: resizing window @%u", __func__
, w
->id
);
2109 resize_window(w
, w
->new_sx
, w
->new_sy
, w
->new_xpixel
, w
->new_ypixel
);
2112 /* Resize timer event. */
2114 server_client_resize_timer(__unused
int fd
, __unused
short events
, void *data
)
2116 struct window_pane
*wp
= data
;
2118 log_debug("%s: %%%u resize timer expired", __func__
, wp
->id
);
2119 evtimer_del(&wp
->resize_timer
);
2122 /* Check if pane should be resized. */
2124 server_client_check_pane_resize(struct window_pane
*wp
)
2126 struct window_pane_resize
*r
;
2127 struct window_pane_resize
*r1
;
2128 struct window_pane_resize
*first
;
2129 struct window_pane_resize
*last
;
2130 struct timeval tv
= { .tv_usec
= 250000 };
2132 if (TAILQ_EMPTY(&wp
->resize_queue
))
2135 if (!event_initialized(&wp
->resize_timer
))
2136 evtimer_set(&wp
->resize_timer
, server_client_resize_timer
, wp
);
2137 if (evtimer_pending(&wp
->resize_timer
, NULL
))
2140 log_debug("%s: %%%u needs to be resized", __func__
, wp
->id
);
2141 TAILQ_FOREACH(r
, &wp
->resize_queue
, entry
) {
2142 log_debug("queued resize: %ux%u -> %ux%u", r
->osx
, r
->osy
,
2147 * There are three cases that matter:
2149 * - Only one resize. It can just be applied.
2151 * - Multiple resizes and the ending size is different from the
2152 * starting size. We can discard all resizes except the most recent.
2154 * - Multiple resizes and the ending size is the same as the starting
2155 * size. We must resize at least twice to force the application to
2156 * redraw. So apply the first and leave the last on the queue for
2159 first
= TAILQ_FIRST(&wp
->resize_queue
);
2160 last
= TAILQ_LAST(&wp
->resize_queue
, window_pane_resizes
);
2161 if (first
== last
) {
2162 /* Only one resize. */
2163 window_pane_send_resize(wp
, first
->sx
, first
->sy
);
2164 TAILQ_REMOVE(&wp
->resize_queue
, first
, entry
);
2166 } else if (last
->sx
!= first
->osx
|| last
->sy
!= first
->osy
) {
2167 /* Multiple resizes ending up with a different size. */
2168 window_pane_send_resize(wp
, last
->sx
, last
->sy
);
2169 TAILQ_FOREACH_SAFE(r
, &wp
->resize_queue
, entry
, r1
) {
2170 TAILQ_REMOVE(&wp
->resize_queue
, r
, entry
);
2175 * Multiple resizes ending up with the same size. There will
2176 * not be more than one to the same size in succession so we
2177 * can just use the last-but-one on the list and leave the last
2178 * for later. We reduce the time until the next check to avoid
2179 * a long delay between the resizes.
2181 r
= TAILQ_PREV(last
, window_pane_resizes
, entry
);
2182 window_pane_send_resize(wp
, r
->sx
, r
->sy
);
2183 TAILQ_FOREACH_SAFE(r
, &wp
->resize_queue
, entry
, r1
) {
2186 TAILQ_REMOVE(&wp
->resize_queue
, r
, entry
);
2191 evtimer_add(&wp
->resize_timer
, &tv
);
2194 /* Check pane buffer size. */
2196 server_client_check_pane_buffer(struct window_pane
*wp
)
2198 struct evbuffer
*evb
= wp
->event
->input
;
2201 struct window_pane_offset
*wpo
;
2203 u_int attached_clients
= 0;
2207 * Work out the minimum used size. This is the most that can be removed
2210 minimum
= wp
->offset
.used
;
2211 if (wp
->pipe_fd
!= -1 && wp
->pipe_offset
.used
< minimum
)
2212 minimum
= wp
->pipe_offset
.used
;
2213 TAILQ_FOREACH(c
, &clients
, entry
) {
2214 if (c
->session
== NULL
)
2218 if (~c
->flags
& CLIENT_CONTROL
) {
2222 wpo
= control_pane_offset(c
, wp
, &flag
);
2230 window_pane_get_new_data(wp
, wpo
, &new_size
);
2231 log_debug("%s: %s has %zu bytes used and %zu left for %%%u",
2232 __func__
, c
->name
, wpo
->used
- wp
->base_offset
, new_size
,
2234 if (wpo
->used
< minimum
)
2235 minimum
= wpo
->used
;
2237 if (attached_clients
== 0)
2239 minimum
-= wp
->base_offset
;
2243 /* Drain the buffer. */
2244 log_debug("%s: %%%u has %zu minimum (of %zu) bytes used", __func__
,
2245 wp
->id
, minimum
, EVBUFFER_LENGTH(evb
));
2246 evbuffer_drain(evb
, minimum
);
2249 * Adjust the base offset. If it would roll over, all the offsets into
2250 * the buffer need to be adjusted.
2252 if (wp
->base_offset
> SIZE_MAX
- minimum
) {
2253 log_debug("%s: %%%u base offset has wrapped", __func__
, wp
->id
);
2254 wp
->offset
.used
-= wp
->base_offset
;
2255 if (wp
->pipe_fd
!= -1)
2256 wp
->pipe_offset
.used
-= wp
->base_offset
;
2257 TAILQ_FOREACH(c
, &clients
, entry
) {
2258 if (c
->session
== NULL
|| (~c
->flags
& CLIENT_CONTROL
))
2260 wpo
= control_pane_offset(c
, wp
, &flag
);
2261 if (wpo
!= NULL
&& !flag
)
2262 wpo
->used
-= wp
->base_offset
;
2264 wp
->base_offset
= minimum
;
2266 wp
->base_offset
+= minimum
;
2270 * If there is data remaining, and there are no clients able to consume
2271 * it, do not read any more. This is true when there are attached
2272 * clients, all of which are control clients which are not able to
2273 * accept any more data.
2275 log_debug("%s: pane %%%u is %s", __func__
, wp
->id
, off
? "off" : "on");
2277 bufferevent_disable(wp
->event
, EV_READ
);
2279 bufferevent_enable(wp
->event
, EV_READ
);
2283 * Update cursor position and mode settings. The scroll region and attributes
2284 * are cleared when idle (waiting for an event) as this is the most likely time
2285 * a user may interrupt tmux, for example with ~^Z in ssh(1). This is a
2286 * compromise between excessive resets and likelihood of an interrupt.
2288 * tty_region/tty_reset/tty_update_mode already take care of not resetting
2289 * things that are already in their default state.
2292 server_client_reset_state(struct client
*c
)
2294 struct tty
*tty
= &c
->tty
;
2295 struct window
*w
= c
->session
->curw
->window
;
2296 struct window_pane
*wp
= server_client_get_pane(c
), *loop
;
2297 struct screen
*s
= NULL
;
2298 struct options
*oo
= c
->session
->options
;
2299 int mode
= 0, cursor
, flags
, n
;
2300 u_int cx
= 0, cy
= 0, ox
, oy
, sx
, sy
;
2302 if (c
->flags
& (CLIENT_CONTROL
|CLIENT_SUSPENDED
))
2305 /* Disable the block flag. */
2306 flags
= (tty
->flags
& TTY_BLOCK
);
2307 tty
->flags
&= ~TTY_BLOCK
;
2309 /* Get mode from overlay if any, else from screen. */
2310 if (c
->overlay_draw
!= NULL
) {
2311 if (c
->overlay_mode
!= NULL
)
2312 s
= c
->overlay_mode(c
, c
->overlay_data
, &cx
, &cy
);
2317 if (log_get_level() != 0) {
2318 log_debug("%s: client %s mode %s", __func__
, c
->name
,
2319 screen_mode_to_string(mode
));
2322 /* Reset region and margin. */
2323 tty_region_off(tty
);
2324 tty_margin_off(tty
);
2326 /* Move cursor to pane cursor and offset. */
2327 if (c
->prompt_string
!= NULL
) {
2328 n
= options_get_number(c
->session
->options
, "status-position");
2332 n
= status_line_size(c
);
2338 cx
= c
->prompt_cursor
;
2339 mode
&= ~MODE_CURSOR
;
2340 } else if (c
->overlay_draw
== NULL
) {
2342 tty_window_offset(tty
, &ox
, &oy
, &sx
, &sy
);
2343 if (wp
->xoff
+ s
->cx
>= ox
&& wp
->xoff
+ s
->cx
<= ox
+ sx
&&
2344 wp
->yoff
+ s
->cy
>= oy
&& wp
->yoff
+ s
->cy
<= oy
+ sy
) {
2347 cx
= wp
->xoff
+ s
->cx
- ox
;
2348 cy
= wp
->yoff
+ s
->cy
- oy
;
2350 if (status_at_line(c
) == 0)
2351 cy
+= status_line_size(c
);
2354 mode
&= ~MODE_CURSOR
;
2356 log_debug("%s: cursor to %u,%u", __func__
, cx
, cy
);
2357 tty_cursor(tty
, cx
, cy
);
2360 * Set mouse mode if requested. To support dragging, always use button
2363 if (options_get_number(oo
, "mouse")) {
2364 if (c
->overlay_draw
== NULL
) {
2365 mode
&= ~ALL_MOUSE_MODES
;
2366 TAILQ_FOREACH(loop
, &w
->panes
, entry
) {
2367 if (loop
->screen
->mode
& MODE_MOUSE_ALL
)
2368 mode
|= MODE_MOUSE_ALL
;
2371 if (~mode
& MODE_MOUSE_ALL
)
2372 mode
|= MODE_MOUSE_BUTTON
;
2375 /* Clear bracketed paste mode if at the prompt. */
2376 if (c
->overlay_draw
== NULL
&& c
->prompt_string
!= NULL
)
2377 mode
&= ~MODE_BRACKETPASTE
;
2379 /* Set the terminal mode and reset attributes. */
2380 tty_update_mode(tty
, mode
, s
);
2383 /* All writing must be done, send a sync end (if it was started). */
2385 tty
->flags
|= flags
;
2388 /* Repeat time callback. */
2390 server_client_repeat_timer(__unused
int fd
, __unused
short events
, void *data
)
2392 struct client
*c
= data
;
2394 if (c
->flags
& CLIENT_REPEAT
) {
2395 server_client_set_key_table(c
, NULL
);
2396 c
->flags
&= ~CLIENT_REPEAT
;
2397 server_status_client(c
);
2401 /* Double-click callback. */
2403 server_client_click_timer(__unused
int fd
, __unused
short events
, void *data
)
2405 struct client
*c
= data
;
2406 struct key_event
*event
;
2408 log_debug("click timer expired");
2410 if (c
->flags
& CLIENT_TRIPLECLICK
) {
2412 * Waiting for a third click that hasn't happened, so this must
2413 * have been a double click.
2415 event
= xmalloc(sizeof *event
);
2416 event
->key
= KEYC_DOUBLECLICK
;
2417 memcpy(&event
->m
, &c
->click_event
, sizeof event
->m
);
2418 if (!server_client_handle_key(c
, event
))
2421 c
->flags
&= ~(CLIENT_DOUBLECLICK
|CLIENT_TRIPLECLICK
);
2424 /* Check if client should be exited. */
2426 server_client_check_exit(struct client
*c
)
2428 struct client_file
*cf
;
2429 const char *name
= c
->exit_session
;
2433 if (c
->flags
& (CLIENT_DEAD
|CLIENT_EXITED
))
2435 if (~c
->flags
& CLIENT_EXIT
)
2438 if (c
->flags
& CLIENT_CONTROL
) {
2440 if (!control_all_done(c
))
2443 RB_FOREACH(cf
, client_files
, &c
->files
) {
2444 if (EVBUFFER_LENGTH(cf
->buffer
) != 0)
2447 c
->flags
|= CLIENT_EXITED
;
2449 switch (c
->exit_type
) {
2450 case CLIENT_EXIT_RETURN
:
2451 if (c
->exit_message
!= NULL
)
2452 msize
= strlen(c
->exit_message
) + 1;
2455 size
= (sizeof c
->retval
) + msize
;
2456 data
= xmalloc(size
);
2457 memcpy(data
, &c
->retval
, sizeof c
->retval
);
2458 if (c
->exit_message
!= NULL
)
2459 memcpy(data
+ sizeof c
->retval
, c
->exit_message
, msize
);
2460 proc_send(c
->peer
, MSG_EXIT
, -1, data
, size
);
2463 case CLIENT_EXIT_SHUTDOWN
:
2464 proc_send(c
->peer
, MSG_SHUTDOWN
, -1, NULL
, 0);
2466 case CLIENT_EXIT_DETACH
:
2467 proc_send(c
->peer
, c
->exit_msgtype
, -1, name
, strlen(name
) + 1);
2470 free(c
->exit_session
);
2471 free(c
->exit_message
);
2474 /* Redraw timer callback. */
2476 server_client_redraw_timer(__unused
int fd
, __unused
short events
,
2477 __unused
void *data
)
2479 log_debug("redraw timer fired");
2483 * Check if modes need to be updated. Only modes in the current window are
2484 * updated and it is done when the status line is redrawn.
2487 server_client_check_modes(struct client
*c
)
2489 struct window
*w
= c
->session
->curw
->window
;
2490 struct window_pane
*wp
;
2491 struct window_mode_entry
*wme
;
2493 if (c
->flags
& (CLIENT_CONTROL
|CLIENT_SUSPENDED
))
2495 if (~c
->flags
& CLIENT_REDRAWSTATUS
)
2497 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
2498 wme
= TAILQ_FIRST(&wp
->modes
);
2499 if (wme
!= NULL
&& wme
->mode
->update
!= NULL
)
2500 wme
->mode
->update(wme
);
2504 /* Check for client redraws. */
2506 server_client_check_redraw(struct client
*c
)
2508 struct session
*s
= c
->session
;
2509 struct tty
*tty
= &c
->tty
;
2510 struct window
*w
= c
->session
->curw
->window
;
2511 struct window_pane
*wp
;
2512 int needed
, flags
, mode
= tty
->mode
, new_flags
= 0;
2515 struct timeval tv
= { .tv_usec
= 1000 };
2516 static struct event ev
;
2519 if (c
->flags
& (CLIENT_CONTROL
|CLIENT_SUSPENDED
))
2521 if (c
->flags
& CLIENT_ALLREDRAWFLAGS
) {
2522 log_debug("%s: redraw%s%s%s%s%s", c
->name
,
2523 (c
->flags
& CLIENT_REDRAWWINDOW
) ? " window" : "",
2524 (c
->flags
& CLIENT_REDRAWSTATUS
) ? " status" : "",
2525 (c
->flags
& CLIENT_REDRAWBORDERS
) ? " borders" : "",
2526 (c
->flags
& CLIENT_REDRAWOVERLAY
) ? " overlay" : "",
2527 (c
->flags
& CLIENT_REDRAWPANES
) ? " panes" : "");
2531 * If there is outstanding data, defer the redraw until it has been
2532 * consumed. We can just add a timer to get out of the event loop and
2536 if (c
->flags
& CLIENT_ALLREDRAWFLAGS
)
2539 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
2540 if (wp
->flags
& PANE_REDRAW
) {
2546 new_flags
|= CLIENT_REDRAWPANES
;
2548 if (needed
&& (left
= EVBUFFER_LENGTH(tty
->out
)) != 0) {
2549 log_debug("%s: redraw deferred (%zu left)", c
->name
, left
);
2550 if (!evtimer_initialized(&ev
))
2551 evtimer_set(&ev
, server_client_redraw_timer
, NULL
);
2552 if (!evtimer_pending(&ev
, NULL
)) {
2553 log_debug("redraw timer started");
2554 evtimer_add(&ev
, &tv
);
2557 if (~c
->flags
& CLIENT_REDRAWWINDOW
) {
2558 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
2559 if (wp
->flags
& PANE_REDRAW
) {
2560 log_debug("%s: pane %%%u needs redraw",
2562 c
->redraw_panes
|= (1 << bit
);
2566 * If more that 64 panes, give up and
2567 * just redraw the window.
2569 new_flags
&= CLIENT_REDRAWPANES
;
2570 new_flags
|= CLIENT_REDRAWWINDOW
;
2574 if (c
->redraw_panes
!= 0)
2575 c
->flags
|= CLIENT_REDRAWPANES
;
2577 c
->flags
|= new_flags
;
2580 log_debug("%s: redraw needed", c
->name
);
2582 flags
= tty
->flags
& (TTY_BLOCK
|TTY_FREEZE
|TTY_NOCURSOR
);
2583 tty
->flags
= (tty
->flags
& ~(TTY_BLOCK
|TTY_FREEZE
))|TTY_NOCURSOR
;
2585 if (~c
->flags
& CLIENT_REDRAWWINDOW
) {
2587 * If not redrawing the entire window, check whether each pane
2588 * needs to be redrawn.
2590 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
2592 if (wp
->flags
& PANE_REDRAW
)
2594 else if (c
->flags
& CLIENT_REDRAWPANES
)
2595 redraw
= !!(c
->redraw_panes
& (1 << bit
));
2599 log_debug("%s: redrawing pane %%%u", __func__
, wp
->id
);
2600 screen_redraw_pane(c
, wp
);
2602 c
->redraw_panes
= 0;
2603 c
->flags
&= ~CLIENT_REDRAWPANES
;
2606 if (c
->flags
& CLIENT_ALLREDRAWFLAGS
) {
2607 if (options_get_number(s
->options
, "set-titles")) {
2608 server_client_set_title(c
);
2609 server_client_set_path(c
);
2611 screen_redraw_screen(c
);
2614 tty
->flags
= (tty
->flags
& ~TTY_NOCURSOR
)|(flags
& TTY_NOCURSOR
);
2615 tty_update_mode(tty
, mode
, NULL
);
2616 tty
->flags
= (tty
->flags
& ~(TTY_BLOCK
|TTY_FREEZE
|TTY_NOCURSOR
))|flags
;
2618 c
->flags
&= ~(CLIENT_ALLREDRAWFLAGS
|CLIENT_STATUSFORCE
);
2622 * We would have deferred the redraw unless the output buffer
2623 * was empty, so we can record how many bytes the redraw
2626 c
->redraw
= EVBUFFER_LENGTH(tty
->out
);
2627 log_debug("%s: redraw added %zu bytes", c
->name
, c
->redraw
);
2631 /* Set client title. */
2633 server_client_set_title(struct client
*c
)
2635 struct session
*s
= c
->session
;
2636 const char *template;
2638 struct format_tree
*ft
;
2640 template = options_get_string(s
->options
, "set-titles-string");
2642 ft
= format_create(c
, NULL
, FORMAT_NONE
, 0);
2643 format_defaults(ft
, c
, NULL
, NULL
, NULL
);
2645 title
= format_expand_time(ft
, template);
2646 if (c
->title
== NULL
|| strcmp(title
, c
->title
) != 0) {
2648 c
->title
= xstrdup(title
);
2649 tty_set_title(&c
->tty
, c
->title
);
2656 /* Set client path. */
2658 server_client_set_path(struct client
*c
)
2660 struct session
*s
= c
->session
;
2663 if (s
->curw
== NULL
)
2665 if (s
->curw
->window
->active
->base
.path
== NULL
)
2668 path
= s
->curw
->window
->active
->base
.path
;
2669 if (c
->path
== NULL
|| strcmp(path
, c
->path
) != 0) {
2671 c
->path
= xstrdup(path
);
2672 tty_set_path(&c
->tty
, c
->path
);
2676 /* Dispatch message from client. */
2678 server_client_dispatch(struct imsg
*imsg
, void *arg
)
2680 struct client
*c
= arg
;
2684 if (c
->flags
& CLIENT_DEAD
)
2688 server_client_lost(c
);
2692 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
2694 switch (imsg
->hdr
.type
) {
2695 case MSG_IDENTIFY_CLIENTPID
:
2696 case MSG_IDENTIFY_CWD
:
2697 case MSG_IDENTIFY_ENVIRON
:
2698 case MSG_IDENTIFY_FEATURES
:
2699 case MSG_IDENTIFY_FLAGS
:
2700 case MSG_IDENTIFY_LONGFLAGS
:
2701 case MSG_IDENTIFY_STDIN
:
2702 case MSG_IDENTIFY_STDOUT
:
2703 case MSG_IDENTIFY_TERM
:
2704 case MSG_IDENTIFY_TERMINFO
:
2705 case MSG_IDENTIFY_TTYNAME
:
2706 case MSG_IDENTIFY_DONE
:
2707 server_client_dispatch_identify(c
, imsg
);
2710 server_client_dispatch_command(c
, imsg
);
2714 fatalx("bad MSG_RESIZE size");
2716 if (c
->flags
& CLIENT_CONTROL
)
2718 server_client_update_latest(c
);
2719 tty_resize(&c
->tty
);
2720 recalculate_sizes();
2721 if (c
->overlay_resize
== NULL
)
2722 server_client_clear_overlay(c
);
2724 c
->overlay_resize(c
, c
->overlay_data
);
2725 server_redraw_client(c
);
2726 if (c
->session
!= NULL
)
2727 notify_client("client-resized", c
);
2731 fatalx("bad MSG_EXITING size");
2732 server_client_set_session(c
, NULL
);
2733 recalculate_sizes();
2735 proc_send(c
->peer
, MSG_EXITED
, -1, NULL
, 0);
2740 fatalx("bad MSG_WAKEUP size");
2742 if (!(c
->flags
& CLIENT_SUSPENDED
))
2744 c
->flags
&= ~CLIENT_SUSPENDED
;
2746 if (c
->fd
== -1 || c
->session
== NULL
) /* exited already */
2750 if (gettimeofday(&c
->activity_time
, NULL
) != 0)
2751 fatal("gettimeofday failed");
2753 tty_start_tty(&c
->tty
);
2754 server_redraw_client(c
);
2755 recalculate_sizes();
2758 session_update_activity(s
, &c
->activity_time
);
2762 fatalx("bad MSG_SHELL size");
2764 server_client_dispatch_shell(c
);
2766 case MSG_WRITE_READY
:
2767 file_write_ready(&c
->files
, imsg
);
2770 file_read_data(&c
->files
, imsg
);
2773 file_read_done(&c
->files
, imsg
);
2778 /* Callback when command is done. */
2779 static enum cmd_retval
2780 server_client_command_done(struct cmdq_item
*item
, __unused
void *data
)
2782 struct client
*c
= cmdq_get_client(item
);
2784 if (~c
->flags
& CLIENT_ATTACHED
)
2785 c
->flags
|= CLIENT_EXIT
;
2786 else if (~c
->flags
& CLIENT_EXIT
)
2787 tty_send_requests(&c
->tty
);
2788 return (CMD_RETURN_NORMAL
);
2791 /* Handle command message. */
2793 server_client_dispatch_command(struct client
*c
, struct imsg
*imsg
)
2795 struct msg_command data
;
2799 char **argv
, *cause
;
2800 struct cmd_parse_result
*pr
;
2801 struct args_value
*values
;
2803 if (c
->flags
& CLIENT_EXIT
)
2806 if (imsg
->hdr
.len
- IMSG_HEADER_SIZE
< sizeof data
)
2807 fatalx("bad MSG_COMMAND size");
2808 memcpy(&data
, imsg
->data
, sizeof data
);
2810 buf
= (char *)imsg
->data
+ sizeof data
;
2811 len
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
- sizeof data
;
2812 if (len
> 0 && buf
[len
- 1] != '\0')
2813 fatalx("bad MSG_COMMAND string");
2816 if (cmd_unpack_argv(buf
, len
, argc
, &argv
) != 0) {
2817 cause
= xstrdup("command too long");
2823 argv
= xcalloc(1, sizeof *argv
);
2824 *argv
= xstrdup("new-session");
2827 values
= args_from_vector(argc
, argv
);
2828 pr
= cmd_parse_from_arguments(values
, argc
, NULL
);
2829 switch (pr
->status
) {
2830 case CMD_PARSE_ERROR
:
2833 case CMD_PARSE_SUCCESS
:
2836 args_free_values(values
, argc
);
2838 cmd_free_argv(argc
, argv
);
2840 cmdq_append(c
, cmdq_get_command(pr
->cmdlist
, NULL
));
2841 cmdq_append(c
, cmdq_get_callback(server_client_command_done
, NULL
));
2843 cmd_list_free(pr
->cmdlist
);
2847 cmd_free_argv(argc
, argv
);
2849 cmdq_append(c
, cmdq_get_error(cause
));
2852 c
->flags
|= CLIENT_EXIT
;
2855 /* Handle identify message. */
2857 server_client_dispatch_identify(struct client
*c
, struct imsg
*imsg
)
2859 const char *data
, *home
;
2865 if (c
->flags
& CLIENT_IDENTIFIED
)
2866 fatalx("out-of-order identify message");
2869 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
2871 switch (imsg
->hdr
.type
) {
2872 case MSG_IDENTIFY_FEATURES
:
2873 if (datalen
!= sizeof feat
)
2874 fatalx("bad MSG_IDENTIFY_FEATURES size");
2875 memcpy(&feat
, data
, sizeof feat
);
2876 c
->term_features
|= feat
;
2877 log_debug("client %p IDENTIFY_FEATURES %s", c
,
2878 tty_get_features(feat
));
2880 case MSG_IDENTIFY_FLAGS
:
2881 if (datalen
!= sizeof flags
)
2882 fatalx("bad MSG_IDENTIFY_FLAGS size");
2883 memcpy(&flags
, data
, sizeof flags
);
2885 log_debug("client %p IDENTIFY_FLAGS %#x", c
, flags
);
2887 case MSG_IDENTIFY_LONGFLAGS
:
2888 if (datalen
!= sizeof longflags
)
2889 fatalx("bad MSG_IDENTIFY_LONGFLAGS size");
2890 memcpy(&longflags
, data
, sizeof longflags
);
2891 c
->flags
|= longflags
;
2892 log_debug("client %p IDENTIFY_LONGFLAGS %#llx", c
,
2893 (unsigned long long)longflags
);
2895 case MSG_IDENTIFY_TERM
:
2896 if (datalen
== 0 || data
[datalen
- 1] != '\0')
2897 fatalx("bad MSG_IDENTIFY_TERM string");
2899 c
->term_name
= xstrdup("unknown");
2901 c
->term_name
= xstrdup(data
);
2902 log_debug("client %p IDENTIFY_TERM %s", c
, data
);
2904 case MSG_IDENTIFY_TERMINFO
:
2905 if (datalen
== 0 || data
[datalen
- 1] != '\0')
2906 fatalx("bad MSG_IDENTIFY_TERMINFO string");
2907 c
->term_caps
= xreallocarray(c
->term_caps
, c
->term_ncaps
+ 1,
2908 sizeof *c
->term_caps
);
2909 c
->term_caps
[c
->term_ncaps
++] = xstrdup(data
);
2910 log_debug("client %p IDENTIFY_TERMINFO %s", c
, data
);
2912 case MSG_IDENTIFY_TTYNAME
:
2913 if (datalen
== 0 || data
[datalen
- 1] != '\0')
2914 fatalx("bad MSG_IDENTIFY_TTYNAME string");
2915 c
->ttyname
= xstrdup(data
);
2916 log_debug("client %p IDENTIFY_TTYNAME %s", c
, data
);
2918 case MSG_IDENTIFY_CWD
:
2919 if (datalen
== 0 || data
[datalen
- 1] != '\0')
2920 fatalx("bad MSG_IDENTIFY_CWD string");
2921 if (access(data
, X_OK
) == 0)
2922 c
->cwd
= xstrdup(data
);
2923 else if ((home
= find_home()) != NULL
)
2924 c
->cwd
= xstrdup(home
);
2926 c
->cwd
= xstrdup("/");
2927 log_debug("client %p IDENTIFY_CWD %s", c
, data
);
2929 case MSG_IDENTIFY_STDIN
:
2931 fatalx("bad MSG_IDENTIFY_STDIN size");
2933 log_debug("client %p IDENTIFY_STDIN %d", c
, imsg
->fd
);
2935 case MSG_IDENTIFY_STDOUT
:
2937 fatalx("bad MSG_IDENTIFY_STDOUT size");
2938 c
->out_fd
= imsg
->fd
;
2939 log_debug("client %p IDENTIFY_STDOUT %d", c
, imsg
->fd
);
2941 case MSG_IDENTIFY_ENVIRON
:
2942 if (datalen
== 0 || data
[datalen
- 1] != '\0')
2943 fatalx("bad MSG_IDENTIFY_ENVIRON string");
2944 if (strchr(data
, '=') != NULL
)
2945 environ_put(c
->environ
, data
, 0);
2946 log_debug("client %p IDENTIFY_ENVIRON %s", c
, data
);
2948 case MSG_IDENTIFY_CLIENTPID
:
2949 if (datalen
!= sizeof c
->pid
)
2950 fatalx("bad MSG_IDENTIFY_CLIENTPID size");
2951 memcpy(&c
->pid
, data
, sizeof c
->pid
);
2952 log_debug("client %p IDENTIFY_CLIENTPID %ld", c
, (long)c
->pid
);
2958 if (imsg
->hdr
.type
!= MSG_IDENTIFY_DONE
)
2960 c
->flags
|= CLIENT_IDENTIFIED
;
2962 if (*c
->ttyname
!= '\0')
2963 name
= xstrdup(c
->ttyname
);
2965 xasprintf(&name
, "client-%ld", (long)c
->pid
);
2967 log_debug("client %p name is %s", c
, c
->name
);
2969 if (c
->flags
& CLIENT_CONTROL
)
2971 else if (c
->fd
!= -1) {
2972 if (tty_init(&c
->tty
, c
) != 0) {
2976 tty_resize(&c
->tty
);
2977 c
->flags
|= CLIENT_TERMINAL
;
2984 * If this is the first client, load configuration files. Any later
2985 * clients are allowed to continue with their command even if the
2986 * config has not been loaded - they might have been run from inside it
2988 if ((~c
->flags
& CLIENT_EXIT
) &&
2990 c
== TAILQ_FIRST(&clients
))
2994 /* Handle shell message. */
2996 server_client_dispatch_shell(struct client
*c
)
3000 shell
= options_get_string(global_s_options
, "default-shell");
3001 if (!checkshell(shell
))
3002 shell
= _PATH_BSHELL
;
3003 proc_send(c
->peer
, MSG_SHELL
, -1, shell
, strlen(shell
) + 1);
3005 proc_kill_peer(c
->peer
);
3008 /* Get client working directory. */
3010 server_client_get_cwd(struct client
*c
, struct session
*s
)
3014 if (!cfg_finished
&& cfg_client
!= NULL
)
3015 return (cfg_client
->cwd
);
3016 if (c
!= NULL
&& c
->session
== NULL
&& c
->cwd
!= NULL
)
3018 if (s
!= NULL
&& s
->cwd
!= NULL
)
3020 if (c
!= NULL
&& (s
= c
->session
) != NULL
&& s
->cwd
!= NULL
)
3022 if ((home
= find_home()) != NULL
)
3027 /* Get control client flags. */
3029 server_client_control_flags(struct client
*c
, const char *next
)
3031 if (strcmp(next
, "pause-after") == 0) {
3033 return (CLIENT_CONTROL_PAUSEAFTER
);
3035 if (sscanf(next
, "pause-after=%u", &c
->pause_age
) == 1) {
3036 c
->pause_age
*= 1000;
3037 return (CLIENT_CONTROL_PAUSEAFTER
);
3039 if (strcmp(next
, "no-output") == 0)
3040 return (CLIENT_CONTROL_NOOUTPUT
);
3041 if (strcmp(next
, "wait-exit") == 0)
3042 return (CLIENT_CONTROL_WAITEXIT
);
3046 /* Set client flags. */
3048 server_client_set_flags(struct client
*c
, const char *flags
)
3050 char *s
, *copy
, *next
;
3054 s
= copy
= xstrdup(flags
);
3055 while ((next
= strsep(&s
, ",")) != NULL
) {
3056 not = (*next
== '!');
3060 if (c
->flags
& CLIENT_CONTROL
)
3061 flag
= server_client_control_flags(c
, next
);
3064 if (strcmp(next
, "read-only") == 0)
3065 flag
= CLIENT_READONLY
;
3066 else if (strcmp(next
, "ignore-size") == 0)
3067 flag
= CLIENT_IGNORESIZE
;
3068 else if (strcmp(next
, "active-pane") == 0)
3069 flag
= CLIENT_ACTIVEPANE
;
3073 log_debug("client %s set flag %s", c
->name
, next
);
3078 if (flag
== CLIENT_CONTROL_NOOUTPUT
)
3079 control_reset_offsets(c
);
3082 proc_send(c
->peer
, MSG_FLAGS
, -1, &c
->flags
, sizeof c
->flags
);
3085 /* Get client flags. This is only flags useful to show to users. */
3087 server_client_get_flags(struct client
*c
)
3093 if (c
->flags
& CLIENT_ATTACHED
)
3094 strlcat(s
, "attached,", sizeof s
);
3095 if (c
->flags
& CLIENT_FOCUSED
)
3096 strlcat(s
, "focused,", sizeof s
);
3097 if (c
->flags
& CLIENT_CONTROL
)
3098 strlcat(s
, "control-mode,", sizeof s
);
3099 if (c
->flags
& CLIENT_IGNORESIZE
)
3100 strlcat(s
, "ignore-size,", sizeof s
);
3101 if (c
->flags
& CLIENT_CONTROL_NOOUTPUT
)
3102 strlcat(s
, "no-output,", sizeof s
);
3103 if (c
->flags
& CLIENT_CONTROL_WAITEXIT
)
3104 strlcat(s
, "wait-exit,", sizeof s
);
3105 if (c
->flags
& CLIENT_CONTROL_PAUSEAFTER
) {
3106 xsnprintf(tmp
, sizeof tmp
, "pause-after=%u,",
3107 c
->pause_age
/ 1000);
3108 strlcat(s
, tmp
, sizeof s
);
3110 if (c
->flags
& CLIENT_READONLY
)
3111 strlcat(s
, "read-only,", sizeof s
);
3112 if (c
->flags
& CLIENT_ACTIVEPANE
)
3113 strlcat(s
, "active-pane,", sizeof s
);
3114 if (c
->flags
& CLIENT_SUSPENDED
)
3115 strlcat(s
, "suspended,", sizeof s
);
3116 if (c
->flags
& CLIENT_UTF8
)
3117 strlcat(s
, "UTF-8,", sizeof s
);
3119 s
[strlen(s
) - 1] = '\0';
3123 /* Get client window. */
3124 struct client_window
*
3125 server_client_get_client_window(struct client
*c
, u_int id
)
3127 struct client_window cw
= { .window
= id
};
3129 return (RB_FIND(client_windows
, &c
->windows
, &cw
));
3132 /* Add client window. */
3133 struct client_window
*
3134 server_client_add_client_window(struct client
*c
, u_int id
)
3136 struct client_window
*cw
;
3138 cw
= server_client_get_client_window(c
, id
);
3140 cw
= xcalloc(1, sizeof *cw
);
3142 RB_INSERT(client_windows
, &c
->windows
, cw
);
3147 /* Get client active pane. */
3148 struct window_pane
*
3149 server_client_get_pane(struct client
*c
)
3151 struct session
*s
= c
->session
;
3152 struct client_window
*cw
;
3157 if (~c
->flags
& CLIENT_ACTIVEPANE
)
3158 return (s
->curw
->window
->active
);
3159 cw
= server_client_get_client_window(c
, s
->curw
->window
->id
);
3161 return (s
->curw
->window
->active
);
3165 /* Set client active pane. */
3167 server_client_set_pane(struct client
*c
, struct window_pane
*wp
)
3169 struct session
*s
= c
->session
;
3170 struct client_window
*cw
;
3175 cw
= server_client_add_client_window(c
, s
->curw
->window
->id
);
3177 log_debug("%s pane now %%%u", c
->name
, wp
->id
);
3180 /* Remove pane from client lists. */
3182 server_client_remove_pane(struct window_pane
*wp
)
3185 struct window
*w
= wp
->window
;
3186 struct client_window
*cw
;
3188 TAILQ_FOREACH(c
, &clients
, entry
) {
3189 cw
= server_client_get_client_window(c
, w
->id
);
3190 if (cw
!= NULL
&& cw
->pane
== wp
) {
3191 RB_REMOVE(client_windows
, &c
->windows
, cw
);