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_reset_state(struct client
*);
47 static int server_client_assume_paste(struct session
*);
48 static void server_client_update_latest(struct client
*);
50 static void server_client_dispatch(struct imsg
*, void *);
51 static void server_client_dispatch_command(struct client
*, struct imsg
*);
52 static void server_client_dispatch_identify(struct client
*, struct imsg
*);
53 static void server_client_dispatch_shell(struct client
*);
55 /* Compare client windows. */
57 server_client_window_cmp(struct client_window
*cw1
,
58 struct client_window
*cw2
)
60 if (cw1
->window
< cw2
->window
)
62 if (cw1
->window
> cw2
->window
)
66 RB_GENERATE(client_windows
, client_window
, entry
, server_client_window_cmp
);
68 /* Number of attached clients. */
70 server_client_how_many(void)
76 TAILQ_FOREACH(c
, &clients
, entry
) {
77 if (c
->session
!= NULL
&& (~c
->flags
& CLIENT_UNATTACHEDFLAGS
))
83 /* Overlay timer callback. */
85 server_client_overlay_timer(__unused
int fd
, __unused
short events
, void *data
)
87 server_client_clear_overlay(data
);
90 /* Set an overlay on client. */
92 server_client_set_overlay(struct client
*c
, u_int delay
,
93 overlay_check_cb checkcb
, overlay_mode_cb modecb
,
94 overlay_draw_cb drawcb
, overlay_key_cb keycb
, overlay_free_cb freecb
,
95 overlay_resize_cb resizecb
, void *data
)
99 if (c
->overlay_draw
!= NULL
)
100 server_client_clear_overlay(c
);
102 tv
.tv_sec
= delay
/ 1000;
103 tv
.tv_usec
= (delay
% 1000) * 1000L;
105 if (event_initialized(&c
->overlay_timer
))
106 evtimer_del(&c
->overlay_timer
);
107 evtimer_set(&c
->overlay_timer
, server_client_overlay_timer
, c
);
109 evtimer_add(&c
->overlay_timer
, &tv
);
111 c
->overlay_check
= checkcb
;
112 c
->overlay_mode
= modecb
;
113 c
->overlay_draw
= drawcb
;
114 c
->overlay_key
= keycb
;
115 c
->overlay_free
= freecb
;
116 c
->overlay_resize
= resizecb
;
117 c
->overlay_data
= data
;
119 if (c
->overlay_check
== NULL
)
120 c
->tty
.flags
|= TTY_FREEZE
;
121 if (c
->overlay_mode
== NULL
)
122 c
->tty
.flags
|= TTY_NOCURSOR
;
123 server_redraw_client(c
);
126 /* Clear overlay mode on client. */
128 server_client_clear_overlay(struct client
*c
)
130 if (c
->overlay_draw
== NULL
)
133 if (event_initialized(&c
->overlay_timer
))
134 evtimer_del(&c
->overlay_timer
);
136 if (c
->overlay_free
!= NULL
)
137 c
->overlay_free(c
, c
->overlay_data
);
139 c
->overlay_check
= NULL
;
140 c
->overlay_mode
= NULL
;
141 c
->overlay_draw
= NULL
;
142 c
->overlay_key
= NULL
;
143 c
->overlay_free
= NULL
;
144 c
->overlay_data
= NULL
;
146 c
->tty
.flags
&= ~(TTY_FREEZE
|TTY_NOCURSOR
);
147 server_redraw_client(c
);
151 * Given overlay position and dimensions, return parts of the input range which
155 server_client_overlay_range(u_int x
, u_int y
, u_int sx
, u_int sy
, u_int px
,
156 u_int py
, u_int nx
, struct overlay_ranges
*r
)
160 /* Return up to 2 ranges. */
164 /* Trivial case of no overlap in the y direction. */
165 if (py
< y
|| py
> y
+ sy
- 1) {
173 /* Visible bit to the left of the popup. */
184 /* Visible bit to the right of the popup. */
198 /* Check if this client is inside this server. */
200 server_client_check_nested(struct client
*c
)
202 struct environ_entry
*envent
;
203 struct window_pane
*wp
;
205 envent
= environ_find(c
->environ
, "TMUX");
206 if (envent
== NULL
|| *envent
->value
== '\0')
209 RB_FOREACH(wp
, window_pane_tree
, &all_window_panes
) {
210 if (strcmp(wp
->tty
, c
->ttyname
) == 0)
216 /* Set client key table. */
218 server_client_set_key_table(struct client
*c
, const char *name
)
221 name
= server_client_get_key_table(c
);
223 key_bindings_unref_table(c
->keytable
);
224 c
->keytable
= key_bindings_get_table(name
, 1);
225 c
->keytable
->references
++;
228 /* Get default key table. */
230 server_client_get_key_table(struct client
*c
)
232 struct session
*s
= c
->session
;
238 name
= options_get_string(s
->options
, "key-table");
244 /* Is this table the default key table? */
246 server_client_is_default_key_table(struct client
*c
, struct key_table
*table
)
248 return (strcmp(table
->name
, server_client_get_key_table(c
)) == 0);
251 /* Create a new client. */
253 server_client_create(int fd
)
259 c
= xcalloc(1, sizeof *c
);
261 c
->peer
= proc_add_peer(server_proc
, fd
, server_client_dispatch
, c
);
263 if (gettimeofday(&c
->creation_time
, NULL
) != 0)
264 fatal("gettimeofday failed");
265 memcpy(&c
->activity_time
, &c
->creation_time
, sizeof c
->activity_time
);
267 c
->environ
= environ_create();
272 c
->queue
= cmdq_new();
273 RB_INIT(&c
->windows
);
280 c
->flags
|= CLIENT_FOCUSED
;
282 c
->keytable
= key_bindings_get_table("root", 1);
283 c
->keytable
->references
++;
285 evtimer_set(&c
->repeat_timer
, server_client_repeat_timer
, c
);
286 evtimer_set(&c
->click_timer
, server_client_click_timer
, c
);
288 TAILQ_INSERT_TAIL(&clients
, c
, entry
);
289 log_debug("new client %p", c
);
293 /* Open client terminal if needed. */
295 server_client_open(struct client
*c
, char **cause
)
297 const char *ttynam
= _PATH_TTY
;
299 if (c
->flags
& CLIENT_CONTROL
)
302 if (strcmp(c
->ttyname
, ttynam
) == 0||
303 ((isatty(STDIN_FILENO
) &&
304 (ttynam
= ttyname(STDIN_FILENO
)) != NULL
&&
305 strcmp(c
->ttyname
, ttynam
) == 0) ||
306 (isatty(STDOUT_FILENO
) &&
307 (ttynam
= ttyname(STDOUT_FILENO
)) != NULL
&&
308 strcmp(c
->ttyname
, ttynam
) == 0) ||
309 (isatty(STDERR_FILENO
) &&
310 (ttynam
= ttyname(STDERR_FILENO
)) != NULL
&&
311 strcmp(c
->ttyname
, ttynam
) == 0))) {
312 xasprintf(cause
, "can't use %s", c
->ttyname
);
316 if (!(c
->flags
& CLIENT_TERMINAL
)) {
317 *cause
= xstrdup("not a terminal");
321 if (tty_open(&c
->tty
, cause
) != 0)
327 /* Lost an attached client. */
329 server_client_attached_lost(struct client
*c
)
334 struct client
*found
;
336 log_debug("lost attached client %p", c
);
339 * By this point the session in the client has been cleared so walk all
340 * windows to find any with this client as the latest.
342 RB_FOREACH(w
, windows
, &windows
) {
347 TAILQ_FOREACH(loop
, &clients
, entry
) {
349 if (loop
== c
|| s
== NULL
|| s
->curw
->window
!= w
)
351 if (found
== NULL
|| timercmp(&loop
->activity_time
,
352 &found
->activity_time
, >))
356 server_client_update_latest(found
);
360 /* Set client session. */
362 server_client_set_session(struct client
*c
, struct session
*s
)
364 struct session
*old
= c
->session
;
366 if (s
!= NULL
&& c
->session
!= NULL
&& c
->session
!= s
)
367 c
->last_session
= c
->session
;
369 c
->last_session
= NULL
;
371 c
->flags
|= CLIENT_FOCUSED
;
373 if (old
!= NULL
&& old
->curw
!= NULL
)
374 window_update_focus(old
->curw
->window
);
377 window_update_focus(s
->curw
->window
);
378 session_update_activity(s
, NULL
);
379 gettimeofday(&s
->last_attached_time
, NULL
);
380 s
->curw
->flags
&= ~WINLINK_ALERTFLAGS
;
381 s
->curw
->window
->latest
= c
;
382 alerts_check_session(s
);
383 tty_update_client_offset(c
);
384 status_timer_start(c
);
385 notify_client("client-session-changed", c
);
386 server_redraw_client(c
);
389 server_check_unattached();
390 server_update_socket();
395 server_client_lost(struct client
*c
)
397 struct client_file
*cf
, *cf1
;
398 struct client_window
*cw
, *cw1
;
400 c
->flags
|= CLIENT_DEAD
;
402 server_client_clear_overlay(c
);
403 status_prompt_clear(c
);
404 status_message_clear(c
);
406 RB_FOREACH_SAFE(cf
, client_files
, &c
->files
, cf1
) {
410 RB_FOREACH_SAFE(cw
, client_windows
, &c
->windows
, cw1
) {
411 RB_REMOVE(client_windows
, &c
->windows
, cw
);
415 TAILQ_REMOVE(&clients
, c
, entry
);
416 log_debug("lost client %p", c
);
418 if (c
->flags
& CLIENT_ATTACHED
) {
419 server_client_attached_lost(c
);
420 notify_client("client-detached", c
);
423 if (c
->flags
& CLIENT_CONTROL
)
425 if (c
->flags
& CLIENT_TERMINAL
)
428 free(c
->clipboard_panes
);
432 tty_term_free_list(c
->term_caps
, c
->term_ncaps
);
437 free((void *)c
->cwd
);
439 evtimer_del(&c
->repeat_timer
);
440 evtimer_del(&c
->click_timer
);
442 key_bindings_unref_table(c
->keytable
);
444 free(c
->message_string
);
445 if (event_initialized(&c
->message_timer
))
446 evtimer_del(&c
->message_timer
);
448 free(c
->prompt_saved
);
449 free(c
->prompt_string
);
450 free(c
->prompt_buffer
);
452 format_lost_client(c
);
453 environ_free(c
->environ
);
455 proc_remove_peer(c
->peer
);
464 server_client_unref(c
);
466 server_add_accept(0); /* may be more file descriptors now */
469 server_check_unattached();
470 server_update_socket();
473 /* Remove reference from a client. */
475 server_client_unref(struct client
*c
)
477 log_debug("unref client %p (%d references)", c
, c
->references
);
480 if (c
->references
== 0)
481 event_once(-1, EV_TIMEOUT
, server_client_free
, c
, NULL
);
484 /* Free dead client. */
486 server_client_free(__unused
int fd
, __unused
short events
, void *arg
)
488 struct client
*c
= arg
;
490 log_debug("free client %p (%d references)", c
, c
->references
);
494 if (c
->references
== 0) {
495 free((void *)c
->name
);
500 /* Suspend a client. */
502 server_client_suspend(struct client
*c
)
504 struct session
*s
= c
->session
;
506 if (s
== NULL
|| (c
->flags
& CLIENT_UNATTACHEDFLAGS
))
509 tty_stop_tty(&c
->tty
);
510 c
->flags
|= CLIENT_SUSPENDED
;
511 proc_send(c
->peer
, MSG_SUSPEND
, -1, NULL
, 0);
514 /* Detach a client. */
516 server_client_detach(struct client
*c
, enum msgtype msgtype
)
518 struct session
*s
= c
->session
;
520 if (s
== NULL
|| (c
->flags
& CLIENT_NODETACHFLAGS
))
523 c
->flags
|= CLIENT_EXIT
;
525 c
->exit_type
= CLIENT_EXIT_DETACH
;
526 c
->exit_msgtype
= msgtype
;
527 c
->exit_session
= xstrdup(s
->name
);
530 /* Execute command to replace a client. */
532 server_client_exec(struct client
*c
, const char *cmd
)
534 struct session
*s
= c
->session
;
537 size_t cmdsize
, shellsize
;
541 cmdsize
= strlen(cmd
) + 1;
544 shell
= options_get_string(s
->options
, "default-shell");
546 shell
= options_get_string(global_s_options
, "default-shell");
547 if (!checkshell(shell
))
548 shell
= _PATH_BSHELL
;
549 shellsize
= strlen(shell
) + 1;
551 msg
= xmalloc(cmdsize
+ shellsize
);
552 memcpy(msg
, cmd
, cmdsize
);
553 memcpy(msg
+ cmdsize
, shell
, shellsize
);
555 proc_send(c
->peer
, MSG_EXEC
, -1, msg
, cmdsize
+ shellsize
);
559 /* Check for mouse keys. */
561 server_client_check_mouse(struct client
*c
, struct key_event
*event
)
563 struct mouse_event
*m
= &event
->m
;
564 struct session
*s
= c
->session
;
566 struct window_pane
*wp
;
567 u_int x
, y
, b
, sx
, sy
, px
, py
;
571 struct style_range
*sr
;
580 TRIPLE
} type
= NOTYPE
;
587 BORDER
} where
= NOWHERE
;
589 log_debug("%s mouse %02x at %u,%u (last %u,%u) (%d)", c
->name
, m
->b
,
590 m
->x
, m
->y
, m
->lx
, m
->ly
, c
->tty
.mouse_drag_flag
);
592 /* What type of event is this? */
593 if (event
->key
== KEYC_DOUBLECLICK
) {
595 x
= m
->x
, y
= m
->y
, b
= m
->b
;
597 log_debug("double-click at %u,%u", x
, y
);
598 } else if ((m
->sgr_type
!= ' ' &&
599 MOUSE_DRAG(m
->sgr_b
) &&
600 MOUSE_RELEASE(m
->sgr_b
)) ||
601 (m
->sgr_type
== ' ' &&
603 MOUSE_RELEASE(m
->b
) &&
604 MOUSE_RELEASE(m
->lb
))) {
606 x
= m
->x
, y
= m
->y
, b
= 0;
607 log_debug("move at %u,%u", x
, y
);
608 } else if (MOUSE_DRAG(m
->b
)) {
610 if (c
->tty
.mouse_drag_flag
) {
611 x
= m
->x
, y
= m
->y
, b
= m
->b
;
612 if (x
== m
->lx
&& y
== m
->ly
)
613 return (KEYC_UNKNOWN
);
614 log_debug("drag update at %u,%u", x
, y
);
616 x
= m
->lx
, y
= m
->ly
, b
= m
->lb
;
617 log_debug("drag start at %u,%u", x
, y
);
619 } else if (MOUSE_WHEEL(m
->b
)) {
621 x
= m
->x
, y
= m
->y
, b
= m
->b
;
622 log_debug("wheel at %u,%u", x
, y
);
623 } else if (MOUSE_RELEASE(m
->b
)) {
625 x
= m
->x
, y
= m
->y
, b
= m
->lb
;
626 log_debug("up at %u,%u", x
, y
);
628 if (c
->flags
& CLIENT_DOUBLECLICK
) {
629 evtimer_del(&c
->click_timer
);
630 c
->flags
&= ~CLIENT_DOUBLECLICK
;
631 if (m
->b
== c
->click_button
) {
633 x
= m
->x
, y
= m
->y
, b
= m
->b
;
634 log_debug("second-click at %u,%u", x
, y
);
635 c
->flags
|= CLIENT_TRIPLECLICK
;
637 } else if (c
->flags
& CLIENT_TRIPLECLICK
) {
638 evtimer_del(&c
->click_timer
);
639 c
->flags
&= ~CLIENT_TRIPLECLICK
;
640 if (m
->b
== c
->click_button
) {
642 x
= m
->x
, y
= m
->y
, b
= m
->b
;
643 log_debug("triple-click at %u,%u", x
, y
);
648 x
= m
->x
, y
= m
->y
, b
= m
->b
;
649 log_debug("down at %u,%u", x
, y
);
650 c
->flags
|= CLIENT_DOUBLECLICK
;
653 if (KEYC_CLICK_TIMEOUT
!= 0) {
654 memcpy(&c
->click_event
, m
, sizeof c
->click_event
);
655 c
->click_button
= m
->b
;
657 log_debug("click timer started");
658 tv
.tv_sec
= KEYC_CLICK_TIMEOUT
/ 1000;
659 tv
.tv_usec
= (KEYC_CLICK_TIMEOUT
% 1000) * 1000L;
660 evtimer_del(&c
->click_timer
);
661 evtimer_add(&c
->click_timer
, &tv
);
667 return (KEYC_UNKNOWN
);
669 /* Save the session. */
674 /* Is this on the status line? */
675 m
->statusat
= status_at_line(c
);
676 m
->statuslines
= status_line_size(c
);
677 if (m
->statusat
!= -1 &&
678 y
>= (u_int
)m
->statusat
&&
679 y
< m
->statusat
+ m
->statuslines
) {
680 sr
= status_get_range(c
, x
, y
- m
->statusat
);
682 where
= STATUS_DEFAULT
;
685 case STYLE_RANGE_NONE
:
686 return (KEYC_UNKNOWN
);
687 case STYLE_RANGE_LEFT
:
690 case STYLE_RANGE_RIGHT
:
691 where
= STATUS_RIGHT
;
693 case STYLE_RANGE_WINDOW
:
694 wl
= winlink_find_by_index(&s
->windows
,
697 return (KEYC_UNKNOWN
);
698 m
->w
= wl
->window
->id
;
706 /* Not on status line. Adjust position and check for border or pane. */
707 if (where
== NOWHERE
) {
709 if (m
->statusat
== 0 && y
>= m
->statuslines
)
710 py
= y
- m
->statuslines
;
711 else if (m
->statusat
> 0 && y
>= (u_int
)m
->statusat
)
712 py
= m
->statusat
- 1;
716 tty_window_offset(&c
->tty
, &m
->ox
, &m
->oy
, &sx
, &sy
);
717 log_debug("mouse window @%u at %u,%u (%ux%u)",
718 s
->curw
->window
->id
, m
->ox
, m
->oy
, sx
, sy
);
719 if (px
> sx
|| py
> sy
)
720 return (KEYC_UNKNOWN
);
724 /* Try the pane borders if not zoomed. */
725 if (~s
->curw
->window
->flags
& WINDOW_ZOOMED
) {
726 TAILQ_FOREACH(wp
, &s
->curw
->window
->panes
, entry
) {
727 if ((wp
->xoff
+ wp
->sx
== px
&&
728 wp
->yoff
<= 1 + py
&&
729 wp
->yoff
+ wp
->sy
>= py
) ||
730 (wp
->yoff
+ wp
->sy
== py
&&
731 wp
->xoff
<= 1 + px
&&
732 wp
->xoff
+ wp
->sx
>= px
))
739 /* Otherwise try inside the pane. */
740 if (where
== NOWHERE
) {
741 wp
= window_get_active_at(s
->curw
->window
, px
, py
);
745 return (KEYC_UNKNOWN
);
748 log_debug("mouse %u,%u on pane %%%u", x
, y
, wp
->id
);
749 else if (where
== BORDER
)
750 log_debug("mouse on pane %%%u border", wp
->id
);
752 m
->w
= wp
->window
->id
;
756 /* Stop dragging if needed. */
757 if (type
!= DRAG
&& type
!= WHEEL
&& c
->tty
.mouse_drag_flag
!= 0) {
758 if (c
->tty
.mouse_drag_release
!= NULL
)
759 c
->tty
.mouse_drag_release(c
, m
);
761 c
->tty
.mouse_drag_update
= NULL
;
762 c
->tty
.mouse_drag_release
= NULL
;
765 * End a mouse drag by passing a MouseDragEnd key corresponding
766 * to the button that started the drag.
768 switch (c
->tty
.mouse_drag_flag
- 1) {
771 key
= KEYC_MOUSEDRAGEND1_PANE
;
773 key
= KEYC_MOUSEDRAGEND1_STATUS
;
774 if (where
== STATUS_LEFT
)
775 key
= KEYC_MOUSEDRAGEND1_STATUS_LEFT
;
776 if (where
== STATUS_RIGHT
)
777 key
= KEYC_MOUSEDRAGEND1_STATUS_RIGHT
;
778 if (where
== STATUS_DEFAULT
)
779 key
= KEYC_MOUSEDRAGEND1_STATUS_DEFAULT
;
781 key
= KEYC_MOUSEDRAGEND1_BORDER
;
785 key
= KEYC_MOUSEDRAGEND2_PANE
;
787 key
= KEYC_MOUSEDRAGEND2_STATUS
;
788 if (where
== STATUS_LEFT
)
789 key
= KEYC_MOUSEDRAGEND2_STATUS_LEFT
;
790 if (where
== STATUS_RIGHT
)
791 key
= KEYC_MOUSEDRAGEND2_STATUS_RIGHT
;
792 if (where
== STATUS_DEFAULT
)
793 key
= KEYC_MOUSEDRAGEND2_STATUS_DEFAULT
;
795 key
= KEYC_MOUSEDRAGEND2_BORDER
;
799 key
= KEYC_MOUSEDRAGEND3_PANE
;
801 key
= KEYC_MOUSEDRAGEND3_STATUS
;
802 if (where
== STATUS_LEFT
)
803 key
= KEYC_MOUSEDRAGEND3_STATUS_LEFT
;
804 if (where
== STATUS_RIGHT
)
805 key
= KEYC_MOUSEDRAGEND3_STATUS_RIGHT
;
806 if (where
== STATUS_DEFAULT
)
807 key
= KEYC_MOUSEDRAGEND3_STATUS_DEFAULT
;
809 key
= KEYC_MOUSEDRAGEND3_BORDER
;
813 key
= KEYC_MOUSEDRAGEND6_PANE
;
815 key
= KEYC_MOUSEDRAGEND6_STATUS
;
816 if (where
== STATUS_LEFT
)
817 key
= KEYC_MOUSEDRAGEND6_STATUS_LEFT
;
818 if (where
== STATUS_RIGHT
)
819 key
= KEYC_MOUSEDRAGEND6_STATUS_RIGHT
;
820 if (where
== STATUS_DEFAULT
)
821 key
= KEYC_MOUSEDRAGEND6_STATUS_DEFAULT
;
823 key
= KEYC_MOUSEDRAGEND6_BORDER
;
827 key
= KEYC_MOUSEDRAGEND7_PANE
;
829 key
= KEYC_MOUSEDRAGEND7_STATUS
;
830 if (where
== STATUS_LEFT
)
831 key
= KEYC_MOUSEDRAGEND7_STATUS_LEFT
;
832 if (where
== STATUS_RIGHT
)
833 key
= KEYC_MOUSEDRAGEND7_STATUS_RIGHT
;
834 if (where
== STATUS_DEFAULT
)
835 key
= KEYC_MOUSEDRAGEND7_STATUS_DEFAULT
;
837 key
= KEYC_MOUSEDRAGEND7_BORDER
;
841 key
= KEYC_MOUSEDRAGEND8_PANE
;
843 key
= KEYC_MOUSEDRAGEND8_STATUS
;
844 if (where
== STATUS_LEFT
)
845 key
= KEYC_MOUSEDRAGEND8_STATUS_LEFT
;
846 if (where
== STATUS_RIGHT
)
847 key
= KEYC_MOUSEDRAGEND8_STATUS_RIGHT
;
848 if (where
== STATUS_DEFAULT
)
849 key
= KEYC_MOUSEDRAGEND8_STATUS_DEFAULT
;
851 key
= KEYC_MOUSEDRAGEND8_BORDER
;
855 key
= KEYC_MOUSEDRAGEND9_PANE
;
857 key
= KEYC_MOUSEDRAGEND9_STATUS
;
858 if (where
== STATUS_LEFT
)
859 key
= KEYC_MOUSEDRAGEND9_STATUS_LEFT
;
860 if (where
== STATUS_RIGHT
)
861 key
= KEYC_MOUSEDRAGEND9_STATUS_RIGHT
;
862 if (where
== STATUS_DEFAULT
)
863 key
= KEYC_MOUSEDRAGEND9_STATUS_DEFAULT
;
865 key
= KEYC_MOUSEDRAGEND9_BORDER
;
867 case MOUSE_BUTTON_10
:
869 key
= KEYC_MOUSEDRAGEND10_PANE
;
871 key
= KEYC_MOUSEDRAGEND10_STATUS
;
872 if (where
== STATUS_LEFT
)
873 key
= KEYC_MOUSEDRAGEND10_STATUS_LEFT
;
874 if (where
== STATUS_RIGHT
)
875 key
= KEYC_MOUSEDRAGEND10_STATUS_RIGHT
;
876 if (where
== STATUS_DEFAULT
)
877 key
= KEYC_MOUSEDRAGEND10_STATUS_DEFAULT
;
879 key
= KEYC_MOUSEDRAGEND10_BORDER
;
881 case MOUSE_BUTTON_11
:
883 key
= KEYC_MOUSEDRAGEND11_PANE
;
885 key
= KEYC_MOUSEDRAGEND11_STATUS
;
886 if (where
== STATUS_LEFT
)
887 key
= KEYC_MOUSEDRAGEND11_STATUS_LEFT
;
888 if (where
== STATUS_RIGHT
)
889 key
= KEYC_MOUSEDRAGEND11_STATUS_RIGHT
;
890 if (where
== STATUS_DEFAULT
)
891 key
= KEYC_MOUSEDRAGEND11_STATUS_DEFAULT
;
893 key
= KEYC_MOUSEDRAGEND11_BORDER
;
899 c
->tty
.mouse_drag_flag
= 0;
903 /* Convert to a key binding. */
910 key
= KEYC_MOUSEMOVE_PANE
;
912 key
= KEYC_MOUSEMOVE_STATUS
;
913 if (where
== STATUS_LEFT
)
914 key
= KEYC_MOUSEMOVE_STATUS_LEFT
;
915 if (where
== STATUS_RIGHT
)
916 key
= KEYC_MOUSEMOVE_STATUS_RIGHT
;
917 if (where
== STATUS_DEFAULT
)
918 key
= KEYC_MOUSEMOVE_STATUS_DEFAULT
;
920 key
= KEYC_MOUSEMOVE_BORDER
;
923 if (c
->tty
.mouse_drag_update
!= NULL
)
926 switch (MOUSE_BUTTONS(b
)) {
929 key
= KEYC_MOUSEDRAG1_PANE
;
931 key
= KEYC_MOUSEDRAG1_STATUS
;
932 if (where
== STATUS_LEFT
)
933 key
= KEYC_MOUSEDRAG1_STATUS_LEFT
;
934 if (where
== STATUS_RIGHT
)
935 key
= KEYC_MOUSEDRAG1_STATUS_RIGHT
;
936 if (where
== STATUS_DEFAULT
)
937 key
= KEYC_MOUSEDRAG1_STATUS_DEFAULT
;
939 key
= KEYC_MOUSEDRAG1_BORDER
;
943 key
= KEYC_MOUSEDRAG2_PANE
;
945 key
= KEYC_MOUSEDRAG2_STATUS
;
946 if (where
== STATUS_LEFT
)
947 key
= KEYC_MOUSEDRAG2_STATUS_LEFT
;
948 if (where
== STATUS_RIGHT
)
949 key
= KEYC_MOUSEDRAG2_STATUS_RIGHT
;
950 if (where
== STATUS_DEFAULT
)
951 key
= KEYC_MOUSEDRAG2_STATUS_DEFAULT
;
953 key
= KEYC_MOUSEDRAG2_BORDER
;
957 key
= KEYC_MOUSEDRAG3_PANE
;
959 key
= KEYC_MOUSEDRAG3_STATUS
;
960 if (where
== STATUS_LEFT
)
961 key
= KEYC_MOUSEDRAG3_STATUS_LEFT
;
962 if (where
== STATUS_RIGHT
)
963 key
= KEYC_MOUSEDRAG3_STATUS_RIGHT
;
964 if (where
== STATUS_DEFAULT
)
965 key
= KEYC_MOUSEDRAG3_STATUS_DEFAULT
;
967 key
= KEYC_MOUSEDRAG3_BORDER
;
971 key
= KEYC_MOUSEDRAG6_PANE
;
973 key
= KEYC_MOUSEDRAG6_STATUS
;
974 if (where
== STATUS_LEFT
)
975 key
= KEYC_MOUSEDRAG6_STATUS_LEFT
;
976 if (where
== STATUS_RIGHT
)
977 key
= KEYC_MOUSEDRAG6_STATUS_RIGHT
;
978 if (where
== STATUS_DEFAULT
)
979 key
= KEYC_MOUSEDRAG6_STATUS_DEFAULT
;
981 key
= KEYC_MOUSEDRAG6_BORDER
;
985 key
= KEYC_MOUSEDRAG7_PANE
;
987 key
= KEYC_MOUSEDRAG7_STATUS
;
988 if (where
== STATUS_LEFT
)
989 key
= KEYC_MOUSEDRAG7_STATUS_LEFT
;
990 if (where
== STATUS_RIGHT
)
991 key
= KEYC_MOUSEDRAG7_STATUS_RIGHT
;
992 if (where
== STATUS_DEFAULT
)
993 key
= KEYC_MOUSEDRAG7_STATUS_DEFAULT
;
995 key
= KEYC_MOUSEDRAG7_BORDER
;
999 key
= KEYC_MOUSEDRAG8_PANE
;
1000 if (where
== STATUS
)
1001 key
= KEYC_MOUSEDRAG8_STATUS
;
1002 if (where
== STATUS_LEFT
)
1003 key
= KEYC_MOUSEDRAG8_STATUS_LEFT
;
1004 if (where
== STATUS_RIGHT
)
1005 key
= KEYC_MOUSEDRAG8_STATUS_RIGHT
;
1006 if (where
== STATUS_DEFAULT
)
1007 key
= KEYC_MOUSEDRAG8_STATUS_DEFAULT
;
1008 if (where
== BORDER
)
1009 key
= KEYC_MOUSEDRAG8_BORDER
;
1011 case MOUSE_BUTTON_9
:
1013 key
= KEYC_MOUSEDRAG9_PANE
;
1014 if (where
== STATUS
)
1015 key
= KEYC_MOUSEDRAG9_STATUS
;
1016 if (where
== STATUS_LEFT
)
1017 key
= KEYC_MOUSEDRAG9_STATUS_LEFT
;
1018 if (where
== STATUS_RIGHT
)
1019 key
= KEYC_MOUSEDRAG9_STATUS_RIGHT
;
1020 if (where
== STATUS_DEFAULT
)
1021 key
= KEYC_MOUSEDRAG9_STATUS_DEFAULT
;
1022 if (where
== BORDER
)
1023 key
= KEYC_MOUSEDRAG9_BORDER
;
1025 case MOUSE_BUTTON_10
:
1027 key
= KEYC_MOUSEDRAG10_PANE
;
1028 if (where
== STATUS
)
1029 key
= KEYC_MOUSEDRAG10_STATUS
;
1030 if (where
== STATUS_LEFT
)
1031 key
= KEYC_MOUSEDRAG10_STATUS_LEFT
;
1032 if (where
== STATUS_RIGHT
)
1033 key
= KEYC_MOUSEDRAG10_STATUS_RIGHT
;
1034 if (where
== STATUS_DEFAULT
)
1035 key
= KEYC_MOUSEDRAG10_STATUS_DEFAULT
;
1036 if (where
== BORDER
)
1037 key
= KEYC_MOUSEDRAG10_BORDER
;
1039 case MOUSE_BUTTON_11
:
1041 key
= KEYC_MOUSEDRAG11_PANE
;
1042 if (where
== STATUS
)
1043 key
= KEYC_MOUSEDRAG11_STATUS
;
1044 if (where
== STATUS_LEFT
)
1045 key
= KEYC_MOUSEDRAG11_STATUS_LEFT
;
1046 if (where
== STATUS_RIGHT
)
1047 key
= KEYC_MOUSEDRAG11_STATUS_RIGHT
;
1048 if (where
== STATUS_DEFAULT
)
1049 key
= KEYC_MOUSEDRAG11_STATUS_DEFAULT
;
1050 if (where
== BORDER
)
1051 key
= KEYC_MOUSEDRAG11_BORDER
;
1057 * Begin a drag by setting the flag to a non-zero value that
1058 * corresponds to the mouse button in use.
1060 c
->tty
.mouse_drag_flag
= MOUSE_BUTTONS(b
) + 1;
1063 if (MOUSE_BUTTONS(b
) == MOUSE_WHEEL_UP
) {
1065 key
= KEYC_WHEELUP_PANE
;
1066 if (where
== STATUS
)
1067 key
= KEYC_WHEELUP_STATUS
;
1068 if (where
== STATUS_LEFT
)
1069 key
= KEYC_WHEELUP_STATUS_LEFT
;
1070 if (where
== STATUS_RIGHT
)
1071 key
= KEYC_WHEELUP_STATUS_RIGHT
;
1072 if (where
== STATUS_DEFAULT
)
1073 key
= KEYC_WHEELUP_STATUS_DEFAULT
;
1074 if (where
== BORDER
)
1075 key
= KEYC_WHEELUP_BORDER
;
1078 key
= KEYC_WHEELDOWN_PANE
;
1079 if (where
== STATUS
)
1080 key
= KEYC_WHEELDOWN_STATUS
;
1081 if (where
== STATUS_LEFT
)
1082 key
= KEYC_WHEELDOWN_STATUS_LEFT
;
1083 if (where
== STATUS_RIGHT
)
1084 key
= KEYC_WHEELDOWN_STATUS_RIGHT
;
1085 if (where
== STATUS_DEFAULT
)
1086 key
= KEYC_WHEELDOWN_STATUS_DEFAULT
;
1087 if (where
== BORDER
)
1088 key
= KEYC_WHEELDOWN_BORDER
;
1092 switch (MOUSE_BUTTONS(b
)) {
1093 case MOUSE_BUTTON_1
:
1095 key
= KEYC_MOUSEUP1_PANE
;
1096 if (where
== STATUS
)
1097 key
= KEYC_MOUSEUP1_STATUS
;
1098 if (where
== STATUS_LEFT
)
1099 key
= KEYC_MOUSEUP1_STATUS_LEFT
;
1100 if (where
== STATUS_RIGHT
)
1101 key
= KEYC_MOUSEUP1_STATUS_RIGHT
;
1102 if (where
== STATUS_DEFAULT
)
1103 key
= KEYC_MOUSEUP1_STATUS_DEFAULT
;
1104 if (where
== BORDER
)
1105 key
= KEYC_MOUSEUP1_BORDER
;
1107 case MOUSE_BUTTON_2
:
1109 key
= KEYC_MOUSEUP2_PANE
;
1110 if (where
== STATUS
)
1111 key
= KEYC_MOUSEUP2_STATUS
;
1112 if (where
== STATUS_LEFT
)
1113 key
= KEYC_MOUSEUP2_STATUS_LEFT
;
1114 if (where
== STATUS_RIGHT
)
1115 key
= KEYC_MOUSEUP2_STATUS_RIGHT
;
1116 if (where
== STATUS_DEFAULT
)
1117 key
= KEYC_MOUSEUP2_STATUS_DEFAULT
;
1118 if (where
== BORDER
)
1119 key
= KEYC_MOUSEUP2_BORDER
;
1121 case MOUSE_BUTTON_3
:
1123 key
= KEYC_MOUSEUP3_PANE
;
1124 if (where
== STATUS
)
1125 key
= KEYC_MOUSEUP3_STATUS
;
1126 if (where
== STATUS_LEFT
)
1127 key
= KEYC_MOUSEUP3_STATUS_LEFT
;
1128 if (where
== STATUS_RIGHT
)
1129 key
= KEYC_MOUSEUP3_STATUS_RIGHT
;
1130 if (where
== STATUS_DEFAULT
)
1131 key
= KEYC_MOUSEUP3_STATUS_DEFAULT
;
1132 if (where
== BORDER
)
1133 key
= KEYC_MOUSEUP3_BORDER
;
1135 case MOUSE_BUTTON_6
:
1137 key
= KEYC_MOUSEUP6_PANE
;
1138 if (where
== STATUS
)
1139 key
= KEYC_MOUSEUP6_STATUS
;
1140 if (where
== STATUS_LEFT
)
1141 key
= KEYC_MOUSEUP6_STATUS_LEFT
;
1142 if (where
== STATUS_RIGHT
)
1143 key
= KEYC_MOUSEUP6_STATUS_RIGHT
;
1144 if (where
== STATUS_DEFAULT
)
1145 key
= KEYC_MOUSEUP6_STATUS_DEFAULT
;
1146 if (where
== BORDER
)
1147 key
= KEYC_MOUSEUP6_BORDER
;
1149 case MOUSE_BUTTON_7
:
1151 key
= KEYC_MOUSEUP7_PANE
;
1152 if (where
== STATUS
)
1153 key
= KEYC_MOUSEUP7_STATUS
;
1154 if (where
== STATUS_LEFT
)
1155 key
= KEYC_MOUSEUP7_STATUS_LEFT
;
1156 if (where
== STATUS_RIGHT
)
1157 key
= KEYC_MOUSEUP7_STATUS_RIGHT
;
1158 if (where
== STATUS_DEFAULT
)
1159 key
= KEYC_MOUSEUP7_STATUS_DEFAULT
;
1160 if (where
== BORDER
)
1161 key
= KEYC_MOUSEUP7_BORDER
;
1163 case MOUSE_BUTTON_8
:
1165 key
= KEYC_MOUSEUP8_PANE
;
1166 if (where
== STATUS
)
1167 key
= KEYC_MOUSEUP8_STATUS
;
1168 if (where
== STATUS_LEFT
)
1169 key
= KEYC_MOUSEUP8_STATUS_LEFT
;
1170 if (where
== STATUS_RIGHT
)
1171 key
= KEYC_MOUSEUP8_STATUS_RIGHT
;
1172 if (where
== STATUS_DEFAULT
)
1173 key
= KEYC_MOUSEUP8_STATUS_DEFAULT
;
1174 if (where
== BORDER
)
1175 key
= KEYC_MOUSEUP8_BORDER
;
1177 case MOUSE_BUTTON_9
:
1179 key
= KEYC_MOUSEUP9_PANE
;
1180 if (where
== STATUS
)
1181 key
= KEYC_MOUSEUP9_STATUS
;
1182 if (where
== STATUS_LEFT
)
1183 key
= KEYC_MOUSEUP9_STATUS_LEFT
;
1184 if (where
== STATUS_RIGHT
)
1185 key
= KEYC_MOUSEUP9_STATUS_RIGHT
;
1186 if (where
== STATUS_DEFAULT
)
1187 key
= KEYC_MOUSEUP9_STATUS_DEFAULT
;
1188 if (where
== BORDER
)
1189 key
= KEYC_MOUSEUP9_BORDER
;
1191 case MOUSE_BUTTON_10
:
1193 key
= KEYC_MOUSEUP1_PANE
;
1194 if (where
== STATUS
)
1195 key
= KEYC_MOUSEUP1_STATUS
;
1196 if (where
== STATUS_LEFT
)
1197 key
= KEYC_MOUSEUP1_STATUS_LEFT
;
1198 if (where
== STATUS_RIGHT
)
1199 key
= KEYC_MOUSEUP1_STATUS_RIGHT
;
1200 if (where
== STATUS_DEFAULT
)
1201 key
= KEYC_MOUSEUP1_STATUS_DEFAULT
;
1202 if (where
== BORDER
)
1203 key
= KEYC_MOUSEUP1_BORDER
;
1205 case MOUSE_BUTTON_11
:
1207 key
= KEYC_MOUSEUP11_PANE
;
1208 if (where
== STATUS
)
1209 key
= KEYC_MOUSEUP11_STATUS
;
1210 if (where
== STATUS_LEFT
)
1211 key
= KEYC_MOUSEUP11_STATUS_LEFT
;
1212 if (where
== STATUS_RIGHT
)
1213 key
= KEYC_MOUSEUP11_STATUS_RIGHT
;
1214 if (where
== STATUS_DEFAULT
)
1215 key
= KEYC_MOUSEUP11_STATUS_DEFAULT
;
1216 if (where
== BORDER
)
1217 key
= KEYC_MOUSEUP11_BORDER
;
1222 switch (MOUSE_BUTTONS(b
)) {
1223 case MOUSE_BUTTON_1
:
1225 key
= KEYC_MOUSEDOWN1_PANE
;
1226 if (where
== STATUS
)
1227 key
= KEYC_MOUSEDOWN1_STATUS
;
1228 if (where
== STATUS_LEFT
)
1229 key
= KEYC_MOUSEDOWN1_STATUS_LEFT
;
1230 if (where
== STATUS_RIGHT
)
1231 key
= KEYC_MOUSEDOWN1_STATUS_RIGHT
;
1232 if (where
== STATUS_DEFAULT
)
1233 key
= KEYC_MOUSEDOWN1_STATUS_DEFAULT
;
1234 if (where
== BORDER
)
1235 key
= KEYC_MOUSEDOWN1_BORDER
;
1237 case MOUSE_BUTTON_2
:
1239 key
= KEYC_MOUSEDOWN2_PANE
;
1240 if (where
== STATUS
)
1241 key
= KEYC_MOUSEDOWN2_STATUS
;
1242 if (where
== STATUS_LEFT
)
1243 key
= KEYC_MOUSEDOWN2_STATUS_LEFT
;
1244 if (where
== STATUS_RIGHT
)
1245 key
= KEYC_MOUSEDOWN2_STATUS_RIGHT
;
1246 if (where
== STATUS_DEFAULT
)
1247 key
= KEYC_MOUSEDOWN2_STATUS_DEFAULT
;
1248 if (where
== BORDER
)
1249 key
= KEYC_MOUSEDOWN2_BORDER
;
1251 case MOUSE_BUTTON_3
:
1253 key
= KEYC_MOUSEDOWN3_PANE
;
1254 if (where
== STATUS
)
1255 key
= KEYC_MOUSEDOWN3_STATUS
;
1256 if (where
== STATUS_LEFT
)
1257 key
= KEYC_MOUSEDOWN3_STATUS_LEFT
;
1258 if (where
== STATUS_RIGHT
)
1259 key
= KEYC_MOUSEDOWN3_STATUS_RIGHT
;
1260 if (where
== STATUS_DEFAULT
)
1261 key
= KEYC_MOUSEDOWN3_STATUS_DEFAULT
;
1262 if (where
== BORDER
)
1263 key
= KEYC_MOUSEDOWN3_BORDER
;
1265 case MOUSE_BUTTON_6
:
1267 key
= KEYC_MOUSEDOWN6_PANE
;
1268 if (where
== STATUS
)
1269 key
= KEYC_MOUSEDOWN6_STATUS
;
1270 if (where
== STATUS_LEFT
)
1271 key
= KEYC_MOUSEDOWN6_STATUS_LEFT
;
1272 if (where
== STATUS_RIGHT
)
1273 key
= KEYC_MOUSEDOWN6_STATUS_RIGHT
;
1274 if (where
== STATUS_DEFAULT
)
1275 key
= KEYC_MOUSEDOWN6_STATUS_DEFAULT
;
1276 if (where
== BORDER
)
1277 key
= KEYC_MOUSEDOWN6_BORDER
;
1279 case MOUSE_BUTTON_7
:
1281 key
= KEYC_MOUSEDOWN7_PANE
;
1282 if (where
== STATUS
)
1283 key
= KEYC_MOUSEDOWN7_STATUS
;
1284 if (where
== STATUS_LEFT
)
1285 key
= KEYC_MOUSEDOWN7_STATUS_LEFT
;
1286 if (where
== STATUS_RIGHT
)
1287 key
= KEYC_MOUSEDOWN7_STATUS_RIGHT
;
1288 if (where
== STATUS_DEFAULT
)
1289 key
= KEYC_MOUSEDOWN7_STATUS_DEFAULT
;
1290 if (where
== BORDER
)
1291 key
= KEYC_MOUSEDOWN7_BORDER
;
1293 case MOUSE_BUTTON_8
:
1295 key
= KEYC_MOUSEDOWN8_PANE
;
1296 if (where
== STATUS
)
1297 key
= KEYC_MOUSEDOWN8_STATUS
;
1298 if (where
== STATUS_LEFT
)
1299 key
= KEYC_MOUSEDOWN8_STATUS_LEFT
;
1300 if (where
== STATUS_RIGHT
)
1301 key
= KEYC_MOUSEDOWN8_STATUS_RIGHT
;
1302 if (where
== STATUS_DEFAULT
)
1303 key
= KEYC_MOUSEDOWN8_STATUS_DEFAULT
;
1304 if (where
== BORDER
)
1305 key
= KEYC_MOUSEDOWN8_BORDER
;
1307 case MOUSE_BUTTON_9
:
1309 key
= KEYC_MOUSEDOWN9_PANE
;
1310 if (where
== STATUS
)
1311 key
= KEYC_MOUSEDOWN9_STATUS
;
1312 if (where
== STATUS_LEFT
)
1313 key
= KEYC_MOUSEDOWN9_STATUS_LEFT
;
1314 if (where
== STATUS_RIGHT
)
1315 key
= KEYC_MOUSEDOWN9_STATUS_RIGHT
;
1316 if (where
== STATUS_DEFAULT
)
1317 key
= KEYC_MOUSEDOWN9_STATUS_DEFAULT
;
1318 if (where
== BORDER
)
1319 key
= KEYC_MOUSEDOWN9_BORDER
;
1321 case MOUSE_BUTTON_10
:
1323 key
= KEYC_MOUSEDOWN10_PANE
;
1324 if (where
== STATUS
)
1325 key
= KEYC_MOUSEDOWN10_STATUS
;
1326 if (where
== STATUS_LEFT
)
1327 key
= KEYC_MOUSEDOWN10_STATUS_LEFT
;
1328 if (where
== STATUS_RIGHT
)
1329 key
= KEYC_MOUSEDOWN10_STATUS_RIGHT
;
1330 if (where
== STATUS_DEFAULT
)
1331 key
= KEYC_MOUSEDOWN10_STATUS_DEFAULT
;
1332 if (where
== BORDER
)
1333 key
= KEYC_MOUSEDOWN10_BORDER
;
1335 case MOUSE_BUTTON_11
:
1337 key
= KEYC_MOUSEDOWN11_PANE
;
1338 if (where
== STATUS
)
1339 key
= KEYC_MOUSEDOWN11_STATUS
;
1340 if (where
== STATUS_LEFT
)
1341 key
= KEYC_MOUSEDOWN11_STATUS_LEFT
;
1342 if (where
== STATUS_RIGHT
)
1343 key
= KEYC_MOUSEDOWN11_STATUS_RIGHT
;
1344 if (where
== STATUS_DEFAULT
)
1345 key
= KEYC_MOUSEDOWN11_STATUS_DEFAULT
;
1346 if (where
== BORDER
)
1347 key
= KEYC_MOUSEDOWN11_BORDER
;
1352 switch (MOUSE_BUTTONS(b
)) {
1353 case MOUSE_BUTTON_1
:
1355 key
= KEYC_SECONDCLICK1_PANE
;
1356 if (where
== STATUS
)
1357 key
= KEYC_SECONDCLICK1_STATUS
;
1358 if (where
== STATUS_LEFT
)
1359 key
= KEYC_SECONDCLICK1_STATUS_LEFT
;
1360 if (where
== STATUS_RIGHT
)
1361 key
= KEYC_SECONDCLICK1_STATUS_RIGHT
;
1362 if (where
== STATUS_DEFAULT
)
1363 key
= KEYC_SECONDCLICK1_STATUS_DEFAULT
;
1364 if (where
== BORDER
)
1365 key
= KEYC_SECONDCLICK1_BORDER
;
1367 case MOUSE_BUTTON_2
:
1369 key
= KEYC_SECONDCLICK2_PANE
;
1370 if (where
== STATUS
)
1371 key
= KEYC_SECONDCLICK2_STATUS
;
1372 if (where
== STATUS_LEFT
)
1373 key
= KEYC_SECONDCLICK2_STATUS_LEFT
;
1374 if (where
== STATUS_RIGHT
)
1375 key
= KEYC_SECONDCLICK2_STATUS_RIGHT
;
1376 if (where
== STATUS_DEFAULT
)
1377 key
= KEYC_SECONDCLICK2_STATUS_DEFAULT
;
1378 if (where
== BORDER
)
1379 key
= KEYC_SECONDCLICK2_BORDER
;
1381 case MOUSE_BUTTON_3
:
1383 key
= KEYC_SECONDCLICK3_PANE
;
1384 if (where
== STATUS
)
1385 key
= KEYC_SECONDCLICK3_STATUS
;
1386 if (where
== STATUS_LEFT
)
1387 key
= KEYC_SECONDCLICK3_STATUS_LEFT
;
1388 if (where
== STATUS_RIGHT
)
1389 key
= KEYC_SECONDCLICK3_STATUS_RIGHT
;
1390 if (where
== STATUS_DEFAULT
)
1391 key
= KEYC_SECONDCLICK3_STATUS_DEFAULT
;
1392 if (where
== BORDER
)
1393 key
= KEYC_SECONDCLICK3_BORDER
;
1395 case MOUSE_BUTTON_6
:
1397 key
= KEYC_SECONDCLICK6_PANE
;
1398 if (where
== STATUS
)
1399 key
= KEYC_SECONDCLICK6_STATUS
;
1400 if (where
== STATUS_LEFT
)
1401 key
= KEYC_SECONDCLICK6_STATUS_LEFT
;
1402 if (where
== STATUS_RIGHT
)
1403 key
= KEYC_SECONDCLICK6_STATUS_RIGHT
;
1404 if (where
== STATUS_DEFAULT
)
1405 key
= KEYC_SECONDCLICK6_STATUS_DEFAULT
;
1406 if (where
== BORDER
)
1407 key
= KEYC_SECONDCLICK6_BORDER
;
1409 case MOUSE_BUTTON_7
:
1411 key
= KEYC_SECONDCLICK7_PANE
;
1412 if (where
== STATUS
)
1413 key
= KEYC_SECONDCLICK7_STATUS
;
1414 if (where
== STATUS_LEFT
)
1415 key
= KEYC_SECONDCLICK7_STATUS_LEFT
;
1416 if (where
== STATUS_RIGHT
)
1417 key
= KEYC_SECONDCLICK7_STATUS_RIGHT
;
1418 if (where
== STATUS_DEFAULT
)
1419 key
= KEYC_SECONDCLICK7_STATUS_DEFAULT
;
1420 if (where
== BORDER
)
1421 key
= KEYC_SECONDCLICK7_BORDER
;
1423 case MOUSE_BUTTON_8
:
1425 key
= KEYC_SECONDCLICK8_PANE
;
1426 if (where
== STATUS
)
1427 key
= KEYC_SECONDCLICK8_STATUS
;
1428 if (where
== STATUS_LEFT
)
1429 key
= KEYC_SECONDCLICK8_STATUS_LEFT
;
1430 if (where
== STATUS_RIGHT
)
1431 key
= KEYC_SECONDCLICK8_STATUS_RIGHT
;
1432 if (where
== STATUS_DEFAULT
)
1433 key
= KEYC_SECONDCLICK8_STATUS_DEFAULT
;
1434 if (where
== BORDER
)
1435 key
= KEYC_SECONDCLICK8_BORDER
;
1437 case MOUSE_BUTTON_9
:
1439 key
= KEYC_SECONDCLICK9_PANE
;
1440 if (where
== STATUS
)
1441 key
= KEYC_SECONDCLICK9_STATUS
;
1442 if (where
== STATUS_LEFT
)
1443 key
= KEYC_SECONDCLICK9_STATUS_LEFT
;
1444 if (where
== STATUS_RIGHT
)
1445 key
= KEYC_SECONDCLICK9_STATUS_RIGHT
;
1446 if (where
== STATUS_DEFAULT
)
1447 key
= KEYC_SECONDCLICK9_STATUS_DEFAULT
;
1448 if (where
== BORDER
)
1449 key
= KEYC_SECONDCLICK9_BORDER
;
1451 case MOUSE_BUTTON_10
:
1453 key
= KEYC_SECONDCLICK10_PANE
;
1454 if (where
== STATUS
)
1455 key
= KEYC_SECONDCLICK10_STATUS
;
1456 if (where
== STATUS_LEFT
)
1457 key
= KEYC_SECONDCLICK10_STATUS_LEFT
;
1458 if (where
== STATUS_RIGHT
)
1459 key
= KEYC_SECONDCLICK10_STATUS_RIGHT
;
1460 if (where
== STATUS_DEFAULT
)
1461 key
= KEYC_SECONDCLICK10_STATUS_DEFAULT
;
1462 if (where
== BORDER
)
1463 key
= KEYC_SECONDCLICK10_BORDER
;
1465 case MOUSE_BUTTON_11
:
1467 key
= KEYC_SECONDCLICK11_PANE
;
1468 if (where
== STATUS
)
1469 key
= KEYC_SECONDCLICK11_STATUS
;
1470 if (where
== STATUS_LEFT
)
1471 key
= KEYC_SECONDCLICK11_STATUS_LEFT
;
1472 if (where
== STATUS_RIGHT
)
1473 key
= KEYC_SECONDCLICK11_STATUS_RIGHT
;
1474 if (where
== STATUS_DEFAULT
)
1475 key
= KEYC_SECONDCLICK11_STATUS_DEFAULT
;
1476 if (where
== BORDER
)
1477 key
= KEYC_SECONDCLICK11_BORDER
;
1482 switch (MOUSE_BUTTONS(b
)) {
1483 case MOUSE_BUTTON_1
:
1485 key
= KEYC_DOUBLECLICK1_PANE
;
1486 if (where
== STATUS
)
1487 key
= KEYC_DOUBLECLICK1_STATUS
;
1488 if (where
== STATUS_LEFT
)
1489 key
= KEYC_DOUBLECLICK1_STATUS_LEFT
;
1490 if (where
== STATUS_RIGHT
)
1491 key
= KEYC_DOUBLECLICK1_STATUS_RIGHT
;
1492 if (where
== STATUS_DEFAULT
)
1493 key
= KEYC_DOUBLECLICK1_STATUS_DEFAULT
;
1494 if (where
== BORDER
)
1495 key
= KEYC_DOUBLECLICK1_BORDER
;
1497 case MOUSE_BUTTON_2
:
1499 key
= KEYC_DOUBLECLICK2_PANE
;
1500 if (where
== STATUS
)
1501 key
= KEYC_DOUBLECLICK2_STATUS
;
1502 if (where
== STATUS_LEFT
)
1503 key
= KEYC_DOUBLECLICK2_STATUS_LEFT
;
1504 if (where
== STATUS_RIGHT
)
1505 key
= KEYC_DOUBLECLICK2_STATUS_RIGHT
;
1506 if (where
== STATUS_DEFAULT
)
1507 key
= KEYC_DOUBLECLICK2_STATUS_DEFAULT
;
1508 if (where
== BORDER
)
1509 key
= KEYC_DOUBLECLICK2_BORDER
;
1511 case MOUSE_BUTTON_3
:
1513 key
= KEYC_DOUBLECLICK3_PANE
;
1514 if (where
== STATUS
)
1515 key
= KEYC_DOUBLECLICK3_STATUS
;
1516 if (where
== STATUS_LEFT
)
1517 key
= KEYC_DOUBLECLICK3_STATUS_LEFT
;
1518 if (where
== STATUS_RIGHT
)
1519 key
= KEYC_DOUBLECLICK3_STATUS_RIGHT
;
1520 if (where
== STATUS_DEFAULT
)
1521 key
= KEYC_DOUBLECLICK3_STATUS_DEFAULT
;
1522 if (where
== BORDER
)
1523 key
= KEYC_DOUBLECLICK3_BORDER
;
1525 case MOUSE_BUTTON_6
:
1527 key
= KEYC_DOUBLECLICK6_PANE
;
1528 if (where
== STATUS
)
1529 key
= KEYC_DOUBLECLICK6_STATUS
;
1530 if (where
== STATUS_LEFT
)
1531 key
= KEYC_DOUBLECLICK6_STATUS_LEFT
;
1532 if (where
== STATUS_RIGHT
)
1533 key
= KEYC_DOUBLECLICK6_STATUS_RIGHT
;
1534 if (where
== STATUS_DEFAULT
)
1535 key
= KEYC_DOUBLECLICK6_STATUS_DEFAULT
;
1536 if (where
== BORDER
)
1537 key
= KEYC_DOUBLECLICK6_BORDER
;
1539 case MOUSE_BUTTON_7
:
1541 key
= KEYC_DOUBLECLICK7_PANE
;
1542 if (where
== STATUS
)
1543 key
= KEYC_DOUBLECLICK7_STATUS
;
1544 if (where
== STATUS_LEFT
)
1545 key
= KEYC_DOUBLECLICK7_STATUS_LEFT
;
1546 if (where
== STATUS_RIGHT
)
1547 key
= KEYC_DOUBLECLICK7_STATUS_RIGHT
;
1548 if (where
== STATUS_DEFAULT
)
1549 key
= KEYC_DOUBLECLICK7_STATUS_DEFAULT
;
1550 if (where
== BORDER
)
1551 key
= KEYC_DOUBLECLICK7_BORDER
;
1553 case MOUSE_BUTTON_8
:
1555 key
= KEYC_DOUBLECLICK8_PANE
;
1556 if (where
== STATUS
)
1557 key
= KEYC_DOUBLECLICK8_STATUS
;
1558 if (where
== STATUS_LEFT
)
1559 key
= KEYC_DOUBLECLICK8_STATUS_LEFT
;
1560 if (where
== STATUS_RIGHT
)
1561 key
= KEYC_DOUBLECLICK8_STATUS_RIGHT
;
1562 if (where
== STATUS_DEFAULT
)
1563 key
= KEYC_DOUBLECLICK8_STATUS_DEFAULT
;
1564 if (where
== BORDER
)
1565 key
= KEYC_DOUBLECLICK8_BORDER
;
1567 case MOUSE_BUTTON_9
:
1569 key
= KEYC_DOUBLECLICK9_PANE
;
1570 if (where
== STATUS
)
1571 key
= KEYC_DOUBLECLICK9_STATUS
;
1572 if (where
== STATUS_LEFT
)
1573 key
= KEYC_DOUBLECLICK9_STATUS_LEFT
;
1574 if (where
== STATUS_RIGHT
)
1575 key
= KEYC_DOUBLECLICK9_STATUS_RIGHT
;
1576 if (where
== STATUS_DEFAULT
)
1577 key
= KEYC_DOUBLECLICK9_STATUS_DEFAULT
;
1578 if (where
== BORDER
)
1579 key
= KEYC_DOUBLECLICK9_BORDER
;
1581 case MOUSE_BUTTON_10
:
1583 key
= KEYC_DOUBLECLICK10_PANE
;
1584 if (where
== STATUS
)
1585 key
= KEYC_DOUBLECLICK10_STATUS
;
1586 if (where
== STATUS_LEFT
)
1587 key
= KEYC_DOUBLECLICK10_STATUS_LEFT
;
1588 if (where
== STATUS_RIGHT
)
1589 key
= KEYC_DOUBLECLICK10_STATUS_RIGHT
;
1590 if (where
== STATUS_DEFAULT
)
1591 key
= KEYC_DOUBLECLICK10_STATUS_DEFAULT
;
1592 if (where
== BORDER
)
1593 key
= KEYC_DOUBLECLICK10_BORDER
;
1595 case MOUSE_BUTTON_11
:
1597 key
= KEYC_DOUBLECLICK11_PANE
;
1598 if (where
== STATUS
)
1599 key
= KEYC_DOUBLECLICK11_STATUS
;
1600 if (where
== STATUS_LEFT
)
1601 key
= KEYC_DOUBLECLICK11_STATUS_LEFT
;
1602 if (where
== STATUS_RIGHT
)
1603 key
= KEYC_DOUBLECLICK11_STATUS_RIGHT
;
1604 if (where
== STATUS_DEFAULT
)
1605 key
= KEYC_DOUBLECLICK11_STATUS_DEFAULT
;
1606 if (where
== BORDER
)
1607 key
= KEYC_DOUBLECLICK11_BORDER
;
1612 switch (MOUSE_BUTTONS(b
)) {
1613 case MOUSE_BUTTON_1
:
1615 key
= KEYC_TRIPLECLICK1_PANE
;
1616 if (where
== STATUS
)
1617 key
= KEYC_TRIPLECLICK1_STATUS
;
1618 if (where
== STATUS_LEFT
)
1619 key
= KEYC_TRIPLECLICK1_STATUS_LEFT
;
1620 if (where
== STATUS_RIGHT
)
1621 key
= KEYC_TRIPLECLICK1_STATUS_RIGHT
;
1622 if (where
== STATUS_DEFAULT
)
1623 key
= KEYC_TRIPLECLICK1_STATUS_DEFAULT
;
1624 if (where
== BORDER
)
1625 key
= KEYC_TRIPLECLICK1_BORDER
;
1627 case MOUSE_BUTTON_2
:
1629 key
= KEYC_TRIPLECLICK2_PANE
;
1630 if (where
== STATUS
)
1631 key
= KEYC_TRIPLECLICK2_STATUS
;
1632 if (where
== STATUS_LEFT
)
1633 key
= KEYC_TRIPLECLICK2_STATUS_LEFT
;
1634 if (where
== STATUS_RIGHT
)
1635 key
= KEYC_TRIPLECLICK2_STATUS_RIGHT
;
1636 if (where
== STATUS_DEFAULT
)
1637 key
= KEYC_TRIPLECLICK2_STATUS_DEFAULT
;
1638 if (where
== BORDER
)
1639 key
= KEYC_TRIPLECLICK2_BORDER
;
1641 case MOUSE_BUTTON_3
:
1643 key
= KEYC_TRIPLECLICK3_PANE
;
1644 if (where
== STATUS
)
1645 key
= KEYC_TRIPLECLICK3_STATUS
;
1646 if (where
== STATUS_LEFT
)
1647 key
= KEYC_TRIPLECLICK3_STATUS_LEFT
;
1648 if (where
== STATUS_RIGHT
)
1649 key
= KEYC_TRIPLECLICK3_STATUS_RIGHT
;
1650 if (where
== STATUS_DEFAULT
)
1651 key
= KEYC_TRIPLECLICK3_STATUS_DEFAULT
;
1652 if (where
== BORDER
)
1653 key
= KEYC_TRIPLECLICK3_BORDER
;
1655 case MOUSE_BUTTON_6
:
1657 key
= KEYC_TRIPLECLICK6_PANE
;
1658 if (where
== STATUS
)
1659 key
= KEYC_TRIPLECLICK6_STATUS
;
1660 if (where
== STATUS_LEFT
)
1661 key
= KEYC_TRIPLECLICK6_STATUS_LEFT
;
1662 if (where
== STATUS_RIGHT
)
1663 key
= KEYC_TRIPLECLICK6_STATUS_RIGHT
;
1664 if (where
== STATUS_DEFAULT
)
1665 key
= KEYC_TRIPLECLICK6_STATUS_DEFAULT
;
1666 if (where
== BORDER
)
1667 key
= KEYC_TRIPLECLICK6_BORDER
;
1669 case MOUSE_BUTTON_7
:
1671 key
= KEYC_TRIPLECLICK7_PANE
;
1672 if (where
== STATUS
)
1673 key
= KEYC_TRIPLECLICK7_STATUS
;
1674 if (where
== STATUS_LEFT
)
1675 key
= KEYC_TRIPLECLICK7_STATUS_LEFT
;
1676 if (where
== STATUS_RIGHT
)
1677 key
= KEYC_TRIPLECLICK7_STATUS_RIGHT
;
1678 if (where
== STATUS_DEFAULT
)
1679 key
= KEYC_TRIPLECLICK7_STATUS_DEFAULT
;
1680 if (where
== BORDER
)
1681 key
= KEYC_TRIPLECLICK7_BORDER
;
1683 case MOUSE_BUTTON_8
:
1685 key
= KEYC_TRIPLECLICK8_PANE
;
1686 if (where
== STATUS
)
1687 key
= KEYC_TRIPLECLICK8_STATUS
;
1688 if (where
== STATUS_LEFT
)
1689 key
= KEYC_TRIPLECLICK8_STATUS_LEFT
;
1690 if (where
== STATUS_RIGHT
)
1691 key
= KEYC_TRIPLECLICK8_STATUS_RIGHT
;
1692 if (where
== STATUS_DEFAULT
)
1693 key
= KEYC_TRIPLECLICK8_STATUS_DEFAULT
;
1694 if (where
== BORDER
)
1695 key
= KEYC_TRIPLECLICK8_BORDER
;
1697 case MOUSE_BUTTON_9
:
1699 key
= KEYC_TRIPLECLICK9_PANE
;
1700 if (where
== STATUS
)
1701 key
= KEYC_TRIPLECLICK9_STATUS
;
1702 if (where
== STATUS_LEFT
)
1703 key
= KEYC_TRIPLECLICK9_STATUS_LEFT
;
1704 if (where
== STATUS_RIGHT
)
1705 key
= KEYC_TRIPLECLICK9_STATUS_RIGHT
;
1706 if (where
== STATUS_DEFAULT
)
1707 key
= KEYC_TRIPLECLICK9_STATUS_DEFAULT
;
1708 if (where
== BORDER
)
1709 key
= KEYC_TRIPLECLICK9_BORDER
;
1711 case MOUSE_BUTTON_10
:
1713 key
= KEYC_TRIPLECLICK10_PANE
;
1714 if (where
== STATUS
)
1715 key
= KEYC_TRIPLECLICK10_STATUS
;
1716 if (where
== STATUS_LEFT
)
1717 key
= KEYC_TRIPLECLICK10_STATUS_LEFT
;
1718 if (where
== STATUS_RIGHT
)
1719 key
= KEYC_TRIPLECLICK10_STATUS_RIGHT
;
1720 if (where
== STATUS_DEFAULT
)
1721 key
= KEYC_TRIPLECLICK10_STATUS_DEFAULT
;
1722 if (where
== BORDER
)
1723 key
= KEYC_TRIPLECLICK10_BORDER
;
1725 case MOUSE_BUTTON_11
:
1727 key
= KEYC_TRIPLECLICK11_PANE
;
1728 if (where
== STATUS
)
1729 key
= KEYC_TRIPLECLICK11_STATUS
;
1730 if (where
== STATUS_LEFT
)
1731 key
= KEYC_TRIPLECLICK11_STATUS_LEFT
;
1732 if (where
== STATUS_RIGHT
)
1733 key
= KEYC_TRIPLECLICK11_STATUS_RIGHT
;
1734 if (where
== STATUS_DEFAULT
)
1735 key
= KEYC_TRIPLECLICK11_STATUS_DEFAULT
;
1736 if (where
== BORDER
)
1737 key
= KEYC_TRIPLECLICK11_BORDER
;
1742 if (key
== KEYC_UNKNOWN
)
1743 return (KEYC_UNKNOWN
);
1746 /* Apply modifiers if any. */
1747 if (b
& MOUSE_MASK_META
)
1749 if (b
& MOUSE_MASK_CTRL
)
1751 if (b
& MOUSE_MASK_SHIFT
)
1754 if (log_get_level() != 0)
1755 log_debug("mouse key is %s", key_string_lookup_key (key
, 1));
1759 /* Is this fast enough to probably be a paste? */
1761 server_client_assume_paste(struct session
*s
)
1766 if ((t
= options_get_number(s
->options
, "assume-paste-time")) == 0)
1769 timersub(&s
->activity_time
, &s
->last_activity_time
, &tv
);
1770 if (tv
.tv_sec
== 0 && tv
.tv_usec
< t
* 1000) {
1771 log_debug("session %s pasting (flag %d)", s
->name
,
1772 !!(s
->flags
& SESSION_PASTING
));
1773 if (s
->flags
& SESSION_PASTING
)
1775 s
->flags
|= SESSION_PASTING
;
1778 log_debug("session %s not pasting", s
->name
);
1779 s
->flags
&= ~SESSION_PASTING
;
1783 /* Has the latest client changed? */
1785 server_client_update_latest(struct client
*c
)
1789 if (c
->session
== NULL
)
1791 w
= c
->session
->curw
->window
;
1797 if (options_get_number(w
->options
, "window-size") == WINDOW_SIZE_LATEST
)
1798 recalculate_size(w
, 0);
1800 notify_client("client-active", c
);
1804 * Handle data key input from client. This owns and can modify the key event it
1805 * is given and is responsible for freeing it.
1807 static enum cmd_retval
1808 server_client_key_callback(struct cmdq_item
*item
, void *data
)
1810 struct client
*c
= cmdq_get_client(item
);
1811 struct key_event
*event
= data
;
1812 key_code key
= event
->key
;
1813 struct mouse_event
*m
= &event
->m
;
1814 struct session
*s
= c
->session
;
1816 struct window_pane
*wp
;
1817 struct window_mode_entry
*wme
;
1819 struct key_table
*table
, *first
;
1820 struct key_binding
*bd
;
1821 int xtimeout
, flags
;
1822 struct cmd_find_state fs
;
1825 /* Check the client is good to accept input. */
1826 if (s
== NULL
|| (c
->flags
& CLIENT_UNATTACHEDFLAGS
))
1830 /* Update the activity timer. */
1831 if (gettimeofday(&c
->activity_time
, NULL
) != 0)
1832 fatal("gettimeofday failed");
1833 session_update_activity(s
, &c
->activity_time
);
1835 /* Check for mouse keys. */
1837 if (key
== KEYC_MOUSE
|| key
== KEYC_DOUBLECLICK
) {
1838 if (c
->flags
& CLIENT_READONLY
)
1840 key
= server_client_check_mouse(c
, event
);
1841 if (key
== KEYC_UNKNOWN
)
1848 * Mouse drag is in progress, so fire the callback (now that
1849 * the mouse event is valid).
1851 if ((key
& KEYC_MASK_KEY
) == KEYC_DRAGGING
) {
1852 c
->tty
.mouse_drag_update(c
, m
);
1858 /* Find affected pane. */
1859 if (!KEYC_IS_MOUSE(key
) || cmd_find_from_mouse(&fs
, m
, 0) != 0)
1860 cmd_find_from_client(&fs
, c
, 0);
1863 /* Forward mouse keys if disabled. */
1864 if (KEYC_IS_MOUSE(key
) && !options_get_number(s
->options
, "mouse"))
1867 /* Treat everything as a regular key when pasting is detected. */
1868 if (!KEYC_IS_MOUSE(key
) && server_client_assume_paste(s
))
1872 * Work out the current key table. If the pane is in a mode, use
1873 * the mode table instead of the default key table.
1875 if (server_client_is_default_key_table(c
, c
->keytable
) &&
1877 (wme
= TAILQ_FIRST(&wp
->modes
)) != NULL
&&
1878 wme
->mode
->key_table
!= NULL
)
1879 table
= key_bindings_get_table(wme
->mode
->key_table(wme
), 1);
1881 table
= c
->keytable
;
1886 * The prefix always takes precedence and forces a switch to the prefix
1887 * table, unless we are already there.
1889 key0
= (key
& (KEYC_MASK_KEY
|KEYC_MASK_MODIFIERS
));
1890 if ((key0
== (key_code
)options_get_number(s
->options
, "prefix") ||
1891 key0
== (key_code
)options_get_number(s
->options
, "prefix2")) &&
1892 strcmp(table
->name
, "prefix") != 0) {
1893 server_client_set_key_table(c
, "prefix");
1894 server_status_client(c
);
1900 /* Log key table. */
1902 log_debug("key table %s (no pane)", table
->name
);
1904 log_debug("key table %s (pane %%%u)", table
->name
, wp
->id
);
1905 if (c
->flags
& CLIENT_REPEAT
)
1906 log_debug("currently repeating");
1908 /* Try to see if there is a key binding in the current table. */
1909 bd
= key_bindings_get(table
, key0
);
1912 * Key was matched in this table. If currently repeating but a
1913 * non-repeating binding was found, stop repeating and try
1914 * again in the root table.
1916 if ((c
->flags
& CLIENT_REPEAT
) &&
1917 (~bd
->flags
& KEY_BINDING_REPEAT
)) {
1918 log_debug("found in key table %s (not repeating)",
1920 server_client_set_key_table(c
, NULL
);
1921 first
= table
= c
->keytable
;
1922 c
->flags
&= ~CLIENT_REPEAT
;
1923 server_status_client(c
);
1926 log_debug("found in key table %s", table
->name
);
1929 * Take a reference to this table to make sure the key binding
1930 * doesn't disappear.
1932 table
->references
++;
1935 * If this is a repeating key, start the timer. Otherwise reset
1936 * the client back to the root table.
1938 xtimeout
= options_get_number(s
->options
, "repeat-time");
1939 if (xtimeout
!= 0 && (bd
->flags
& KEY_BINDING_REPEAT
)) {
1940 c
->flags
|= CLIENT_REPEAT
;
1942 tv
.tv_sec
= xtimeout
/ 1000;
1943 tv
.tv_usec
= (xtimeout
% 1000) * 1000L;
1944 evtimer_del(&c
->repeat_timer
);
1945 evtimer_add(&c
->repeat_timer
, &tv
);
1947 c
->flags
&= ~CLIENT_REPEAT
;
1948 server_client_set_key_table(c
, NULL
);
1950 server_status_client(c
);
1952 /* Execute the key binding. */
1953 key_bindings_dispatch(bd
, item
, c
, event
, &fs
);
1954 key_bindings_unref_table(table
);
1959 * No match, try the ANY key.
1961 if (key0
!= KEYC_ANY
) {
1967 * No match in this table. If not in the root table or if repeating,
1968 * switch the client back to the root table and try again.
1970 log_debug("not found in key table %s", table
->name
);
1971 if (!server_client_is_default_key_table(c
, table
) ||
1972 (c
->flags
& CLIENT_REPEAT
)) {
1973 log_debug("trying in root table");
1974 server_client_set_key_table(c
, NULL
);
1975 table
= c
->keytable
;
1976 if (c
->flags
& CLIENT_REPEAT
)
1978 c
->flags
&= ~CLIENT_REPEAT
;
1979 server_status_client(c
);
1984 * No match in the root table either. If this wasn't the first table
1985 * tried, don't pass the key to the pane.
1987 if (first
!= table
&& (~flags
& CLIENT_REPEAT
)) {
1988 server_client_set_key_table(c
, NULL
);
1989 server_status_client(c
);
1994 if (c
->flags
& CLIENT_READONLY
)
1997 window_pane_key(wp
, c
, s
, wl
, key
, m
);
2000 if (s
!= NULL
&& key
!= KEYC_FOCUS_OUT
)
2001 server_client_update_latest(c
);
2003 return (CMD_RETURN_NORMAL
);
2006 /* Handle a key event. */
2008 server_client_handle_key(struct client
*c
, struct key_event
*event
)
2010 struct session
*s
= c
->session
;
2011 struct cmdq_item
*item
;
2013 /* Check the client is good to accept input. */
2014 if (s
== NULL
|| (c
->flags
& CLIENT_UNATTACHEDFLAGS
))
2018 * Key presses in overlay mode and the command prompt are a special
2019 * case. The queue might be blocked so they need to be processed
2020 * immediately rather than queued.
2022 if (~c
->flags
& CLIENT_READONLY
) {
2023 if (c
->message_string
!= NULL
) {
2024 if (c
->message_ignore_keys
)
2026 status_message_clear(c
);
2028 if (c
->overlay_key
!= NULL
) {
2029 switch (c
->overlay_key(c
, c
->overlay_data
, event
)) {
2033 server_client_clear_overlay(c
);
2037 server_client_clear_overlay(c
);
2038 if (c
->prompt_string
!= NULL
) {
2039 if (status_prompt_key(c
, event
->key
) == 0)
2045 * Add the key to the queue so it happens after any commands queued by
2048 item
= cmdq_get_callback(server_client_key_callback
, event
);
2049 cmdq_append(c
, item
);
2053 /* Client functions that need to happen every loop. */
2055 server_client_loop(void)
2059 struct window_pane
*wp
;
2061 /* Check for window resize. This is done before redrawing. */
2062 RB_FOREACH(w
, windows
, &windows
)
2063 server_client_check_window_resize(w
);
2065 /* Check clients. */
2066 TAILQ_FOREACH(c
, &clients
, entry
) {
2067 server_client_check_exit(c
);
2068 if (c
->session
!= NULL
) {
2069 server_client_check_modes(c
);
2070 server_client_check_redraw(c
);
2071 server_client_reset_state(c
);
2076 * Any windows will have been redrawn as part of clients, so clear
2079 RB_FOREACH(w
, windows
, &windows
) {
2080 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
2082 server_client_check_pane_resize(wp
);
2083 server_client_check_pane_buffer(wp
);
2085 wp
->flags
&= ~PANE_REDRAW
;
2087 check_window_name(w
);
2091 /* Check if window needs to be resized. */
2093 server_client_check_window_resize(struct window
*w
)
2097 if (~w
->flags
& WINDOW_RESIZE
)
2100 TAILQ_FOREACH(wl
, &w
->winlinks
, wentry
) {
2101 if (wl
->session
->attached
!= 0 && wl
->session
->curw
== wl
)
2107 log_debug("%s: resizing window @%u", __func__
, w
->id
);
2108 resize_window(w
, w
->new_sx
, w
->new_sy
, w
->new_xpixel
, w
->new_ypixel
);
2111 /* Resize timer event. */
2113 server_client_resize_timer(__unused
int fd
, __unused
short events
, void *data
)
2115 struct window_pane
*wp
= data
;
2117 log_debug("%s: %%%u resize timer expired", __func__
, wp
->id
);
2118 evtimer_del(&wp
->resize_timer
);
2121 /* Check if pane should be resized. */
2123 server_client_check_pane_resize(struct window_pane
*wp
)
2125 struct window_pane_resize
*r
;
2126 struct window_pane_resize
*r1
;
2127 struct window_pane_resize
*first
;
2128 struct window_pane_resize
*last
;
2129 struct timeval tv
= { .tv_usec
= 250000 };
2131 if (TAILQ_EMPTY(&wp
->resize_queue
))
2134 if (!event_initialized(&wp
->resize_timer
))
2135 evtimer_set(&wp
->resize_timer
, server_client_resize_timer
, wp
);
2136 if (evtimer_pending(&wp
->resize_timer
, NULL
))
2139 log_debug("%s: %%%u needs to be resized", __func__
, wp
->id
);
2140 TAILQ_FOREACH(r
, &wp
->resize_queue
, entry
) {
2141 log_debug("queued resize: %ux%u -> %ux%u", r
->osx
, r
->osy
,
2146 * There are three cases that matter:
2148 * - Only one resize. It can just be applied.
2150 * - Multiple resizes and the ending size is different from the
2151 * starting size. We can discard all resizes except the most recent.
2153 * - Multiple resizes and the ending size is the same as the starting
2154 * size. We must resize at least twice to force the application to
2155 * redraw. So apply the first and leave the last on the queue for
2158 first
= TAILQ_FIRST(&wp
->resize_queue
);
2159 last
= TAILQ_LAST(&wp
->resize_queue
, window_pane_resizes
);
2160 if (first
== last
) {
2161 /* Only one resize. */
2162 window_pane_send_resize(wp
, first
->sx
, first
->sy
);
2163 TAILQ_REMOVE(&wp
->resize_queue
, first
, entry
);
2165 } else if (last
->sx
!= first
->osx
|| last
->sy
!= first
->osy
) {
2166 /* Multiple resizes ending up with a different size. */
2167 window_pane_send_resize(wp
, last
->sx
, last
->sy
);
2168 TAILQ_FOREACH_SAFE(r
, &wp
->resize_queue
, entry
, r1
) {
2169 TAILQ_REMOVE(&wp
->resize_queue
, r
, entry
);
2174 * Multiple resizes ending up with the same size. There will
2175 * not be more than one to the same size in succession so we
2176 * can just use the last-but-one on the list and leave the last
2177 * for later. We reduce the time until the next check to avoid
2178 * a long delay between the resizes.
2180 r
= TAILQ_PREV(last
, window_pane_resizes
, entry
);
2181 window_pane_send_resize(wp
, r
->sx
, r
->sy
);
2182 TAILQ_FOREACH_SAFE(r
, &wp
->resize_queue
, entry
, r1
) {
2185 TAILQ_REMOVE(&wp
->resize_queue
, r
, entry
);
2190 evtimer_add(&wp
->resize_timer
, &tv
);
2193 /* Check pane buffer size. */
2195 server_client_check_pane_buffer(struct window_pane
*wp
)
2197 struct evbuffer
*evb
= wp
->event
->input
;
2200 struct window_pane_offset
*wpo
;
2202 u_int attached_clients
= 0;
2206 * Work out the minimum used size. This is the most that can be removed
2209 minimum
= wp
->offset
.used
;
2210 if (wp
->pipe_fd
!= -1 && wp
->pipe_offset
.used
< minimum
)
2211 minimum
= wp
->pipe_offset
.used
;
2212 TAILQ_FOREACH(c
, &clients
, entry
) {
2213 if (c
->session
== NULL
)
2217 if (~c
->flags
& CLIENT_CONTROL
) {
2221 wpo
= control_pane_offset(c
, wp
, &flag
);
2229 window_pane_get_new_data(wp
, wpo
, &new_size
);
2230 log_debug("%s: %s has %zu bytes used and %zu left for %%%u",
2231 __func__
, c
->name
, wpo
->used
- wp
->base_offset
, new_size
,
2233 if (wpo
->used
< minimum
)
2234 minimum
= wpo
->used
;
2236 if (attached_clients
== 0)
2238 minimum
-= wp
->base_offset
;
2242 /* Drain the buffer. */
2243 log_debug("%s: %%%u has %zu minimum (of %zu) bytes used", __func__
,
2244 wp
->id
, minimum
, EVBUFFER_LENGTH(evb
));
2245 evbuffer_drain(evb
, minimum
);
2248 * Adjust the base offset. If it would roll over, all the offsets into
2249 * the buffer need to be adjusted.
2251 if (wp
->base_offset
> SIZE_MAX
- minimum
) {
2252 log_debug("%s: %%%u base offset has wrapped", __func__
, wp
->id
);
2253 wp
->offset
.used
-= wp
->base_offset
;
2254 if (wp
->pipe_fd
!= -1)
2255 wp
->pipe_offset
.used
-= wp
->base_offset
;
2256 TAILQ_FOREACH(c
, &clients
, entry
) {
2257 if (c
->session
== NULL
|| (~c
->flags
& CLIENT_CONTROL
))
2259 wpo
= control_pane_offset(c
, wp
, &flag
);
2260 if (wpo
!= NULL
&& !flag
)
2261 wpo
->used
-= wp
->base_offset
;
2263 wp
->base_offset
= minimum
;
2265 wp
->base_offset
+= minimum
;
2269 * If there is data remaining, and there are no clients able to consume
2270 * it, do not read any more. This is true when there are attached
2271 * clients, all of which are control clients which are not able to
2272 * accept any more data.
2274 log_debug("%s: pane %%%u is %s", __func__
, wp
->id
, off
? "off" : "on");
2276 bufferevent_disable(wp
->event
, EV_READ
);
2278 bufferevent_enable(wp
->event
, EV_READ
);
2282 * Update cursor position and mode settings. The scroll region and attributes
2283 * are cleared when idle (waiting for an event) as this is the most likely time
2284 * a user may interrupt tmux, for example with ~^Z in ssh(1). This is a
2285 * compromise between excessive resets and likelihood of an interrupt.
2287 * tty_region/tty_reset/tty_update_mode already take care of not resetting
2288 * things that are already in their default state.
2291 server_client_reset_state(struct client
*c
)
2293 struct tty
*tty
= &c
->tty
;
2294 struct window
*w
= c
->session
->curw
->window
;
2295 struct window_pane
*wp
= server_client_get_pane(c
), *loop
;
2296 struct screen
*s
= NULL
;
2297 struct options
*oo
= c
->session
->options
;
2298 int mode
= 0, cursor
, flags
, n
;
2299 u_int cx
= 0, cy
= 0, ox
, oy
, sx
, sy
;
2301 if (c
->flags
& (CLIENT_CONTROL
|CLIENT_SUSPENDED
))
2304 /* Disable the block flag. */
2305 flags
= (tty
->flags
& TTY_BLOCK
);
2306 tty
->flags
&= ~TTY_BLOCK
;
2308 /* Get mode from overlay if any, else from screen. */
2309 if (c
->overlay_draw
!= NULL
) {
2310 if (c
->overlay_mode
!= NULL
)
2311 s
= c
->overlay_mode(c
, c
->overlay_data
, &cx
, &cy
);
2316 if (log_get_level() != 0) {
2317 log_debug("%s: client %s mode %s", __func__
, c
->name
,
2318 screen_mode_to_string(mode
));
2321 /* Reset region and margin. */
2322 tty_region_off(tty
);
2323 tty_margin_off(tty
);
2325 /* Move cursor to pane cursor and offset. */
2326 if (c
->prompt_string
!= NULL
) {
2327 n
= options_get_number(c
->session
->options
, "status-position");
2331 n
= status_line_size(c
);
2337 cx
= c
->prompt_cursor
;
2338 mode
&= ~MODE_CURSOR
;
2339 } else if (c
->overlay_draw
== NULL
) {
2341 tty_window_offset(tty
, &ox
, &oy
, &sx
, &sy
);
2342 if (wp
->xoff
+ s
->cx
>= ox
&& wp
->xoff
+ s
->cx
<= ox
+ sx
&&
2343 wp
->yoff
+ s
->cy
>= oy
&& wp
->yoff
+ s
->cy
<= oy
+ sy
) {
2346 cx
= wp
->xoff
+ s
->cx
- ox
;
2347 cy
= wp
->yoff
+ s
->cy
- oy
;
2349 if (status_at_line(c
) == 0)
2350 cy
+= status_line_size(c
);
2353 mode
&= ~MODE_CURSOR
;
2355 log_debug("%s: cursor to %u,%u", __func__
, cx
, cy
);
2356 tty_cursor(tty
, cx
, cy
);
2359 * Set mouse mode if requested. To support dragging, always use button
2362 if (options_get_number(oo
, "mouse")) {
2363 if (c
->overlay_draw
== NULL
) {
2364 mode
&= ~ALL_MOUSE_MODES
;
2365 TAILQ_FOREACH(loop
, &w
->panes
, entry
) {
2366 if (loop
->screen
->mode
& MODE_MOUSE_ALL
)
2367 mode
|= MODE_MOUSE_ALL
;
2370 if (~mode
& MODE_MOUSE_ALL
)
2371 mode
|= MODE_MOUSE_BUTTON
;
2374 /* Clear bracketed paste mode if at the prompt. */
2375 if (c
->overlay_draw
== NULL
&& c
->prompt_string
!= NULL
)
2376 mode
&= ~MODE_BRACKETPASTE
;
2378 /* Set the terminal mode and reset attributes. */
2379 tty_update_mode(tty
, mode
, s
);
2382 /* All writing must be done, send a sync end (if it was started). */
2384 tty
->flags
|= flags
;
2387 /* Repeat time callback. */
2389 server_client_repeat_timer(__unused
int fd
, __unused
short events
, void *data
)
2391 struct client
*c
= data
;
2393 if (c
->flags
& CLIENT_REPEAT
) {
2394 server_client_set_key_table(c
, NULL
);
2395 c
->flags
&= ~CLIENT_REPEAT
;
2396 server_status_client(c
);
2400 /* Double-click callback. */
2402 server_client_click_timer(__unused
int fd
, __unused
short events
, void *data
)
2404 struct client
*c
= data
;
2405 struct key_event
*event
;
2407 log_debug("click timer expired");
2409 if (c
->flags
& CLIENT_TRIPLECLICK
) {
2411 * Waiting for a third click that hasn't happened, so this must
2412 * have been a double click.
2414 event
= xmalloc(sizeof *event
);
2415 event
->key
= KEYC_DOUBLECLICK
;
2416 memcpy(&event
->m
, &c
->click_event
, sizeof event
->m
);
2417 if (!server_client_handle_key(c
, event
))
2420 c
->flags
&= ~(CLIENT_DOUBLECLICK
|CLIENT_TRIPLECLICK
);
2423 /* Check if client should be exited. */
2425 server_client_check_exit(struct client
*c
)
2427 struct client_file
*cf
;
2428 const char *name
= c
->exit_session
;
2432 if (c
->flags
& (CLIENT_DEAD
|CLIENT_EXITED
))
2434 if (~c
->flags
& CLIENT_EXIT
)
2437 if (c
->flags
& CLIENT_CONTROL
) {
2439 if (!control_all_done(c
))
2442 RB_FOREACH(cf
, client_files
, &c
->files
) {
2443 if (EVBUFFER_LENGTH(cf
->buffer
) != 0)
2446 c
->flags
|= CLIENT_EXITED
;
2448 switch (c
->exit_type
) {
2449 case CLIENT_EXIT_RETURN
:
2450 if (c
->exit_message
!= NULL
)
2451 msize
= strlen(c
->exit_message
) + 1;
2454 size
= (sizeof c
->retval
) + msize
;
2455 data
= xmalloc(size
);
2456 memcpy(data
, &c
->retval
, sizeof c
->retval
);
2457 if (c
->exit_message
!= NULL
)
2458 memcpy(data
+ sizeof c
->retval
, c
->exit_message
, msize
);
2459 proc_send(c
->peer
, MSG_EXIT
, -1, data
, size
);
2462 case CLIENT_EXIT_SHUTDOWN
:
2463 proc_send(c
->peer
, MSG_SHUTDOWN
, -1, NULL
, 0);
2465 case CLIENT_EXIT_DETACH
:
2466 proc_send(c
->peer
, c
->exit_msgtype
, -1, name
, strlen(name
) + 1);
2469 free(c
->exit_session
);
2470 free(c
->exit_message
);
2473 /* Redraw timer callback. */
2475 server_client_redraw_timer(__unused
int fd
, __unused
short events
,
2476 __unused
void *data
)
2478 log_debug("redraw timer fired");
2482 * Check if modes need to be updated. Only modes in the current window are
2483 * updated and it is done when the status line is redrawn.
2486 server_client_check_modes(struct client
*c
)
2488 struct window
*w
= c
->session
->curw
->window
;
2489 struct window_pane
*wp
;
2490 struct window_mode_entry
*wme
;
2492 if (c
->flags
& (CLIENT_CONTROL
|CLIENT_SUSPENDED
))
2494 if (~c
->flags
& CLIENT_REDRAWSTATUS
)
2496 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
2497 wme
= TAILQ_FIRST(&wp
->modes
);
2498 if (wme
!= NULL
&& wme
->mode
->update
!= NULL
)
2499 wme
->mode
->update(wme
);
2503 /* Check for client redraws. */
2505 server_client_check_redraw(struct client
*c
)
2507 struct session
*s
= c
->session
;
2508 struct tty
*tty
= &c
->tty
;
2509 struct window
*w
= c
->session
->curw
->window
;
2510 struct window_pane
*wp
;
2511 int needed
, flags
, mode
= tty
->mode
, new_flags
= 0;
2514 struct timeval tv
= { .tv_usec
= 1000 };
2515 static struct event ev
;
2518 if (c
->flags
& (CLIENT_CONTROL
|CLIENT_SUSPENDED
))
2520 if (c
->flags
& CLIENT_ALLREDRAWFLAGS
) {
2521 log_debug("%s: redraw%s%s%s%s%s", c
->name
,
2522 (c
->flags
& CLIENT_REDRAWWINDOW
) ? " window" : "",
2523 (c
->flags
& CLIENT_REDRAWSTATUS
) ? " status" : "",
2524 (c
->flags
& CLIENT_REDRAWBORDERS
) ? " borders" : "",
2525 (c
->flags
& CLIENT_REDRAWOVERLAY
) ? " overlay" : "",
2526 (c
->flags
& CLIENT_REDRAWPANES
) ? " panes" : "");
2530 * If there is outstanding data, defer the redraw until it has been
2531 * consumed. We can just add a timer to get out of the event loop and
2535 if (c
->flags
& CLIENT_ALLREDRAWFLAGS
)
2538 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
2539 if (wp
->flags
& PANE_REDRAW
) {
2545 new_flags
|= CLIENT_REDRAWPANES
;
2547 if (needed
&& (left
= EVBUFFER_LENGTH(tty
->out
)) != 0) {
2548 log_debug("%s: redraw deferred (%zu left)", c
->name
, left
);
2549 if (!evtimer_initialized(&ev
))
2550 evtimer_set(&ev
, server_client_redraw_timer
, NULL
);
2551 if (!evtimer_pending(&ev
, NULL
)) {
2552 log_debug("redraw timer started");
2553 evtimer_add(&ev
, &tv
);
2556 if (~c
->flags
& CLIENT_REDRAWWINDOW
) {
2557 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
2558 if (wp
->flags
& PANE_REDRAW
) {
2559 log_debug("%s: pane %%%u needs redraw",
2561 c
->redraw_panes
|= (1 << bit
);
2565 * If more that 64 panes, give up and
2566 * just redraw the window.
2568 new_flags
&= CLIENT_REDRAWPANES
;
2569 new_flags
|= CLIENT_REDRAWWINDOW
;
2573 if (c
->redraw_panes
!= 0)
2574 c
->flags
|= CLIENT_REDRAWPANES
;
2576 c
->flags
|= new_flags
;
2579 log_debug("%s: redraw needed", c
->name
);
2581 flags
= tty
->flags
& (TTY_BLOCK
|TTY_FREEZE
|TTY_NOCURSOR
);
2582 tty
->flags
= (tty
->flags
& ~(TTY_BLOCK
|TTY_FREEZE
))|TTY_NOCURSOR
;
2584 if (~c
->flags
& CLIENT_REDRAWWINDOW
) {
2586 * If not redrawing the entire window, check whether each pane
2587 * needs to be redrawn.
2589 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
2591 if (wp
->flags
& PANE_REDRAW
)
2593 else if (c
->flags
& CLIENT_REDRAWPANES
)
2594 redraw
= !!(c
->redraw_panes
& (1 << bit
));
2598 log_debug("%s: redrawing pane %%%u", __func__
, wp
->id
);
2599 screen_redraw_pane(c
, wp
);
2601 c
->redraw_panes
= 0;
2602 c
->flags
&= ~CLIENT_REDRAWPANES
;
2605 if (c
->flags
& CLIENT_ALLREDRAWFLAGS
) {
2606 if (options_get_number(s
->options
, "set-titles"))
2607 server_client_set_title(c
);
2608 screen_redraw_screen(c
);
2611 tty
->flags
= (tty
->flags
& ~TTY_NOCURSOR
)|(flags
& TTY_NOCURSOR
);
2612 tty_update_mode(tty
, mode
, NULL
);
2613 tty
->flags
= (tty
->flags
& ~(TTY_BLOCK
|TTY_FREEZE
|TTY_NOCURSOR
))|flags
;
2615 c
->flags
&= ~(CLIENT_ALLREDRAWFLAGS
|CLIENT_STATUSFORCE
);
2619 * We would have deferred the redraw unless the output buffer
2620 * was empty, so we can record how many bytes the redraw
2623 c
->redraw
= EVBUFFER_LENGTH(tty
->out
);
2624 log_debug("%s: redraw added %zu bytes", c
->name
, c
->redraw
);
2628 /* Set client title. */
2630 server_client_set_title(struct client
*c
)
2632 struct session
*s
= c
->session
;
2633 const char *template;
2635 struct format_tree
*ft
;
2637 template = options_get_string(s
->options
, "set-titles-string");
2639 ft
= format_create(c
, NULL
, FORMAT_NONE
, 0);
2640 format_defaults(ft
, c
, NULL
, NULL
, NULL
);
2642 title
= format_expand_time(ft
, template);
2643 if (c
->title
== NULL
|| strcmp(title
, c
->title
) != 0) {
2645 c
->title
= xstrdup(title
);
2646 tty_set_title(&c
->tty
, c
->title
);
2653 /* Dispatch message from client. */
2655 server_client_dispatch(struct imsg
*imsg
, void *arg
)
2657 struct client
*c
= arg
;
2661 if (c
->flags
& CLIENT_DEAD
)
2665 server_client_lost(c
);
2669 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
2671 switch (imsg
->hdr
.type
) {
2672 case MSG_IDENTIFY_CLIENTPID
:
2673 case MSG_IDENTIFY_CWD
:
2674 case MSG_IDENTIFY_ENVIRON
:
2675 case MSG_IDENTIFY_FEATURES
:
2676 case MSG_IDENTIFY_FLAGS
:
2677 case MSG_IDENTIFY_LONGFLAGS
:
2678 case MSG_IDENTIFY_STDIN
:
2679 case MSG_IDENTIFY_STDOUT
:
2680 case MSG_IDENTIFY_TERM
:
2681 case MSG_IDENTIFY_TERMINFO
:
2682 case MSG_IDENTIFY_TTYNAME
:
2683 case MSG_IDENTIFY_DONE
:
2684 server_client_dispatch_identify(c
, imsg
);
2687 server_client_dispatch_command(c
, imsg
);
2691 fatalx("bad MSG_RESIZE size");
2693 if (c
->flags
& CLIENT_CONTROL
)
2695 server_client_update_latest(c
);
2696 tty_resize(&c
->tty
);
2697 recalculate_sizes();
2698 if (c
->overlay_resize
== NULL
)
2699 server_client_clear_overlay(c
);
2701 c
->overlay_resize(c
, c
->overlay_data
);
2702 server_redraw_client(c
);
2703 if (c
->session
!= NULL
)
2704 notify_client("client-resized", c
);
2708 fatalx("bad MSG_EXITING size");
2709 server_client_set_session(c
, NULL
);
2710 recalculate_sizes();
2712 proc_send(c
->peer
, MSG_EXITED
, -1, NULL
, 0);
2717 fatalx("bad MSG_WAKEUP size");
2719 if (!(c
->flags
& CLIENT_SUSPENDED
))
2721 c
->flags
&= ~CLIENT_SUSPENDED
;
2723 if (c
->fd
== -1 || c
->session
== NULL
) /* exited already */
2727 if (gettimeofday(&c
->activity_time
, NULL
) != 0)
2728 fatal("gettimeofday failed");
2730 tty_start_tty(&c
->tty
);
2731 server_redraw_client(c
);
2732 recalculate_sizes();
2735 session_update_activity(s
, &c
->activity_time
);
2739 fatalx("bad MSG_SHELL size");
2741 server_client_dispatch_shell(c
);
2743 case MSG_WRITE_READY
:
2744 file_write_ready(&c
->files
, imsg
);
2747 file_read_data(&c
->files
, imsg
);
2750 file_read_done(&c
->files
, imsg
);
2755 /* Callback when command is done. */
2756 static enum cmd_retval
2757 server_client_command_done(struct cmdq_item
*item
, __unused
void *data
)
2759 struct client
*c
= cmdq_get_client(item
);
2761 if (~c
->flags
& CLIENT_ATTACHED
)
2762 c
->flags
|= CLIENT_EXIT
;
2763 else if (~c
->flags
& CLIENT_EXIT
)
2764 tty_send_requests(&c
->tty
);
2765 return (CMD_RETURN_NORMAL
);
2768 /* Handle command message. */
2770 server_client_dispatch_command(struct client
*c
, struct imsg
*imsg
)
2772 struct msg_command data
;
2776 char **argv
, *cause
;
2777 struct cmd_parse_result
*pr
;
2778 struct args_value
*values
;
2780 if (c
->flags
& CLIENT_EXIT
)
2783 if (imsg
->hdr
.len
- IMSG_HEADER_SIZE
< sizeof data
)
2784 fatalx("bad MSG_COMMAND size");
2785 memcpy(&data
, imsg
->data
, sizeof data
);
2787 buf
= (char *)imsg
->data
+ sizeof data
;
2788 len
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
- sizeof data
;
2789 if (len
> 0 && buf
[len
- 1] != '\0')
2790 fatalx("bad MSG_COMMAND string");
2793 if (cmd_unpack_argv(buf
, len
, argc
, &argv
) != 0) {
2794 cause
= xstrdup("command too long");
2800 argv
= xcalloc(1, sizeof *argv
);
2801 *argv
= xstrdup("new-session");
2804 values
= args_from_vector(argc
, argv
);
2805 pr
= cmd_parse_from_arguments(values
, argc
, NULL
);
2806 switch (pr
->status
) {
2807 case CMD_PARSE_ERROR
:
2810 case CMD_PARSE_SUCCESS
:
2813 args_free_values(values
, argc
);
2815 cmd_free_argv(argc
, argv
);
2817 cmdq_append(c
, cmdq_get_command(pr
->cmdlist
, NULL
));
2818 cmdq_append(c
, cmdq_get_callback(server_client_command_done
, NULL
));
2820 cmd_list_free(pr
->cmdlist
);
2824 cmd_free_argv(argc
, argv
);
2826 cmdq_append(c
, cmdq_get_error(cause
));
2829 c
->flags
|= CLIENT_EXIT
;
2832 /* Handle identify message. */
2834 server_client_dispatch_identify(struct client
*c
, struct imsg
*imsg
)
2836 const char *data
, *home
;
2842 if (c
->flags
& CLIENT_IDENTIFIED
)
2843 fatalx("out-of-order identify message");
2846 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
2848 switch (imsg
->hdr
.type
) {
2849 case MSG_IDENTIFY_FEATURES
:
2850 if (datalen
!= sizeof feat
)
2851 fatalx("bad MSG_IDENTIFY_FEATURES size");
2852 memcpy(&feat
, data
, sizeof feat
);
2853 c
->term_features
|= feat
;
2854 log_debug("client %p IDENTIFY_FEATURES %s", c
,
2855 tty_get_features(feat
));
2857 case MSG_IDENTIFY_FLAGS
:
2858 if (datalen
!= sizeof flags
)
2859 fatalx("bad MSG_IDENTIFY_FLAGS size");
2860 memcpy(&flags
, data
, sizeof flags
);
2862 log_debug("client %p IDENTIFY_FLAGS %#x", c
, flags
);
2864 case MSG_IDENTIFY_LONGFLAGS
:
2865 if (datalen
!= sizeof longflags
)
2866 fatalx("bad MSG_IDENTIFY_LONGFLAGS size");
2867 memcpy(&longflags
, data
, sizeof longflags
);
2868 c
->flags
|= longflags
;
2869 log_debug("client %p IDENTIFY_LONGFLAGS %#llx", c
,
2870 (unsigned long long)longflags
);
2872 case MSG_IDENTIFY_TERM
:
2873 if (datalen
== 0 || data
[datalen
- 1] != '\0')
2874 fatalx("bad MSG_IDENTIFY_TERM string");
2876 c
->term_name
= xstrdup("unknown");
2878 c
->term_name
= xstrdup(data
);
2879 log_debug("client %p IDENTIFY_TERM %s", c
, data
);
2881 case MSG_IDENTIFY_TERMINFO
:
2882 if (datalen
== 0 || data
[datalen
- 1] != '\0')
2883 fatalx("bad MSG_IDENTIFY_TERMINFO string");
2884 c
->term_caps
= xreallocarray(c
->term_caps
, c
->term_ncaps
+ 1,
2885 sizeof *c
->term_caps
);
2886 c
->term_caps
[c
->term_ncaps
++] = xstrdup(data
);
2887 log_debug("client %p IDENTIFY_TERMINFO %s", c
, data
);
2889 case MSG_IDENTIFY_TTYNAME
:
2890 if (datalen
== 0 || data
[datalen
- 1] != '\0')
2891 fatalx("bad MSG_IDENTIFY_TTYNAME string");
2892 c
->ttyname
= xstrdup(data
);
2893 log_debug("client %p IDENTIFY_TTYNAME %s", c
, data
);
2895 case MSG_IDENTIFY_CWD
:
2896 if (datalen
== 0 || data
[datalen
- 1] != '\0')
2897 fatalx("bad MSG_IDENTIFY_CWD string");
2898 if (access(data
, X_OK
) == 0)
2899 c
->cwd
= xstrdup(data
);
2900 else if ((home
= find_home()) != NULL
)
2901 c
->cwd
= xstrdup(home
);
2903 c
->cwd
= xstrdup("/");
2904 log_debug("client %p IDENTIFY_CWD %s", c
, data
);
2906 case MSG_IDENTIFY_STDIN
:
2908 fatalx("bad MSG_IDENTIFY_STDIN size");
2910 log_debug("client %p IDENTIFY_STDIN %d", c
, imsg
->fd
);
2912 case MSG_IDENTIFY_STDOUT
:
2914 fatalx("bad MSG_IDENTIFY_STDOUT size");
2915 c
->out_fd
= imsg
->fd
;
2916 log_debug("client %p IDENTIFY_STDOUT %d", c
, imsg
->fd
);
2918 case MSG_IDENTIFY_ENVIRON
:
2919 if (datalen
== 0 || data
[datalen
- 1] != '\0')
2920 fatalx("bad MSG_IDENTIFY_ENVIRON string");
2921 if (strchr(data
, '=') != NULL
)
2922 environ_put(c
->environ
, data
, 0);
2923 log_debug("client %p IDENTIFY_ENVIRON %s", c
, data
);
2925 case MSG_IDENTIFY_CLIENTPID
:
2926 if (datalen
!= sizeof c
->pid
)
2927 fatalx("bad MSG_IDENTIFY_CLIENTPID size");
2928 memcpy(&c
->pid
, data
, sizeof c
->pid
);
2929 log_debug("client %p IDENTIFY_CLIENTPID %ld", c
, (long)c
->pid
);
2935 if (imsg
->hdr
.type
!= MSG_IDENTIFY_DONE
)
2937 c
->flags
|= CLIENT_IDENTIFIED
;
2939 if (*c
->ttyname
!= '\0')
2940 name
= xstrdup(c
->ttyname
);
2942 xasprintf(&name
, "client-%ld", (long)c
->pid
);
2944 log_debug("client %p name is %s", c
, c
->name
);
2946 if (c
->flags
& CLIENT_CONTROL
)
2948 else if (c
->fd
!= -1) {
2949 if (tty_init(&c
->tty
, c
) != 0) {
2953 tty_resize(&c
->tty
);
2954 c
->flags
|= CLIENT_TERMINAL
;
2961 * If this is the first client, load configuration files. Any later
2962 * clients are allowed to continue with their command even if the
2963 * config has not been loaded - they might have been run from inside it
2965 if ((~c
->flags
& CLIENT_EXIT
) &&
2967 c
== TAILQ_FIRST(&clients
))
2971 /* Handle shell message. */
2973 server_client_dispatch_shell(struct client
*c
)
2977 shell
= options_get_string(global_s_options
, "default-shell");
2978 if (!checkshell(shell
))
2979 shell
= _PATH_BSHELL
;
2980 proc_send(c
->peer
, MSG_SHELL
, -1, shell
, strlen(shell
) + 1);
2982 proc_kill_peer(c
->peer
);
2985 /* Get client working directory. */
2987 server_client_get_cwd(struct client
*c
, struct session
*s
)
2991 if (!cfg_finished
&& cfg_client
!= NULL
)
2992 return (cfg_client
->cwd
);
2993 if (c
!= NULL
&& c
->session
== NULL
&& c
->cwd
!= NULL
)
2995 if (s
!= NULL
&& s
->cwd
!= NULL
)
2997 if (c
!= NULL
&& (s
= c
->session
) != NULL
&& s
->cwd
!= NULL
)
2999 if ((home
= find_home()) != NULL
)
3004 /* Get control client flags. */
3006 server_client_control_flags(struct client
*c
, const char *next
)
3008 if (strcmp(next
, "pause-after") == 0) {
3010 return (CLIENT_CONTROL_PAUSEAFTER
);
3012 if (sscanf(next
, "pause-after=%u", &c
->pause_age
) == 1) {
3013 c
->pause_age
*= 1000;
3014 return (CLIENT_CONTROL_PAUSEAFTER
);
3016 if (strcmp(next
, "no-output") == 0)
3017 return (CLIENT_CONTROL_NOOUTPUT
);
3018 if (strcmp(next
, "wait-exit") == 0)
3019 return (CLIENT_CONTROL_WAITEXIT
);
3023 /* Set client flags. */
3025 server_client_set_flags(struct client
*c
, const char *flags
)
3027 char *s
, *copy
, *next
;
3031 s
= copy
= xstrdup(flags
);
3032 while ((next
= strsep(&s
, ",")) != NULL
) {
3033 not = (*next
== '!');
3037 if (c
->flags
& CLIENT_CONTROL
)
3038 flag
= server_client_control_flags(c
, next
);
3041 if (strcmp(next
, "read-only") == 0)
3042 flag
= CLIENT_READONLY
;
3043 else if (strcmp(next
, "ignore-size") == 0)
3044 flag
= CLIENT_IGNORESIZE
;
3045 else if (strcmp(next
, "active-pane") == 0)
3046 flag
= CLIENT_ACTIVEPANE
;
3050 log_debug("client %s set flag %s", c
->name
, next
);
3055 if (flag
== CLIENT_CONTROL_NOOUTPUT
)
3056 control_reset_offsets(c
);
3059 proc_send(c
->peer
, MSG_FLAGS
, -1, &c
->flags
, sizeof c
->flags
);
3062 /* Get client flags. This is only flags useful to show to users. */
3064 server_client_get_flags(struct client
*c
)
3070 if (c
->flags
& CLIENT_ATTACHED
)
3071 strlcat(s
, "attached,", sizeof s
);
3072 if (c
->flags
& CLIENT_FOCUSED
)
3073 strlcat(s
, "focused,", sizeof s
);
3074 if (c
->flags
& CLIENT_CONTROL
)
3075 strlcat(s
, "control-mode,", sizeof s
);
3076 if (c
->flags
& CLIENT_IGNORESIZE
)
3077 strlcat(s
, "ignore-size,", sizeof s
);
3078 if (c
->flags
& CLIENT_CONTROL_NOOUTPUT
)
3079 strlcat(s
, "no-output,", sizeof s
);
3080 if (c
->flags
& CLIENT_CONTROL_WAITEXIT
)
3081 strlcat(s
, "wait-exit,", sizeof s
);
3082 if (c
->flags
& CLIENT_CONTROL_PAUSEAFTER
) {
3083 xsnprintf(tmp
, sizeof tmp
, "pause-after=%u,",
3084 c
->pause_age
/ 1000);
3085 strlcat(s
, tmp
, sizeof s
);
3087 if (c
->flags
& CLIENT_READONLY
)
3088 strlcat(s
, "read-only,", sizeof s
);
3089 if (c
->flags
& CLIENT_ACTIVEPANE
)
3090 strlcat(s
, "active-pane,", sizeof s
);
3091 if (c
->flags
& CLIENT_SUSPENDED
)
3092 strlcat(s
, "suspended,", sizeof s
);
3093 if (c
->flags
& CLIENT_UTF8
)
3094 strlcat(s
, "UTF-8,", sizeof s
);
3096 s
[strlen(s
) - 1] = '\0';
3100 /* Get client window. */
3101 struct client_window
*
3102 server_client_get_client_window(struct client
*c
, u_int id
)
3104 struct client_window cw
= { .window
= id
};
3106 return (RB_FIND(client_windows
, &c
->windows
, &cw
));
3109 /* Add client window. */
3110 struct client_window
*
3111 server_client_add_client_window(struct client
*c
, u_int id
)
3113 struct client_window
*cw
;
3115 cw
= server_client_get_client_window(c
, id
);
3117 cw
= xcalloc(1, sizeof *cw
);
3119 RB_INSERT(client_windows
, &c
->windows
, cw
);
3124 /* Get client active pane. */
3125 struct window_pane
*
3126 server_client_get_pane(struct client
*c
)
3128 struct session
*s
= c
->session
;
3129 struct client_window
*cw
;
3134 if (~c
->flags
& CLIENT_ACTIVEPANE
)
3135 return (s
->curw
->window
->active
);
3136 cw
= server_client_get_client_window(c
, s
->curw
->window
->id
);
3138 return (s
->curw
->window
->active
);
3142 /* Set client active pane. */
3144 server_client_set_pane(struct client
*c
, struct window_pane
*wp
)
3146 struct session
*s
= c
->session
;
3147 struct client_window
*cw
;
3152 cw
= server_client_add_client_window(c
, s
->curw
->window
->id
);
3154 log_debug("%s pane now %%%u", c
->name
, wp
->id
);
3157 /* Remove pane from client lists. */
3159 server_client_remove_pane(struct window_pane
*wp
)
3162 struct window
*w
= wp
->window
;
3163 struct client_window
*cw
;
3165 TAILQ_FOREACH(c
, &clients
, entry
) {
3166 cw
= server_client_get_client_window(c
, w
->id
);
3167 if (cw
!= NULL
&& cw
->pane
== wp
) {
3168 RB_REMOVE(client_windows
, &c
->windows
, cw
);