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>
45 static void server_client_free(int, short, void *);
46 static void server_client_check_pane_resize(struct window_pane
*);
47 static void server_client_check_pane_buffer(struct window_pane
*);
48 static void server_client_check_window_resize(struct window
*);
49 static key_code
server_client_check_mouse(struct client
*, struct key_event
*);
50 static void server_client_repeat_timer(int, short, void *);
51 static void server_client_click_timer(int, short, void *);
52 static void server_client_check_exit(struct client
*);
53 static void server_client_check_redraw(struct client
*);
54 static void server_client_check_modes(struct client
*);
55 static void server_client_set_title(struct client
*);
56 static void server_client_set_path(struct client
*);
57 static void server_client_reset_state(struct client
*);
58 static void server_client_update_latest(struct client
*);
60 static void server_client_dispatch(struct imsg
*, void *);
61 static void server_client_dispatch_command(struct client
*, struct imsg
*);
62 static void server_client_dispatch_identify(struct client
*, struct imsg
*);
63 static void server_client_dispatch_shell(struct client
*);
65 /* Compare client windows. */
67 server_client_window_cmp(struct client_window
*cw1
,
68 struct client_window
*cw2
)
70 if (cw1
->window
< cw2
->window
)
72 if (cw1
->window
> cw2
->window
)
76 RB_GENERATE(client_windows
, client_window
, entry
, server_client_window_cmp
);
78 /* Number of attached clients. */
80 server_client_how_many(void)
86 TAILQ_FOREACH(c
, &clients
, entry
) {
87 if (c
->session
!= NULL
&& (~c
->flags
& CLIENT_UNATTACHEDFLAGS
))
93 /* Overlay timer callback. */
95 server_client_overlay_timer(__unused
int fd
, __unused
short events
, void *data
)
97 server_client_clear_overlay(data
);
100 /* Set an overlay on client. */
102 server_client_set_overlay(struct client
*c
, u_int delay
,
103 overlay_check_cb checkcb
, overlay_mode_cb modecb
,
104 overlay_draw_cb drawcb
, overlay_key_cb keycb
, overlay_free_cb freecb
,
105 overlay_resize_cb resizecb
, void *data
)
109 if (c
->overlay_draw
!= NULL
)
110 server_client_clear_overlay(c
);
112 tv
.tv_sec
= delay
/ 1000;
113 tv
.tv_usec
= (delay
% 1000) * 1000L;
115 if (event_initialized(&c
->overlay_timer
))
116 evtimer_del(&c
->overlay_timer
);
117 evtimer_set(&c
->overlay_timer
, server_client_overlay_timer
, c
);
119 evtimer_add(&c
->overlay_timer
, &tv
);
121 c
->overlay_check
= checkcb
;
122 c
->overlay_mode
= modecb
;
123 c
->overlay_draw
= drawcb
;
124 c
->overlay_key
= keycb
;
125 c
->overlay_free
= freecb
;
126 c
->overlay_resize
= resizecb
;
127 c
->overlay_data
= data
;
129 if (c
->overlay_check
== NULL
)
130 c
->tty
.flags
|= TTY_FREEZE
;
131 if (c
->overlay_mode
== NULL
)
132 c
->tty
.flags
|= TTY_NOCURSOR
;
133 window_update_focus(c
->session
->curw
->window
);
134 server_redraw_client(c
);
137 /* Clear overlay mode on client. */
139 server_client_clear_overlay(struct client
*c
)
141 if (c
->overlay_draw
== NULL
)
144 if (event_initialized(&c
->overlay_timer
))
145 evtimer_del(&c
->overlay_timer
);
147 if (c
->overlay_free
!= NULL
)
148 c
->overlay_free(c
, c
->overlay_data
);
150 c
->overlay_check
= NULL
;
151 c
->overlay_mode
= NULL
;
152 c
->overlay_draw
= NULL
;
153 c
->overlay_key
= NULL
;
154 c
->overlay_free
= NULL
;
155 c
->overlay_data
= NULL
;
157 c
->tty
.flags
&= ~(TTY_FREEZE
|TTY_NOCURSOR
);
158 window_update_focus(c
->session
->curw
->window
);
159 server_redraw_client(c
);
163 * Given overlay position and dimensions, return parts of the input range which
167 server_client_overlay_range(u_int x
, u_int y
, u_int sx
, u_int sy
, u_int px
,
168 u_int py
, u_int nx
, struct overlay_ranges
*r
)
172 /* Return up to 2 ranges. */
176 /* Trivial case of no overlap in the y direction. */
177 if (py
< y
|| py
> y
+ sy
- 1) {
185 /* Visible bit to the left of the popup. */
196 /* Visible bit to the right of the popup. */
210 /* Check if this client is inside this server. */
212 server_client_check_nested(struct client
*c
)
214 struct environ_entry
*envent
;
215 struct window_pane
*wp
;
217 envent
= environ_find(c
->environ
, "TMUX");
218 if (envent
== NULL
|| *envent
->value
== '\0')
221 RB_FOREACH(wp
, window_pane_tree
, &all_window_panes
) {
222 if (strcmp(wp
->tty
, c
->ttyname
) == 0)
228 /* Set client key table. */
230 server_client_set_key_table(struct client
*c
, const char *name
)
233 name
= server_client_get_key_table(c
);
235 key_bindings_unref_table(c
->keytable
);
236 c
->keytable
= key_bindings_get_table(name
, 1);
237 c
->keytable
->references
++;
238 if (gettimeofday(&c
->keytable
->activity_time
, NULL
) != 0)
239 fatal("gettimeofday failed");
243 server_client_key_table_activity_diff(struct client
*c
)
247 timersub(&c
->activity_time
, &c
->keytable
->activity_time
, &diff
);
248 return ((diff
.tv_sec
* 1000ULL) + (diff
.tv_usec
/ 1000ULL));
251 /* Get default key table. */
253 server_client_get_key_table(struct client
*c
)
255 struct session
*s
= c
->session
;
261 name
= options_get_string(s
->options
, "key-table");
267 /* Is this table the default key table? */
269 server_client_is_default_key_table(struct client
*c
, struct key_table
*table
)
271 return (strcmp(table
->name
, server_client_get_key_table(c
)) == 0);
274 /* Create a new client. */
276 server_client_create(int fd
)
282 c
= xcalloc(1, sizeof *c
);
284 c
->peer
= proc_add_peer(server_proc
, fd
, server_client_dispatch
, c
);
286 if (gettimeofday(&c
->creation_time
, NULL
) != 0)
287 fatal("gettimeofday failed");
288 memcpy(&c
->activity_time
, &c
->creation_time
, sizeof c
->activity_time
);
290 c
->environ
= environ_create();
295 c
->queue
= cmdq_new();
296 RB_INIT(&c
->windows
);
303 c
->flags
|= CLIENT_FOCUSED
;
305 c
->keytable
= key_bindings_get_table("root", 1);
306 c
->keytable
->references
++;
308 evtimer_set(&c
->repeat_timer
, server_client_repeat_timer
, c
);
309 evtimer_set(&c
->click_timer
, server_client_click_timer
, c
);
311 TAILQ_INSERT_TAIL(&clients
, c
, entry
);
312 log_debug("new client %p", c
);
316 /* Open client terminal if needed. */
318 server_client_open(struct client
*c
, char **cause
)
320 const char *ttynam
= _PATH_TTY
;
322 if (c
->flags
& CLIENT_CONTROL
)
325 if (strcmp(c
->ttyname
, ttynam
) == 0||
326 ((isatty(STDIN_FILENO
) &&
327 (ttynam
= ttyname(STDIN_FILENO
)) != NULL
&&
328 strcmp(c
->ttyname
, ttynam
) == 0) ||
329 (isatty(STDOUT_FILENO
) &&
330 (ttynam
= ttyname(STDOUT_FILENO
)) != NULL
&&
331 strcmp(c
->ttyname
, ttynam
) == 0) ||
332 (isatty(STDERR_FILENO
) &&
333 (ttynam
= ttyname(STDERR_FILENO
)) != NULL
&&
334 strcmp(c
->ttyname
, ttynam
) == 0))) {
335 xasprintf(cause
, "can't use %s", c
->ttyname
);
339 if (!(c
->flags
& CLIENT_TERMINAL
)) {
340 *cause
= xstrdup("not a terminal");
344 if (tty_open(&c
->tty
, cause
) != 0)
350 /* Lost an attached client. */
352 server_client_attached_lost(struct client
*c
)
357 struct client
*found
;
359 log_debug("lost attached client %p", c
);
362 * By this point the session in the client has been cleared so walk all
363 * windows to find any with this client as the latest.
365 RB_FOREACH(w
, windows
, &windows
) {
370 TAILQ_FOREACH(loop
, &clients
, entry
) {
372 if (loop
== c
|| s
== NULL
|| s
->curw
->window
!= w
)
374 if (found
== NULL
|| timercmp(&loop
->activity_time
,
375 &found
->activity_time
, >))
379 server_client_update_latest(found
);
383 /* Set client session. */
385 server_client_set_session(struct client
*c
, struct session
*s
)
387 struct session
*old
= c
->session
;
389 if (s
!= NULL
&& c
->session
!= NULL
&& c
->session
!= s
)
390 c
->last_session
= c
->session
;
392 c
->last_session
= NULL
;
394 c
->flags
|= CLIENT_FOCUSED
;
396 if (old
!= NULL
&& old
->curw
!= NULL
)
397 window_update_focus(old
->curw
->window
);
400 window_update_focus(s
->curw
->window
);
401 session_update_activity(s
, NULL
);
402 gettimeofday(&s
->last_attached_time
, NULL
);
403 s
->curw
->flags
&= ~WINLINK_ALERTFLAGS
;
404 s
->curw
->window
->latest
= c
;
405 alerts_check_session(s
);
406 tty_update_client_offset(c
);
407 status_timer_start(c
);
408 notify_client("client-session-changed", c
);
409 server_redraw_client(c
);
412 server_check_unattached();
413 server_update_socket();
418 server_client_lost(struct client
*c
)
420 struct client_file
*cf
, *cf1
;
421 struct client_window
*cw
, *cw1
;
423 c
->flags
|= CLIENT_DEAD
;
425 server_client_clear_overlay(c
);
426 status_prompt_clear(c
);
427 status_message_clear(c
);
429 RB_FOREACH_SAFE(cf
, client_files
, &c
->files
, cf1
) {
433 RB_FOREACH_SAFE(cw
, client_windows
, &c
->windows
, cw1
) {
434 RB_REMOVE(client_windows
, &c
->windows
, cw
);
438 TAILQ_REMOVE(&clients
, c
, entry
);
439 log_debug("lost client %p", c
);
441 if (c
->flags
& CLIENT_ATTACHED
) {
442 server_client_attached_lost(c
);
443 notify_client("client-detached", c
);
446 if (c
->flags
& CLIENT_CONTROL
)
448 if (c
->flags
& CLIENT_TERMINAL
)
451 free(c
->clipboard_panes
);
455 tty_term_free_list(c
->term_caps
, c
->term_ncaps
);
460 free((void *)c
->cwd
);
462 evtimer_del(&c
->repeat_timer
);
463 evtimer_del(&c
->click_timer
);
465 key_bindings_unref_table(c
->keytable
);
467 free(c
->message_string
);
468 if (event_initialized(&c
->message_timer
))
469 evtimer_del(&c
->message_timer
);
471 free(c
->prompt_saved
);
472 free(c
->prompt_string
);
473 free(c
->prompt_buffer
);
475 format_lost_client(c
);
476 environ_free(c
->environ
);
478 proc_remove_peer(c
->peer
);
487 server_client_unref(c
);
489 server_add_accept(0); /* may be more file descriptors now */
492 server_check_unattached();
493 server_update_socket();
496 /* Remove reference from a client. */
498 server_client_unref(struct client
*c
)
500 log_debug("unref client %p (%d references)", c
, c
->references
);
503 if (c
->references
== 0)
504 event_once(-1, EV_TIMEOUT
, server_client_free
, c
, NULL
);
507 /* Free dead client. */
509 server_client_free(__unused
int fd
, __unused
short events
, void *arg
)
511 struct client
*c
= arg
;
513 log_debug("free client %p (%d references)", c
, c
->references
);
517 if (c
->references
== 0) {
518 free((void *)c
->name
);
523 /* Suspend a client. */
525 server_client_suspend(struct client
*c
)
527 struct session
*s
= c
->session
;
529 if (s
== NULL
|| (c
->flags
& CLIENT_UNATTACHEDFLAGS
))
532 tty_stop_tty(&c
->tty
);
533 c
->flags
|= CLIENT_SUSPENDED
;
534 proc_send(c
->peer
, MSG_SUSPEND
, -1, NULL
, 0);
537 /* Detach a client. */
539 server_client_detach(struct client
*c
, enum msgtype msgtype
)
541 struct session
*s
= c
->session
;
543 if (s
== NULL
|| (c
->flags
& CLIENT_NODETACHFLAGS
))
546 c
->flags
|= CLIENT_EXIT
;
548 c
->exit_type
= CLIENT_EXIT_DETACH
;
549 c
->exit_msgtype
= msgtype
;
550 c
->exit_session
= xstrdup(s
->name
);
553 /* Execute command to replace a client. */
555 server_client_exec(struct client
*c
, const char *cmd
)
557 struct session
*s
= c
->session
;
560 size_t cmdsize
, shellsize
;
564 cmdsize
= strlen(cmd
) + 1;
567 shell
= options_get_string(s
->options
, "default-shell");
569 shell
= options_get_string(global_s_options
, "default-shell");
570 if (!checkshell(shell
))
571 shell
= _PATH_BSHELL
;
572 shellsize
= strlen(shell
) + 1;
574 msg
= xmalloc(cmdsize
+ shellsize
);
575 memcpy(msg
, cmd
, cmdsize
);
576 memcpy(msg
+ cmdsize
, shell
, shellsize
);
578 proc_send(c
->peer
, MSG_EXEC
, -1, msg
, cmdsize
+ shellsize
);
582 static enum mouse_where
583 server_client_check_mouse_in_pane(struct window_pane
*wp
, u_int px
, u_int py
,
586 struct window
*w
= wp
->window
;
587 struct options
*wo
= w
->options
;
588 struct window_pane
*fwp
;
589 int pane_status
, sb
, sb_pos
, sb_w
, sb_pad
;
590 u_int line
, sl_top
, sl_bottom
;
592 sb
= options_get_number(wo
, "pane-scrollbars");
593 sb_pos
= options_get_number(wo
, "pane-scrollbars-position");
594 pane_status
= options_get_number(wo
, "pane-border-status");
595 sb_pos
= options_get_number(wo
, "pane-scrollbars-position");
597 if (window_pane_show_scrollbar(wp
, sb
)) {
598 sb_w
= wp
->scrollbar_style
.width
;
599 sb_pad
= wp
->scrollbar_style
.pad
;
604 if (pane_status
== PANE_STATUS_TOP
)
606 else if (pane_status
== PANE_STATUS_BOTTOM
)
607 line
= wp
->yoff
+ wp
->sy
;
609 /* Check if point is within the pane or scrollbar. */
610 if (((pane_status
!= PANE_STATUS_OFF
&& py
!= line
) ||
611 (wp
->yoff
== 0 && py
< wp
->sy
) ||
612 (py
>= wp
->yoff
&& py
< wp
->yoff
+ wp
->sy
)) &&
613 ((sb_pos
== PANE_SCROLLBARS_RIGHT
&&
614 px
< wp
->xoff
+ wp
->sx
+ sb_pad
+ sb_w
) ||
615 (sb_pos
== PANE_SCROLLBARS_LEFT
&&
616 px
< wp
->xoff
+ wp
->sx
- sb_pad
- sb_w
))) {
617 /* Check if in the scrollbar. */
618 if ((sb_pos
== PANE_SCROLLBARS_RIGHT
&&
619 (px
>= wp
->xoff
+ wp
->sx
+ sb_pad
&&
620 px
< wp
->xoff
+ wp
->sx
+ sb_pad
+ sb_w
)) ||
621 (sb_pos
== PANE_SCROLLBARS_LEFT
&&
622 (px
>= wp
->xoff
- sb_pad
- sb_w
&&
623 px
< wp
->xoff
- sb_pad
))) {
624 /* Check where inside the scrollbar. */
625 sl_top
= wp
->yoff
+ wp
->sb_slider_y
;
626 sl_bottom
= (wp
->yoff
+ wp
->sb_slider_y
+
627 wp
->sb_slider_h
- 1);
629 return (SCROLLBAR_UP
);
630 else if (py
>= sl_top
&&
632 *sl_mpos
= (py
- wp
->sb_slider_y
- wp
->yoff
);
633 return (SCROLLBAR_SLIDER
);
634 } else /* py > sl_bottom */
635 return (SCROLLBAR_DOWN
);
637 /* Must be inside the pane. */
640 } else if (~w
->flags
& WINDOW_ZOOMED
) {
641 /* Try the pane borders if not zoomed. */
642 TAILQ_FOREACH(fwp
, &w
->panes
, entry
) {
643 if ((((sb_pos
== PANE_SCROLLBARS_RIGHT
&&
644 fwp
->xoff
+ fwp
->sx
+ sb_pad
+ sb_w
== px
) ||
645 (sb_pos
== PANE_SCROLLBARS_LEFT
&&
646 fwp
->xoff
+ fwp
->sx
== px
)) &&
647 fwp
->yoff
<= 1 + py
&&
648 fwp
->yoff
+ fwp
->sy
>= py
) ||
649 (fwp
->yoff
+ fwp
->sy
== py
&&
650 fwp
->xoff
<= 1 + px
&&
651 fwp
->xoff
+ fwp
->sx
>= px
))
662 /* Check for mouse keys. */
664 server_client_check_mouse(struct client
*c
, struct key_event
*event
)
666 struct mouse_event
*m
= &event
->m
;
667 struct session
*s
= c
->session
, *fs
;
668 struct window
*w
= s
->curw
->window
;
670 struct window_pane
*wp
, *fwp
;
671 u_int x
, y
, b
, sx
, sy
, px
, py
, sl_mpos
= 0;
675 struct style_range
*sr
;
684 TRIPLE
} type
= NOTYPE
;
685 enum mouse_where where
= NOWHERE
;
687 log_debug("%s mouse %02x at %u,%u (last %u,%u) (%d)", c
->name
, m
->b
,
688 m
->x
, m
->y
, m
->lx
, m
->ly
, c
->tty
.mouse_drag_flag
);
690 /* What type of event is this? */
691 if (event
->key
== KEYC_DOUBLECLICK
) {
693 x
= m
->x
, y
= m
->y
, b
= m
->b
;
695 log_debug("double-click at %u,%u", x
, y
);
696 } else if ((m
->sgr_type
!= ' ' &&
697 MOUSE_DRAG(m
->sgr_b
) &&
698 MOUSE_RELEASE(m
->sgr_b
)) ||
699 (m
->sgr_type
== ' ' &&
701 MOUSE_RELEASE(m
->b
) &&
702 MOUSE_RELEASE(m
->lb
))) {
704 x
= m
->x
, y
= m
->y
, b
= 0;
705 log_debug("move at %u,%u", x
, y
);
706 } else if (MOUSE_DRAG(m
->b
)) {
708 if (c
->tty
.mouse_drag_flag
) {
709 x
= m
->x
, y
= m
->y
, b
= m
->b
;
710 if (x
== m
->lx
&& y
== m
->ly
)
711 return (KEYC_UNKNOWN
);
712 log_debug("drag update at %u,%u", x
, y
);
714 x
= m
->lx
, y
= m
->ly
, b
= m
->lb
;
715 log_debug("drag start at %u,%u", x
, y
);
717 } else if (MOUSE_WHEEL(m
->b
)) {
719 x
= m
->x
, y
= m
->y
, b
= m
->b
;
720 log_debug("wheel at %u,%u", x
, y
);
721 } else if (MOUSE_RELEASE(m
->b
)) {
723 x
= m
->x
, y
= m
->y
, b
= m
->lb
;
724 if (m
->sgr_type
== 'm')
726 log_debug("up at %u,%u", x
, y
);
728 if (c
->flags
& CLIENT_DOUBLECLICK
) {
729 evtimer_del(&c
->click_timer
);
730 c
->flags
&= ~CLIENT_DOUBLECLICK
;
731 if (m
->b
== c
->click_button
) {
733 x
= m
->x
, y
= m
->y
, b
= m
->b
;
734 log_debug("second-click at %u,%u", x
, y
);
735 c
->flags
|= CLIENT_TRIPLECLICK
;
737 } else if (c
->flags
& CLIENT_TRIPLECLICK
) {
738 evtimer_del(&c
->click_timer
);
739 c
->flags
&= ~CLIENT_TRIPLECLICK
;
740 if (m
->b
== c
->click_button
) {
742 x
= m
->x
, y
= m
->y
, b
= m
->b
;
743 log_debug("triple-click at %u,%u", x
, y
);
748 /* DOWN is the only remaining event type. */
749 if (type
== NOTYPE
) {
751 x
= m
->x
, y
= m
->y
, b
= m
->b
;
752 log_debug("down at %u,%u", x
, y
);
753 c
->flags
|= CLIENT_DOUBLECLICK
;
756 if (KEYC_CLICK_TIMEOUT
!= 0) {
757 memcpy(&c
->click_event
, m
, sizeof c
->click_event
);
758 c
->click_button
= m
->b
;
760 log_debug("click timer started");
761 tv
.tv_sec
= KEYC_CLICK_TIMEOUT
/ 1000;
762 tv
.tv_usec
= (KEYC_CLICK_TIMEOUT
% 1000) * 1000L;
763 evtimer_del(&c
->click_timer
);
764 evtimer_add(&c
->click_timer
, &tv
);
770 return (KEYC_UNKNOWN
);
772 /* Save the session. */
778 /* Is this on the status line? */
779 m
->statusat
= status_at_line(c
);
780 m
->statuslines
= status_line_size(c
);
781 if (m
->statusat
!= -1 &&
782 y
>= (u_int
)m
->statusat
&&
783 y
< m
->statusat
+ m
->statuslines
) {
784 sr
= status_get_range(c
, x
, y
- m
->statusat
);
786 where
= STATUS_DEFAULT
;
789 case STYLE_RANGE_NONE
:
790 return (KEYC_UNKNOWN
);
791 case STYLE_RANGE_LEFT
:
792 log_debug("mouse range: left");
795 case STYLE_RANGE_RIGHT
:
796 log_debug("mouse range: right");
797 where
= STATUS_RIGHT
;
799 case STYLE_RANGE_PANE
:
800 fwp
= window_pane_find_by_id(sr
->argument
);
802 return (KEYC_UNKNOWN
);
803 m
->wp
= sr
->argument
;
805 log_debug("mouse range: pane %%%u", m
->wp
);
808 case STYLE_RANGE_WINDOW
:
809 fwl
= winlink_find_by_index(&s
->windows
,
812 return (KEYC_UNKNOWN
);
813 m
->w
= fwl
->window
->id
;
815 log_debug("mouse range: window @%u", m
->w
);
818 case STYLE_RANGE_SESSION
:
819 fs
= session_find_by_id(sr
->argument
);
821 return (KEYC_UNKNOWN
);
824 log_debug("mouse range: session $%u", m
->s
);
827 case STYLE_RANGE_USER
:
835 * Not on status line. Adjust position and check for border, pane, or
838 if (where
== NOWHERE
) {
839 if (c
->tty
.mouse_scrolling_flag
)
840 where
= SCROLLBAR_SLIDER
;
843 if (m
->statusat
== 0 && y
>= m
->statuslines
)
844 py
= y
- m
->statuslines
;
845 else if (m
->statusat
> 0 && y
>= (u_int
)m
->statusat
)
846 py
= m
->statusat
- 1;
850 tty_window_offset(&c
->tty
, &m
->ox
, &m
->oy
, &sx
, &sy
);
851 log_debug("mouse window @%u at %u,%u (%ux%u)",
852 w
->id
, m
->ox
, m
->oy
, sx
, sy
);
853 if (px
> sx
|| py
> sy
)
854 return (KEYC_UNKNOWN
);
858 /* Try inside the pane. */
859 wp
= window_get_active_at(w
, px
, py
);
861 return (KEYC_UNKNOWN
);
862 where
= server_client_check_mouse_in_pane(wp
, px
, py
,
866 log_debug("mouse %u,%u on pane %%%u", x
, y
,
868 } else if (where
== BORDER
)
869 log_debug("mouse on pane %%%u border", wp
->id
);
870 else if (where
== SCROLLBAR_UP
||
871 where
== SCROLLBAR_SLIDER
||
872 where
== SCROLLBAR_DOWN
) {
873 log_debug("mouse on pane %%%u scrollbar",
877 m
->w
= wp
->window
->id
;
882 /* Stop dragging if needed. */
883 if (type
!= DRAG
&& type
!= WHEEL
&& c
->tty
.mouse_drag_flag
!= 0) {
884 if (c
->tty
.mouse_drag_release
!= NULL
)
885 c
->tty
.mouse_drag_release(c
, m
);
887 c
->tty
.mouse_drag_update
= NULL
;
888 c
->tty
.mouse_drag_release
= NULL
;
889 c
->tty
.mouse_scrolling_flag
= 0;
892 * End a mouse drag by passing a MouseDragEnd key corresponding
893 * to the button that started the drag.
895 switch (c
->tty
.mouse_drag_flag
- 1) {
898 key
= KEYC_MOUSEDRAGEND1_PANE
;
900 key
= KEYC_MOUSEDRAGEND1_STATUS
;
901 if (where
== STATUS_LEFT
)
902 key
= KEYC_MOUSEDRAGEND1_STATUS_LEFT
;
903 if (where
== STATUS_RIGHT
)
904 key
= KEYC_MOUSEDRAGEND1_STATUS_RIGHT
;
905 if (where
== STATUS_DEFAULT
)
906 key
= KEYC_MOUSEDRAGEND1_STATUS_DEFAULT
;
907 if (where
== SCROLLBAR_SLIDER
)
908 key
= KEYC_MOUSEDRAGEND1_SCROLLBAR_SLIDER
;
910 key
= KEYC_MOUSEDRAGEND1_BORDER
;
914 key
= KEYC_MOUSEDRAGEND2_PANE
;
916 key
= KEYC_MOUSEDRAGEND2_STATUS
;
917 if (where
== STATUS_LEFT
)
918 key
= KEYC_MOUSEDRAGEND2_STATUS_LEFT
;
919 if (where
== STATUS_RIGHT
)
920 key
= KEYC_MOUSEDRAGEND2_STATUS_RIGHT
;
921 if (where
== STATUS_DEFAULT
)
922 key
= KEYC_MOUSEDRAGEND2_STATUS_DEFAULT
;
923 if (where
== SCROLLBAR_SLIDER
)
924 key
= KEYC_MOUSEDRAGEND2_SCROLLBAR_SLIDER
;
926 key
= KEYC_MOUSEDRAGEND2_BORDER
;
930 key
= KEYC_MOUSEDRAGEND3_PANE
;
932 key
= KEYC_MOUSEDRAGEND3_STATUS
;
933 if (where
== STATUS_LEFT
)
934 key
= KEYC_MOUSEDRAGEND3_STATUS_LEFT
;
935 if (where
== STATUS_RIGHT
)
936 key
= KEYC_MOUSEDRAGEND3_STATUS_RIGHT
;
937 if (where
== STATUS_DEFAULT
)
938 key
= KEYC_MOUSEDRAGEND3_STATUS_DEFAULT
;
939 if (where
== SCROLLBAR_SLIDER
)
940 key
= KEYC_MOUSEDRAGEND3_SCROLLBAR_SLIDER
;
942 key
= KEYC_MOUSEDRAGEND3_BORDER
;
946 key
= KEYC_MOUSEDRAGEND6_PANE
;
948 key
= KEYC_MOUSEDRAGEND6_STATUS
;
949 if (where
== STATUS_LEFT
)
950 key
= KEYC_MOUSEDRAGEND6_STATUS_LEFT
;
951 if (where
== STATUS_RIGHT
)
952 key
= KEYC_MOUSEDRAGEND6_STATUS_RIGHT
;
953 if (where
== STATUS_DEFAULT
)
954 key
= KEYC_MOUSEDRAGEND6_STATUS_DEFAULT
;
955 if (where
== SCROLLBAR_SLIDER
)
956 key
= KEYC_MOUSEDRAGEND6_SCROLLBAR_SLIDER
;
958 key
= KEYC_MOUSEDRAGEND6_BORDER
;
962 key
= KEYC_MOUSEDRAGEND7_PANE
;
964 key
= KEYC_MOUSEDRAGEND7_STATUS
;
965 if (where
== STATUS_LEFT
)
966 key
= KEYC_MOUSEDRAGEND7_STATUS_LEFT
;
967 if (where
== STATUS_RIGHT
)
968 key
= KEYC_MOUSEDRAGEND7_STATUS_RIGHT
;
969 if (where
== STATUS_DEFAULT
)
970 key
= KEYC_MOUSEDRAGEND7_STATUS_DEFAULT
;
971 if (where
== SCROLLBAR_SLIDER
)
972 key
= KEYC_MOUSEDRAGEND7_SCROLLBAR_SLIDER
;
974 key
= KEYC_MOUSEDRAGEND7_BORDER
;
978 key
= KEYC_MOUSEDRAGEND8_PANE
;
980 key
= KEYC_MOUSEDRAGEND8_STATUS
;
981 if (where
== STATUS_LEFT
)
982 key
= KEYC_MOUSEDRAGEND8_STATUS_LEFT
;
983 if (where
== STATUS_RIGHT
)
984 key
= KEYC_MOUSEDRAGEND8_STATUS_RIGHT
;
985 if (where
== STATUS_DEFAULT
)
986 key
= KEYC_MOUSEDRAGEND8_STATUS_DEFAULT
;
987 if (where
== SCROLLBAR_SLIDER
)
988 key
= KEYC_MOUSEDRAGEND8_SCROLLBAR_SLIDER
;
990 key
= KEYC_MOUSEDRAGEND8_BORDER
;
994 key
= KEYC_MOUSEDRAGEND9_PANE
;
996 key
= KEYC_MOUSEDRAGEND9_STATUS
;
997 if (where
== STATUS_LEFT
)
998 key
= KEYC_MOUSEDRAGEND9_STATUS_LEFT
;
999 if (where
== STATUS_RIGHT
)
1000 key
= KEYC_MOUSEDRAGEND9_STATUS_RIGHT
;
1001 if (where
== STATUS_DEFAULT
)
1002 key
= KEYC_MOUSEDRAGEND9_STATUS_DEFAULT
;
1003 if (where
== SCROLLBAR_SLIDER
)
1004 key
= KEYC_MOUSEDRAGEND9_SCROLLBAR_SLIDER
;
1005 if (where
== BORDER
)
1006 key
= KEYC_MOUSEDRAGEND9_BORDER
;
1008 case MOUSE_BUTTON_10
:
1010 key
= KEYC_MOUSEDRAGEND10_PANE
;
1011 if (where
== STATUS
)
1012 key
= KEYC_MOUSEDRAGEND10_STATUS
;
1013 if (where
== STATUS_LEFT
)
1014 key
= KEYC_MOUSEDRAGEND10_STATUS_LEFT
;
1015 if (where
== STATUS_RIGHT
)
1016 key
= KEYC_MOUSEDRAGEND10_STATUS_RIGHT
;
1017 if (where
== STATUS_DEFAULT
)
1018 key
= KEYC_MOUSEDRAGEND10_STATUS_DEFAULT
;
1019 if (where
== SCROLLBAR_SLIDER
)
1020 key
= KEYC_MOUSEDRAGEND10_SCROLLBAR_SLIDER
;
1021 if (where
== BORDER
)
1022 key
= KEYC_MOUSEDRAGEND10_BORDER
;
1024 case MOUSE_BUTTON_11
:
1026 key
= KEYC_MOUSEDRAGEND11_PANE
;
1027 if (where
== STATUS
)
1028 key
= KEYC_MOUSEDRAGEND11_STATUS
;
1029 if (where
== STATUS_LEFT
)
1030 key
= KEYC_MOUSEDRAGEND11_STATUS_LEFT
;
1031 if (where
== STATUS_RIGHT
)
1032 key
= KEYC_MOUSEDRAGEND11_STATUS_RIGHT
;
1033 if (where
== STATUS_DEFAULT
)
1034 key
= KEYC_MOUSEDRAGEND11_STATUS_DEFAULT
;
1035 if (where
== SCROLLBAR_SLIDER
)
1036 key
= KEYC_MOUSEDRAGEND11_SCROLLBAR_SLIDER
;
1037 if (where
== BORDER
)
1038 key
= KEYC_MOUSEDRAGEND11_BORDER
;
1044 c
->tty
.mouse_drag_flag
= 0;
1045 c
->tty
.mouse_slider_mpos
= -1;
1049 /* Convert to a key binding. */
1056 key
= KEYC_MOUSEMOVE_PANE
;
1057 if (where
== STATUS
)
1058 key
= KEYC_MOUSEMOVE_STATUS
;
1059 if (where
== STATUS_LEFT
)
1060 key
= KEYC_MOUSEMOVE_STATUS_LEFT
;
1061 if (where
== STATUS_RIGHT
)
1062 key
= KEYC_MOUSEMOVE_STATUS_RIGHT
;
1063 if (where
== STATUS_DEFAULT
)
1064 key
= KEYC_MOUSEMOVE_STATUS_DEFAULT
;
1065 if (where
== BORDER
)
1066 key
= KEYC_MOUSEMOVE_BORDER
;
1069 if (c
->tty
.mouse_drag_update
!= NULL
)
1070 key
= KEYC_DRAGGING
;
1072 switch (MOUSE_BUTTONS(b
)) {
1073 case MOUSE_BUTTON_1
:
1075 key
= KEYC_MOUSEDRAG1_PANE
;
1076 if (where
== STATUS
)
1077 key
= KEYC_MOUSEDRAG1_STATUS
;
1078 if (where
== STATUS_LEFT
)
1079 key
= KEYC_MOUSEDRAG1_STATUS_LEFT
;
1080 if (where
== STATUS_RIGHT
)
1081 key
= KEYC_MOUSEDRAG1_STATUS_RIGHT
;
1082 if (where
== STATUS_DEFAULT
)
1083 key
= KEYC_MOUSEDRAG1_STATUS_DEFAULT
;
1084 if (where
== SCROLLBAR_UP
)
1085 key
= KEYC_MOUSEDRAG1_SCROLLBAR_UP
;
1086 if (where
== SCROLLBAR_SLIDER
)
1087 key
= KEYC_MOUSEDRAG1_SCROLLBAR_SLIDER
;
1088 if (where
== SCROLLBAR_DOWN
)
1089 key
= KEYC_MOUSEDRAG1_SCROLLBAR_DOWN
;
1090 if (where
== BORDER
)
1091 key
= KEYC_MOUSEDRAG1_BORDER
;
1093 case MOUSE_BUTTON_2
:
1095 key
= KEYC_MOUSEDRAG2_PANE
;
1096 if (where
== STATUS
)
1097 key
= KEYC_MOUSEDRAG2_STATUS
;
1098 if (where
== STATUS_LEFT
)
1099 key
= KEYC_MOUSEDRAG2_STATUS_LEFT
;
1100 if (where
== STATUS_RIGHT
)
1101 key
= KEYC_MOUSEDRAG2_STATUS_RIGHT
;
1102 if (where
== STATUS_DEFAULT
)
1103 key
= KEYC_MOUSEDRAG2_STATUS_DEFAULT
;
1104 if (where
== SCROLLBAR_UP
)
1105 key
= KEYC_MOUSEDRAG2_SCROLLBAR_UP
;
1106 if (where
== SCROLLBAR_SLIDER
)
1107 key
= KEYC_MOUSEDRAG2_SCROLLBAR_SLIDER
;
1108 if (where
== SCROLLBAR_DOWN
)
1109 key
= KEYC_MOUSEDRAG2_SCROLLBAR_DOWN
;
1110 if (where
== BORDER
)
1111 key
= KEYC_MOUSEDRAG2_BORDER
;
1113 case MOUSE_BUTTON_3
:
1115 key
= KEYC_MOUSEDRAG3_PANE
;
1116 if (where
== STATUS
)
1117 key
= KEYC_MOUSEDRAG3_STATUS
;
1118 if (where
== STATUS_LEFT
)
1119 key
= KEYC_MOUSEDRAG3_STATUS_LEFT
;
1120 if (where
== STATUS_RIGHT
)
1121 key
= KEYC_MOUSEDRAG3_STATUS_RIGHT
;
1122 if (where
== STATUS_DEFAULT
)
1123 key
= KEYC_MOUSEDRAG3_STATUS_DEFAULT
;
1124 if (where
== SCROLLBAR_UP
)
1125 key
= KEYC_MOUSEDRAG3_SCROLLBAR_UP
;
1126 if (where
== SCROLLBAR_SLIDER
)
1127 key
= KEYC_MOUSEDRAG3_SCROLLBAR_SLIDER
;
1128 if (where
== SCROLLBAR_DOWN
)
1129 key
= KEYC_MOUSEDRAG3_SCROLLBAR_DOWN
;
1130 if (where
== BORDER
)
1131 key
= KEYC_MOUSEDRAG3_BORDER
;
1133 case MOUSE_BUTTON_6
:
1135 key
= KEYC_MOUSEDRAG6_PANE
;
1136 if (where
== STATUS
)
1137 key
= KEYC_MOUSEDRAG6_STATUS
;
1138 if (where
== STATUS_LEFT
)
1139 key
= KEYC_MOUSEDRAG6_STATUS_LEFT
;
1140 if (where
== STATUS_RIGHT
)
1141 key
= KEYC_MOUSEDRAG6_STATUS_RIGHT
;
1142 if (where
== STATUS_DEFAULT
)
1143 key
= KEYC_MOUSEDRAG6_STATUS_DEFAULT
;
1144 if (where
== SCROLLBAR_UP
)
1145 key
= KEYC_MOUSEDRAG6_SCROLLBAR_UP
;
1146 if (where
== SCROLLBAR_SLIDER
)
1147 key
= KEYC_MOUSEDRAG6_SCROLLBAR_SLIDER
;
1148 if (where
== SCROLLBAR_DOWN
)
1149 key
= KEYC_MOUSEDRAG6_SCROLLBAR_DOWN
;
1150 if (where
== BORDER
)
1151 key
= KEYC_MOUSEDRAG6_BORDER
;
1153 case MOUSE_BUTTON_7
:
1155 key
= KEYC_MOUSEDRAG7_PANE
;
1156 if (where
== STATUS
)
1157 key
= KEYC_MOUSEDRAG7_STATUS
;
1158 if (where
== STATUS_LEFT
)
1159 key
= KEYC_MOUSEDRAG7_STATUS_LEFT
;
1160 if (where
== STATUS_RIGHT
)
1161 key
= KEYC_MOUSEDRAG7_STATUS_RIGHT
;
1162 if (where
== STATUS_DEFAULT
)
1163 key
= KEYC_MOUSEDRAG7_STATUS_DEFAULT
;
1164 if (where
== SCROLLBAR_UP
)
1165 key
= KEYC_MOUSEDRAG7_SCROLLBAR_UP
;
1166 if (where
== SCROLLBAR_SLIDER
)
1167 key
= KEYC_MOUSEDRAG7_SCROLLBAR_SLIDER
;
1168 if (where
== SCROLLBAR_DOWN
)
1169 key
= KEYC_MOUSEDRAG7_SCROLLBAR_DOWN
;
1170 if (where
== BORDER
)
1171 key
= KEYC_MOUSEDRAG7_BORDER
;
1173 case MOUSE_BUTTON_8
:
1175 key
= KEYC_MOUSEDRAG8_PANE
;
1176 if (where
== STATUS
)
1177 key
= KEYC_MOUSEDRAG8_STATUS
;
1178 if (where
== STATUS_LEFT
)
1179 key
= KEYC_MOUSEDRAG8_STATUS_LEFT
;
1180 if (where
== STATUS_RIGHT
)
1181 key
= KEYC_MOUSEDRAG8_STATUS_RIGHT
;
1182 if (where
== STATUS_DEFAULT
)
1183 key
= KEYC_MOUSEDRAG8_STATUS_DEFAULT
;
1184 if (where
== SCROLLBAR_UP
)
1185 key
= KEYC_MOUSEDRAG8_SCROLLBAR_UP
;
1186 if (where
== SCROLLBAR_SLIDER
)
1187 key
= KEYC_MOUSEDRAG8_SCROLLBAR_SLIDER
;
1188 if (where
== SCROLLBAR_DOWN
)
1189 key
= KEYC_MOUSEDRAG8_SCROLLBAR_DOWN
;
1190 if (where
== BORDER
)
1191 key
= KEYC_MOUSEDRAG8_BORDER
;
1193 case MOUSE_BUTTON_9
:
1195 key
= KEYC_MOUSEDRAG9_PANE
;
1196 if (where
== STATUS
)
1197 key
= KEYC_MOUSEDRAG9_STATUS
;
1198 if (where
== STATUS_LEFT
)
1199 key
= KEYC_MOUSEDRAG9_STATUS_LEFT
;
1200 if (where
== STATUS_RIGHT
)
1201 key
= KEYC_MOUSEDRAG9_STATUS_RIGHT
;
1202 if (where
== STATUS_DEFAULT
)
1203 key
= KEYC_MOUSEDRAG9_STATUS_DEFAULT
;
1204 if (where
== SCROLLBAR_UP
)
1205 key
= KEYC_MOUSEDRAG9_SCROLLBAR_UP
;
1206 if (where
== SCROLLBAR_SLIDER
)
1207 key
= KEYC_MOUSEDRAG9_SCROLLBAR_SLIDER
;
1208 if (where
== SCROLLBAR_DOWN
)
1209 key
= KEYC_MOUSEDRAG9_SCROLLBAR_DOWN
;
1210 if (where
== BORDER
)
1211 key
= KEYC_MOUSEDRAG9_BORDER
;
1213 case MOUSE_BUTTON_10
:
1215 key
= KEYC_MOUSEDRAG10_PANE
;
1216 if (where
== STATUS
)
1217 key
= KEYC_MOUSEDRAG10_STATUS
;
1218 if (where
== STATUS_LEFT
)
1219 key
= KEYC_MOUSEDRAG10_STATUS_LEFT
;
1220 if (where
== STATUS_RIGHT
)
1221 key
= KEYC_MOUSEDRAG10_STATUS_RIGHT
;
1222 if (where
== STATUS_DEFAULT
)
1223 key
= KEYC_MOUSEDRAG10_STATUS_DEFAULT
;
1224 if (where
== SCROLLBAR_UP
)
1225 key
= KEYC_MOUSEDRAG10_SCROLLBAR_UP
;
1226 if (where
== SCROLLBAR_SLIDER
)
1227 key
= KEYC_MOUSEDRAG10_SCROLLBAR_SLIDER
;
1228 if (where
== SCROLLBAR_DOWN
)
1229 key
= KEYC_MOUSEDRAG10_SCROLLBAR_DOWN
;
1230 if (where
== BORDER
)
1231 key
= KEYC_MOUSEDRAG10_BORDER
;
1233 case MOUSE_BUTTON_11
:
1235 key
= KEYC_MOUSEDRAG11_PANE
;
1236 if (where
== STATUS
)
1237 key
= KEYC_MOUSEDRAG11_STATUS
;
1238 if (where
== STATUS_LEFT
)
1239 key
= KEYC_MOUSEDRAG11_STATUS_LEFT
;
1240 if (where
== STATUS_RIGHT
)
1241 key
= KEYC_MOUSEDRAG11_STATUS_RIGHT
;
1242 if (where
== STATUS_DEFAULT
)
1243 key
= KEYC_MOUSEDRAG11_STATUS_DEFAULT
;
1244 if (where
== SCROLLBAR_UP
)
1245 key
= KEYC_MOUSEDRAG11_SCROLLBAR_UP
;
1246 if (where
== SCROLLBAR_SLIDER
)
1247 key
= KEYC_MOUSEDRAG11_SCROLLBAR_SLIDER
;
1248 if (where
== SCROLLBAR_DOWN
)
1249 key
= KEYC_MOUSEDRAG11_SCROLLBAR_DOWN
;
1250 if (where
== BORDER
)
1251 key
= KEYC_MOUSEDRAG11_BORDER
;
1257 * Begin a drag by setting the flag to a non-zero value that
1258 * corresponds to the mouse button in use. If starting to drag
1259 * the scrollbar, store the relative position in the slider
1260 * where the user grabbed.
1262 c
->tty
.mouse_drag_flag
= MOUSE_BUTTONS(b
) + 1;
1263 if (c
->tty
.mouse_scrolling_flag
== 0 &&
1264 where
== SCROLLBAR_SLIDER
) {
1265 c
->tty
.mouse_scrolling_flag
= 1;
1266 c
->tty
.mouse_slider_mpos
= sl_mpos
;
1270 if (MOUSE_BUTTONS(b
) == MOUSE_WHEEL_UP
) {
1272 key
= KEYC_WHEELUP_PANE
;
1273 if (where
== STATUS
)
1274 key
= KEYC_WHEELUP_STATUS
;
1275 if (where
== STATUS_LEFT
)
1276 key
= KEYC_WHEELUP_STATUS_LEFT
;
1277 if (where
== STATUS_RIGHT
)
1278 key
= KEYC_WHEELUP_STATUS_RIGHT
;
1279 if (where
== STATUS_DEFAULT
)
1280 key
= KEYC_WHEELUP_STATUS_DEFAULT
;
1281 if (where
== BORDER
)
1282 key
= KEYC_WHEELUP_BORDER
;
1285 key
= KEYC_WHEELDOWN_PANE
;
1286 if (where
== STATUS
)
1287 key
= KEYC_WHEELDOWN_STATUS
;
1288 if (where
== STATUS_LEFT
)
1289 key
= KEYC_WHEELDOWN_STATUS_LEFT
;
1290 if (where
== STATUS_RIGHT
)
1291 key
= KEYC_WHEELDOWN_STATUS_RIGHT
;
1292 if (where
== STATUS_DEFAULT
)
1293 key
= KEYC_WHEELDOWN_STATUS_DEFAULT
;
1294 if (where
== BORDER
)
1295 key
= KEYC_WHEELDOWN_BORDER
;
1299 switch (MOUSE_BUTTONS(b
)) {
1300 case MOUSE_BUTTON_1
:
1302 key
= KEYC_MOUSEUP1_PANE
;
1303 if (where
== STATUS
)
1304 key
= KEYC_MOUSEUP1_STATUS
;
1305 if (where
== STATUS_LEFT
)
1306 key
= KEYC_MOUSEUP1_STATUS_LEFT
;
1307 if (where
== STATUS_RIGHT
)
1308 key
= KEYC_MOUSEUP1_STATUS_RIGHT
;
1309 if (where
== STATUS_DEFAULT
)
1310 key
= KEYC_MOUSEUP1_STATUS_DEFAULT
;
1311 if (where
== SCROLLBAR_UP
)
1312 key
= KEYC_MOUSEUP1_SCROLLBAR_UP
;
1313 if (where
== SCROLLBAR_SLIDER
)
1314 key
= KEYC_MOUSEUP1_SCROLLBAR_SLIDER
;
1315 if (where
== SCROLLBAR_DOWN
)
1316 key
= KEYC_MOUSEUP1_SCROLLBAR_DOWN
;
1317 if (where
== BORDER
)
1318 key
= KEYC_MOUSEUP1_BORDER
;
1320 case MOUSE_BUTTON_2
:
1322 key
= KEYC_MOUSEUP2_PANE
;
1323 if (where
== STATUS
)
1324 key
= KEYC_MOUSEUP2_STATUS
;
1325 if (where
== STATUS_LEFT
)
1326 key
= KEYC_MOUSEUP2_STATUS_LEFT
;
1327 if (where
== STATUS_RIGHT
)
1328 key
= KEYC_MOUSEUP2_STATUS_RIGHT
;
1329 if (where
== STATUS_DEFAULT
)
1330 key
= KEYC_MOUSEUP2_STATUS_DEFAULT
;
1331 if (where
== SCROLLBAR_UP
)
1332 key
= KEYC_MOUSEUP2_SCROLLBAR_UP
;
1333 if (where
== SCROLLBAR_SLIDER
)
1334 key
= KEYC_MOUSEUP2_SCROLLBAR_SLIDER
;
1335 if (where
== SCROLLBAR_DOWN
)
1336 key
= KEYC_MOUSEUP2_SCROLLBAR_DOWN
;
1337 if (where
== BORDER
)
1338 key
= KEYC_MOUSEUP2_BORDER
;
1340 case MOUSE_BUTTON_3
:
1342 key
= KEYC_MOUSEUP3_PANE
;
1343 if (where
== STATUS
)
1344 key
= KEYC_MOUSEUP3_STATUS
;
1345 if (where
== STATUS_LEFT
)
1346 key
= KEYC_MOUSEUP3_STATUS_LEFT
;
1347 if (where
== STATUS_RIGHT
)
1348 key
= KEYC_MOUSEUP3_STATUS_RIGHT
;
1349 if (where
== STATUS_DEFAULT
)
1350 key
= KEYC_MOUSEUP3_STATUS_DEFAULT
;
1351 if (where
== SCROLLBAR_UP
)
1352 key
= KEYC_MOUSEUP3_SCROLLBAR_UP
;
1353 if (where
== SCROLLBAR_SLIDER
)
1354 key
= KEYC_MOUSEUP3_SCROLLBAR_SLIDER
;
1355 if (where
== SCROLLBAR_DOWN
)
1356 key
= KEYC_MOUSEUP3_SCROLLBAR_DOWN
;
1357 if (where
== BORDER
)
1358 key
= KEYC_MOUSEUP3_BORDER
;
1360 case MOUSE_BUTTON_6
:
1362 key
= KEYC_MOUSEUP6_PANE
;
1363 if (where
== STATUS
)
1364 key
= KEYC_MOUSEUP6_STATUS
;
1365 if (where
== STATUS_LEFT
)
1366 key
= KEYC_MOUSEUP6_STATUS_LEFT
;
1367 if (where
== STATUS_RIGHT
)
1368 key
= KEYC_MOUSEUP6_STATUS_RIGHT
;
1369 if (where
== STATUS_DEFAULT
)
1370 key
= KEYC_MOUSEUP6_STATUS_DEFAULT
;
1371 if (where
== SCROLLBAR_UP
)
1372 key
= KEYC_MOUSEUP6_SCROLLBAR_UP
;
1373 if (where
== SCROLLBAR_SLIDER
)
1374 key
= KEYC_MOUSEUP6_SCROLLBAR_SLIDER
;
1375 if (where
== SCROLLBAR_DOWN
)
1376 key
= KEYC_MOUSEUP6_SCROLLBAR_DOWN
;
1377 if (where
== BORDER
)
1378 key
= KEYC_MOUSEUP6_BORDER
;
1380 case MOUSE_BUTTON_7
:
1382 key
= KEYC_MOUSEUP7_PANE
;
1383 if (where
== STATUS
)
1384 key
= KEYC_MOUSEUP7_STATUS
;
1385 if (where
== STATUS_LEFT
)
1386 key
= KEYC_MOUSEUP7_STATUS_LEFT
;
1387 if (where
== STATUS_RIGHT
)
1388 key
= KEYC_MOUSEUP7_STATUS_RIGHT
;
1389 if (where
== STATUS_DEFAULT
)
1390 key
= KEYC_MOUSEUP7_STATUS_DEFAULT
;
1391 if (where
== SCROLLBAR_UP
)
1392 key
= KEYC_MOUSEUP7_SCROLLBAR_UP
;
1393 if (where
== SCROLLBAR_SLIDER
)
1394 key
= KEYC_MOUSEUP7_SCROLLBAR_SLIDER
;
1395 if (where
== SCROLLBAR_DOWN
)
1396 key
= KEYC_MOUSEUP7_SCROLLBAR_DOWN
;
1397 if (where
== BORDER
)
1398 key
= KEYC_MOUSEUP7_BORDER
;
1400 case MOUSE_BUTTON_8
:
1402 key
= KEYC_MOUSEUP8_PANE
;
1403 if (where
== STATUS
)
1404 key
= KEYC_MOUSEUP8_STATUS
;
1405 if (where
== STATUS_LEFT
)
1406 key
= KEYC_MOUSEUP8_STATUS_LEFT
;
1407 if (where
== STATUS_RIGHT
)
1408 key
= KEYC_MOUSEUP8_STATUS_RIGHT
;
1409 if (where
== STATUS_DEFAULT
)
1410 key
= KEYC_MOUSEUP8_STATUS_DEFAULT
;
1411 if (where
== SCROLLBAR_UP
)
1412 key
= KEYC_MOUSEUP8_SCROLLBAR_UP
;
1413 if (where
== SCROLLBAR_SLIDER
)
1414 key
= KEYC_MOUSEUP8_SCROLLBAR_SLIDER
;
1415 if (where
== SCROLLBAR_DOWN
)
1416 key
= KEYC_MOUSEUP8_SCROLLBAR_DOWN
;
1417 if (where
== BORDER
)
1418 key
= KEYC_MOUSEUP8_BORDER
;
1420 case MOUSE_BUTTON_9
:
1422 key
= KEYC_MOUSEUP9_PANE
;
1423 if (where
== STATUS
)
1424 key
= KEYC_MOUSEUP9_STATUS
;
1425 if (where
== STATUS_LEFT
)
1426 key
= KEYC_MOUSEUP9_STATUS_LEFT
;
1427 if (where
== STATUS_RIGHT
)
1428 key
= KEYC_MOUSEUP9_STATUS_RIGHT
;
1429 if (where
== STATUS_DEFAULT
)
1430 key
= KEYC_MOUSEUP9_STATUS_DEFAULT
;
1431 if (where
== SCROLLBAR_UP
)
1432 key
= KEYC_MOUSEUP9_SCROLLBAR_UP
;
1433 if (where
== SCROLLBAR_SLIDER
)
1434 key
= KEYC_MOUSEUP9_SCROLLBAR_SLIDER
;
1435 if (where
== SCROLLBAR_DOWN
)
1436 key
= KEYC_MOUSEUP9_SCROLLBAR_DOWN
;
1437 if (where
== BORDER
)
1438 key
= KEYC_MOUSEUP9_BORDER
;
1440 case MOUSE_BUTTON_10
:
1442 key
= KEYC_MOUSEUP1_PANE
;
1443 if (where
== STATUS
)
1444 key
= KEYC_MOUSEUP1_STATUS
;
1445 if (where
== STATUS_LEFT
)
1446 key
= KEYC_MOUSEUP1_STATUS_LEFT
;
1447 if (where
== STATUS_RIGHT
)
1448 key
= KEYC_MOUSEUP1_STATUS_RIGHT
;
1449 if (where
== STATUS_DEFAULT
)
1450 key
= KEYC_MOUSEUP10_STATUS_DEFAULT
;
1451 if (where
== SCROLLBAR_UP
)
1452 key
= KEYC_MOUSEUP10_SCROLLBAR_UP
;
1453 if (where
== SCROLLBAR_SLIDER
)
1454 key
= KEYC_MOUSEUP10_SCROLLBAR_SLIDER
;
1455 if (where
== SCROLLBAR_DOWN
)
1456 key
= KEYC_MOUSEUP1_SCROLLBAR_DOWN
;
1457 if (where
== BORDER
)
1458 key
= KEYC_MOUSEUP1_BORDER
;
1460 case MOUSE_BUTTON_11
:
1462 key
= KEYC_MOUSEUP11_PANE
;
1463 if (where
== STATUS
)
1464 key
= KEYC_MOUSEUP11_STATUS
;
1465 if (where
== STATUS_LEFT
)
1466 key
= KEYC_MOUSEUP11_STATUS_LEFT
;
1467 if (where
== STATUS_RIGHT
)
1468 key
= KEYC_MOUSEUP11_STATUS_RIGHT
;
1469 if (where
== STATUS_DEFAULT
)
1470 key
= KEYC_MOUSEUP11_STATUS_DEFAULT
;
1471 if (where
== SCROLLBAR_UP
)
1472 key
= KEYC_MOUSEUP11_SCROLLBAR_UP
;
1473 if (where
== SCROLLBAR_SLIDER
)
1474 key
= KEYC_MOUSEUP11_SCROLLBAR_SLIDER
;
1475 if (where
== SCROLLBAR_DOWN
)
1476 key
= KEYC_MOUSEUP11_SCROLLBAR_DOWN
;
1477 if (where
== BORDER
)
1478 key
= KEYC_MOUSEUP11_BORDER
;
1483 switch (MOUSE_BUTTONS(b
)) {
1484 case MOUSE_BUTTON_1
:
1486 key
= KEYC_MOUSEDOWN1_PANE
;
1487 if (where
== STATUS
)
1488 key
= KEYC_MOUSEDOWN1_STATUS
;
1489 if (where
== STATUS_LEFT
)
1490 key
= KEYC_MOUSEDOWN1_STATUS_LEFT
;
1491 if (where
== STATUS_RIGHT
)
1492 key
= KEYC_MOUSEDOWN1_STATUS_RIGHT
;
1493 if (where
== STATUS_DEFAULT
)
1494 key
= KEYC_MOUSEDOWN1_STATUS_DEFAULT
;
1495 if (where
== SCROLLBAR_UP
)
1496 key
= KEYC_MOUSEDOWN1_SCROLLBAR_UP
;
1497 if (where
== SCROLLBAR_SLIDER
)
1498 key
= KEYC_MOUSEDOWN1_SCROLLBAR_SLIDER
;
1499 if (where
== SCROLLBAR_DOWN
)
1500 key
= KEYC_MOUSEDOWN1_SCROLLBAR_DOWN
;
1501 if (where
== BORDER
)
1502 key
= KEYC_MOUSEDOWN1_BORDER
;
1504 case MOUSE_BUTTON_2
:
1506 key
= KEYC_MOUSEDOWN2_PANE
;
1507 if (where
== STATUS
)
1508 key
= KEYC_MOUSEDOWN2_STATUS
;
1509 if (where
== STATUS_LEFT
)
1510 key
= KEYC_MOUSEDOWN2_STATUS_LEFT
;
1511 if (where
== STATUS_RIGHT
)
1512 key
= KEYC_MOUSEDOWN2_STATUS_RIGHT
;
1513 if (where
== STATUS_DEFAULT
)
1514 key
= KEYC_MOUSEDOWN2_STATUS_DEFAULT
;
1515 if (where
== SCROLLBAR_UP
)
1516 key
= KEYC_MOUSEDOWN2_SCROLLBAR_UP
;
1517 if (where
== SCROLLBAR_SLIDER
)
1518 key
= KEYC_MOUSEDOWN2_SCROLLBAR_SLIDER
;
1519 if (where
== SCROLLBAR_DOWN
)
1520 key
= KEYC_MOUSEDOWN2_SCROLLBAR_DOWN
;
1521 if (where
== BORDER
)
1522 key
= KEYC_MOUSEDOWN2_BORDER
;
1524 case MOUSE_BUTTON_3
:
1526 key
= KEYC_MOUSEDOWN3_PANE
;
1527 if (where
== STATUS
)
1528 key
= KEYC_MOUSEDOWN3_STATUS
;
1529 if (where
== STATUS_LEFT
)
1530 key
= KEYC_MOUSEDOWN3_STATUS_LEFT
;
1531 if (where
== STATUS_RIGHT
)
1532 key
= KEYC_MOUSEDOWN3_STATUS_RIGHT
;
1533 if (where
== STATUS_DEFAULT
)
1534 key
= KEYC_MOUSEDOWN3_STATUS_DEFAULT
;
1535 if (where
== SCROLLBAR_UP
)
1536 key
= KEYC_MOUSEDOWN3_SCROLLBAR_UP
;
1537 if (where
== SCROLLBAR_SLIDER
)
1538 key
= KEYC_MOUSEDOWN3_SCROLLBAR_SLIDER
;
1539 if (where
== SCROLLBAR_DOWN
)
1540 key
= KEYC_MOUSEDOWN3_SCROLLBAR_DOWN
;
1541 if (where
== BORDER
)
1542 key
= KEYC_MOUSEDOWN3_BORDER
;
1544 case MOUSE_BUTTON_6
:
1546 key
= KEYC_MOUSEDOWN6_PANE
;
1547 if (where
== STATUS
)
1548 key
= KEYC_MOUSEDOWN6_STATUS
;
1549 if (where
== STATUS_LEFT
)
1550 key
= KEYC_MOUSEDOWN6_STATUS_LEFT
;
1551 if (where
== STATUS_RIGHT
)
1552 key
= KEYC_MOUSEDOWN6_STATUS_RIGHT
;
1553 if (where
== STATUS_DEFAULT
)
1554 key
= KEYC_MOUSEDOWN6_STATUS_DEFAULT
;
1555 if (where
== SCROLLBAR_UP
)
1556 key
= KEYC_MOUSEDOWN6_SCROLLBAR_UP
;
1557 if (where
== SCROLLBAR_SLIDER
)
1558 key
= KEYC_MOUSEDOWN6_SCROLLBAR_SLIDER
;
1559 if (where
== SCROLLBAR_DOWN
)
1560 key
= KEYC_MOUSEDOWN6_SCROLLBAR_DOWN
;
1561 if (where
== BORDER
)
1562 key
= KEYC_MOUSEDOWN6_BORDER
;
1564 case MOUSE_BUTTON_7
:
1566 key
= KEYC_MOUSEDOWN7_PANE
;
1567 if (where
== STATUS
)
1568 key
= KEYC_MOUSEDOWN7_STATUS
;
1569 if (where
== STATUS_LEFT
)
1570 key
= KEYC_MOUSEDOWN7_STATUS_LEFT
;
1571 if (where
== STATUS_RIGHT
)
1572 key
= KEYC_MOUSEDOWN7_STATUS_RIGHT
;
1573 if (where
== STATUS_DEFAULT
)
1574 key
= KEYC_MOUSEDOWN7_STATUS_DEFAULT
;
1575 if (where
== SCROLLBAR_UP
)
1576 key
= KEYC_MOUSEDOWN7_SCROLLBAR_UP
;
1577 if (where
== SCROLLBAR_SLIDER
)
1578 key
= KEYC_MOUSEDOWN7_SCROLLBAR_SLIDER
;
1579 if (where
== SCROLLBAR_DOWN
)
1580 key
= KEYC_MOUSEDOWN7_SCROLLBAR_DOWN
;
1581 if (where
== BORDER
)
1582 key
= KEYC_MOUSEDOWN7_BORDER
;
1584 case MOUSE_BUTTON_8
:
1586 key
= KEYC_MOUSEDOWN8_PANE
;
1587 if (where
== STATUS
)
1588 key
= KEYC_MOUSEDOWN8_STATUS
;
1589 if (where
== STATUS_LEFT
)
1590 key
= KEYC_MOUSEDOWN8_STATUS_LEFT
;
1591 if (where
== STATUS_RIGHT
)
1592 key
= KEYC_MOUSEDOWN8_STATUS_RIGHT
;
1593 if (where
== STATUS_DEFAULT
)
1594 key
= KEYC_MOUSEDOWN8_STATUS_DEFAULT
;
1595 if (where
== SCROLLBAR_UP
)
1596 key
= KEYC_MOUSEDOWN8_SCROLLBAR_UP
;
1597 if (where
== SCROLLBAR_SLIDER
)
1598 key
= KEYC_MOUSEDOWN8_SCROLLBAR_SLIDER
;
1599 if (where
== SCROLLBAR_DOWN
)
1600 key
= KEYC_MOUSEDOWN8_SCROLLBAR_DOWN
;
1601 if (where
== BORDER
)
1602 key
= KEYC_MOUSEDOWN8_BORDER
;
1604 case MOUSE_BUTTON_9
:
1606 key
= KEYC_MOUSEDOWN9_PANE
;
1607 if (where
== STATUS
)
1608 key
= KEYC_MOUSEDOWN9_STATUS
;
1609 if (where
== STATUS_LEFT
)
1610 key
= KEYC_MOUSEDOWN9_STATUS_LEFT
;
1611 if (where
== STATUS_RIGHT
)
1612 key
= KEYC_MOUSEDOWN9_STATUS_RIGHT
;
1613 if (where
== STATUS_DEFAULT
)
1614 key
= KEYC_MOUSEDOWN9_STATUS_DEFAULT
;
1615 if (where
== SCROLLBAR_UP
)
1616 key
= KEYC_MOUSEDOWN9_SCROLLBAR_UP
;
1617 if (where
== SCROLLBAR_SLIDER
)
1618 key
= KEYC_MOUSEDOWN9_SCROLLBAR_SLIDER
;
1619 if (where
== SCROLLBAR_DOWN
)
1620 key
= KEYC_MOUSEDOWN9_SCROLLBAR_DOWN
;
1621 if (where
== BORDER
)
1622 key
= KEYC_MOUSEDOWN9_BORDER
;
1624 case MOUSE_BUTTON_10
:
1626 key
= KEYC_MOUSEDOWN10_PANE
;
1627 if (where
== STATUS
)
1628 key
= KEYC_MOUSEDOWN10_STATUS
;
1629 if (where
== STATUS_LEFT
)
1630 key
= KEYC_MOUSEDOWN10_STATUS_LEFT
;
1631 if (where
== STATUS_RIGHT
)
1632 key
= KEYC_MOUSEDOWN10_STATUS_RIGHT
;
1633 if (where
== STATUS_DEFAULT
)
1634 key
= KEYC_MOUSEDOWN10_STATUS_DEFAULT
;
1635 if (where
== SCROLLBAR_UP
)
1636 key
= KEYC_MOUSEDOWN10_SCROLLBAR_UP
;
1637 if (where
== SCROLLBAR_SLIDER
)
1638 key
= KEYC_MOUSEDOWN10_SCROLLBAR_SLIDER
;
1639 if (where
== SCROLLBAR_DOWN
)
1640 key
= KEYC_MOUSEDOWN10_SCROLLBAR_DOWN
;
1641 if (where
== BORDER
)
1642 key
= KEYC_MOUSEDOWN10_BORDER
;
1644 case MOUSE_BUTTON_11
:
1646 key
= KEYC_MOUSEDOWN11_PANE
;
1647 if (where
== STATUS
)
1648 key
= KEYC_MOUSEDOWN11_STATUS
;
1649 if (where
== STATUS_LEFT
)
1650 key
= KEYC_MOUSEDOWN11_STATUS_LEFT
;
1651 if (where
== STATUS_RIGHT
)
1652 key
= KEYC_MOUSEDOWN11_STATUS_RIGHT
;
1653 if (where
== STATUS_DEFAULT
)
1654 key
= KEYC_MOUSEDOWN11_STATUS_DEFAULT
;
1655 if (where
== SCROLLBAR_UP
)
1656 key
= KEYC_MOUSEDOWN11_SCROLLBAR_UP
;
1657 if (where
== SCROLLBAR_SLIDER
)
1658 key
= KEYC_MOUSEDOWN11_SCROLLBAR_SLIDER
;
1659 if (where
== SCROLLBAR_DOWN
)
1660 key
= KEYC_MOUSEDOWN11_SCROLLBAR_DOWN
;
1661 if (where
== BORDER
)
1662 key
= KEYC_MOUSEDOWN11_BORDER
;
1667 switch (MOUSE_BUTTONS(b
)) {
1668 case MOUSE_BUTTON_1
:
1670 key
= KEYC_SECONDCLICK1_PANE
;
1671 if (where
== STATUS
)
1672 key
= KEYC_SECONDCLICK1_STATUS
;
1673 if (where
== STATUS_LEFT
)
1674 key
= KEYC_SECONDCLICK1_STATUS_LEFT
;
1675 if (where
== STATUS_RIGHT
)
1676 key
= KEYC_SECONDCLICK1_STATUS_RIGHT
;
1677 if (where
== STATUS_DEFAULT
)
1678 key
= KEYC_SECONDCLICK1_STATUS_DEFAULT
;
1679 if (where
== SCROLLBAR_UP
)
1680 key
= KEYC_SECONDCLICK1_SCROLLBAR_UP
;
1681 if (where
== SCROLLBAR_SLIDER
)
1682 key
= KEYC_SECONDCLICK1_SCROLLBAR_SLIDER
;
1683 if (where
== SCROLLBAR_DOWN
)
1684 key
= KEYC_SECONDCLICK1_SCROLLBAR_DOWN
;
1685 if (where
== BORDER
)
1686 key
= KEYC_SECONDCLICK1_BORDER
;
1688 case MOUSE_BUTTON_2
:
1690 key
= KEYC_SECONDCLICK2_PANE
;
1691 if (where
== STATUS
)
1692 key
= KEYC_SECONDCLICK2_STATUS
;
1693 if (where
== STATUS_LEFT
)
1694 key
= KEYC_SECONDCLICK2_STATUS_LEFT
;
1695 if (where
== STATUS_RIGHT
)
1696 key
= KEYC_SECONDCLICK2_STATUS_RIGHT
;
1697 if (where
== STATUS_DEFAULT
)
1698 key
= KEYC_SECONDCLICK2_STATUS_DEFAULT
;
1699 if (where
== SCROLLBAR_UP
)
1700 key
= KEYC_SECONDCLICK2_SCROLLBAR_UP
;
1701 if (where
== SCROLLBAR_SLIDER
)
1702 key
= KEYC_SECONDCLICK2_SCROLLBAR_SLIDER
;
1703 if (where
== SCROLLBAR_DOWN
)
1704 key
= KEYC_SECONDCLICK2_SCROLLBAR_DOWN
;
1705 if (where
== BORDER
)
1706 key
= KEYC_SECONDCLICK2_BORDER
;
1708 case MOUSE_BUTTON_3
:
1710 key
= KEYC_SECONDCLICK3_PANE
;
1711 if (where
== STATUS
)
1712 key
= KEYC_SECONDCLICK3_STATUS
;
1713 if (where
== STATUS_LEFT
)
1714 key
= KEYC_SECONDCLICK3_STATUS_LEFT
;
1715 if (where
== STATUS_RIGHT
)
1716 key
= KEYC_SECONDCLICK3_STATUS_RIGHT
;
1717 if (where
== STATUS_DEFAULT
)
1718 key
= KEYC_SECONDCLICK3_STATUS_DEFAULT
;
1719 if (where
== SCROLLBAR_UP
)
1720 key
= KEYC_SECONDCLICK3_SCROLLBAR_UP
;
1721 if (where
== SCROLLBAR_SLIDER
)
1722 key
= KEYC_SECONDCLICK3_SCROLLBAR_SLIDER
;
1723 if (where
== SCROLLBAR_DOWN
)
1724 key
= KEYC_SECONDCLICK3_SCROLLBAR_DOWN
;
1725 if (where
== BORDER
)
1726 key
= KEYC_SECONDCLICK3_BORDER
;
1728 case MOUSE_BUTTON_6
:
1730 key
= KEYC_SECONDCLICK6_PANE
;
1731 if (where
== STATUS
)
1732 key
= KEYC_SECONDCLICK6_STATUS
;
1733 if (where
== STATUS_LEFT
)
1734 key
= KEYC_SECONDCLICK6_STATUS_LEFT
;
1735 if (where
== STATUS_RIGHT
)
1736 key
= KEYC_SECONDCLICK6_STATUS_RIGHT
;
1737 if (where
== STATUS_DEFAULT
)
1738 key
= KEYC_SECONDCLICK6_STATUS_DEFAULT
;
1739 if (where
== SCROLLBAR_UP
)
1740 key
= KEYC_SECONDCLICK6_SCROLLBAR_UP
;
1741 if (where
== SCROLLBAR_SLIDER
)
1742 key
= KEYC_SECONDCLICK6_SCROLLBAR_SLIDER
;
1743 if (where
== SCROLLBAR_DOWN
)
1744 key
= KEYC_SECONDCLICK6_SCROLLBAR_DOWN
;
1745 if (where
== BORDER
)
1746 key
= KEYC_SECONDCLICK6_BORDER
;
1748 case MOUSE_BUTTON_7
:
1750 key
= KEYC_SECONDCLICK7_PANE
;
1751 if (where
== STATUS
)
1752 key
= KEYC_SECONDCLICK7_STATUS
;
1753 if (where
== STATUS_LEFT
)
1754 key
= KEYC_SECONDCLICK7_STATUS_LEFT
;
1755 if (where
== STATUS_RIGHT
)
1756 key
= KEYC_SECONDCLICK7_STATUS_RIGHT
;
1757 if (where
== STATUS_DEFAULT
)
1758 key
= KEYC_SECONDCLICK7_STATUS_DEFAULT
;
1759 if (where
== SCROLLBAR_UP
)
1760 key
= KEYC_SECONDCLICK7_SCROLLBAR_UP
;
1761 if (where
== SCROLLBAR_SLIDER
)
1762 key
= KEYC_SECONDCLICK7_SCROLLBAR_SLIDER
;
1763 if (where
== SCROLLBAR_DOWN
)
1764 key
= KEYC_SECONDCLICK7_SCROLLBAR_DOWN
;
1765 if (where
== BORDER
)
1766 key
= KEYC_SECONDCLICK7_BORDER
;
1768 case MOUSE_BUTTON_8
:
1770 key
= KEYC_SECONDCLICK8_PANE
;
1771 if (where
== STATUS
)
1772 key
= KEYC_SECONDCLICK8_STATUS
;
1773 if (where
== STATUS_LEFT
)
1774 key
= KEYC_SECONDCLICK8_STATUS_LEFT
;
1775 if (where
== STATUS_RIGHT
)
1776 key
= KEYC_SECONDCLICK8_STATUS_RIGHT
;
1777 if (where
== STATUS_DEFAULT
)
1778 key
= KEYC_SECONDCLICK8_STATUS_DEFAULT
;
1779 if (where
== SCROLLBAR_UP
)
1780 key
= KEYC_SECONDCLICK8_SCROLLBAR_UP
;
1781 if (where
== SCROLLBAR_SLIDER
)
1782 key
= KEYC_SECONDCLICK8_SCROLLBAR_SLIDER
;
1783 if (where
== SCROLLBAR_DOWN
)
1784 key
= KEYC_SECONDCLICK8_SCROLLBAR_DOWN
;
1785 if (where
== BORDER
)
1786 key
= KEYC_SECONDCLICK8_BORDER
;
1788 case MOUSE_BUTTON_9
:
1790 key
= KEYC_SECONDCLICK9_PANE
;
1791 if (where
== STATUS
)
1792 key
= KEYC_SECONDCLICK9_STATUS
;
1793 if (where
== STATUS_LEFT
)
1794 key
= KEYC_SECONDCLICK9_STATUS_LEFT
;
1795 if (where
== STATUS_RIGHT
)
1796 key
= KEYC_SECONDCLICK9_STATUS_RIGHT
;
1797 if (where
== STATUS_DEFAULT
)
1798 key
= KEYC_SECONDCLICK9_STATUS_DEFAULT
;
1799 if (where
== SCROLLBAR_UP
)
1800 key
= KEYC_SECONDCLICK9_SCROLLBAR_UP
;
1801 if (where
== SCROLLBAR_SLIDER
)
1802 key
= KEYC_SECONDCLICK9_SCROLLBAR_SLIDER
;
1803 if (where
== SCROLLBAR_DOWN
)
1804 key
= KEYC_SECONDCLICK9_SCROLLBAR_DOWN
;
1805 if (where
== BORDER
)
1806 key
= KEYC_SECONDCLICK9_BORDER
;
1808 case MOUSE_BUTTON_10
:
1810 key
= KEYC_SECONDCLICK10_PANE
;
1811 if (where
== STATUS
)
1812 key
= KEYC_SECONDCLICK10_STATUS
;
1813 if (where
== STATUS_LEFT
)
1814 key
= KEYC_SECONDCLICK10_STATUS_LEFT
;
1815 if (where
== STATUS_RIGHT
)
1816 key
= KEYC_SECONDCLICK10_STATUS_RIGHT
;
1817 if (where
== STATUS_DEFAULT
)
1818 key
= KEYC_SECONDCLICK10_STATUS_DEFAULT
;
1819 if (where
== SCROLLBAR_UP
)
1820 key
= KEYC_SECONDCLICK10_SCROLLBAR_UP
;
1821 if (where
== SCROLLBAR_SLIDER
)
1822 key
= KEYC_SECONDCLICK10_SCROLLBAR_SLIDER
;
1823 if (where
== SCROLLBAR_DOWN
)
1824 key
= KEYC_SECONDCLICK10_SCROLLBAR_DOWN
;
1825 if (where
== BORDER
)
1826 key
= KEYC_SECONDCLICK10_BORDER
;
1828 case MOUSE_BUTTON_11
:
1830 key
= KEYC_SECONDCLICK11_PANE
;
1831 if (where
== STATUS
)
1832 key
= KEYC_SECONDCLICK11_STATUS
;
1833 if (where
== STATUS_LEFT
)
1834 key
= KEYC_SECONDCLICK11_STATUS_LEFT
;
1835 if (where
== STATUS_RIGHT
)
1836 key
= KEYC_SECONDCLICK11_STATUS_RIGHT
;
1837 if (where
== STATUS_DEFAULT
)
1838 key
= KEYC_SECONDCLICK11_STATUS_DEFAULT
;
1839 if (where
== SCROLLBAR_UP
)
1840 key
= KEYC_SECONDCLICK11_SCROLLBAR_UP
;
1841 if (where
== SCROLLBAR_SLIDER
)
1842 key
= KEYC_SECONDCLICK11_SCROLLBAR_SLIDER
;
1843 if (where
== SCROLLBAR_DOWN
)
1844 key
= KEYC_SECONDCLICK11_SCROLLBAR_DOWN
;
1845 if (where
== BORDER
)
1846 key
= KEYC_SECONDCLICK11_BORDER
;
1851 switch (MOUSE_BUTTONS(b
)) {
1852 case MOUSE_BUTTON_1
:
1854 key
= KEYC_DOUBLECLICK1_PANE
;
1855 if (where
== STATUS
)
1856 key
= KEYC_DOUBLECLICK1_STATUS
;
1857 if (where
== STATUS_LEFT
)
1858 key
= KEYC_DOUBLECLICK1_STATUS_LEFT
;
1859 if (where
== STATUS_RIGHT
)
1860 key
= KEYC_DOUBLECLICK1_STATUS_RIGHT
;
1861 if (where
== STATUS_DEFAULT
)
1862 key
= KEYC_DOUBLECLICK1_STATUS_DEFAULT
;
1863 if (where
== SCROLLBAR_UP
)
1864 key
= KEYC_DOUBLECLICK1_SCROLLBAR_UP
;
1865 if (where
== SCROLLBAR_SLIDER
)
1866 key
= KEYC_DOUBLECLICK1_SCROLLBAR_SLIDER
;
1867 if (where
== SCROLLBAR_DOWN
)
1868 key
= KEYC_DOUBLECLICK1_SCROLLBAR_DOWN
;
1869 if (where
== BORDER
)
1870 key
= KEYC_DOUBLECLICK1_BORDER
;
1872 case MOUSE_BUTTON_2
:
1874 key
= KEYC_DOUBLECLICK2_PANE
;
1875 if (where
== STATUS
)
1876 key
= KEYC_DOUBLECLICK2_STATUS
;
1877 if (where
== STATUS_LEFT
)
1878 key
= KEYC_DOUBLECLICK2_STATUS_LEFT
;
1879 if (where
== STATUS_RIGHT
)
1880 key
= KEYC_DOUBLECLICK2_STATUS_RIGHT
;
1881 if (where
== STATUS_DEFAULT
)
1882 key
= KEYC_DOUBLECLICK2_STATUS_DEFAULT
;
1883 if (where
== SCROLLBAR_UP
)
1884 key
= KEYC_DOUBLECLICK2_SCROLLBAR_UP
;
1885 if (where
== SCROLLBAR_SLIDER
)
1886 key
= KEYC_DOUBLECLICK2_SCROLLBAR_SLIDER
;
1887 if (where
== SCROLLBAR_DOWN
)
1888 key
= KEYC_DOUBLECLICK2_SCROLLBAR_DOWN
;
1889 if (where
== BORDER
)
1890 key
= KEYC_DOUBLECLICK2_BORDER
;
1892 case MOUSE_BUTTON_3
:
1894 key
= KEYC_DOUBLECLICK3_PANE
;
1895 if (where
== STATUS
)
1896 key
= KEYC_DOUBLECLICK3_STATUS
;
1897 if (where
== STATUS_LEFT
)
1898 key
= KEYC_DOUBLECLICK3_STATUS_LEFT
;
1899 if (where
== STATUS_RIGHT
)
1900 key
= KEYC_DOUBLECLICK3_STATUS_RIGHT
;
1901 if (where
== STATUS_DEFAULT
)
1902 key
= KEYC_DOUBLECLICK3_STATUS_DEFAULT
;
1903 if (where
== SCROLLBAR_UP
)
1904 key
= KEYC_DOUBLECLICK3_SCROLLBAR_UP
;
1905 if (where
== SCROLLBAR_SLIDER
)
1906 key
= KEYC_DOUBLECLICK3_SCROLLBAR_SLIDER
;
1907 if (where
== SCROLLBAR_DOWN
)
1908 key
= KEYC_DOUBLECLICK3_SCROLLBAR_DOWN
;
1909 if (where
== BORDER
)
1910 key
= KEYC_DOUBLECLICK3_BORDER
;
1912 case MOUSE_BUTTON_6
:
1914 key
= KEYC_DOUBLECLICK6_PANE
;
1915 if (where
== STATUS
)
1916 key
= KEYC_DOUBLECLICK6_STATUS
;
1917 if (where
== STATUS_LEFT
)
1918 key
= KEYC_DOUBLECLICK6_STATUS_LEFT
;
1919 if (where
== STATUS_RIGHT
)
1920 key
= KEYC_DOUBLECLICK6_STATUS_RIGHT
;
1921 if (where
== STATUS_DEFAULT
)
1922 key
= KEYC_DOUBLECLICK6_STATUS_DEFAULT
;
1923 if (where
== SCROLLBAR_UP
)
1924 key
= KEYC_DOUBLECLICK6_SCROLLBAR_UP
;
1925 if (where
== SCROLLBAR_SLIDER
)
1926 key
= KEYC_DOUBLECLICK6_SCROLLBAR_SLIDER
;
1927 if (where
== SCROLLBAR_DOWN
)
1928 key
= KEYC_DOUBLECLICK6_SCROLLBAR_DOWN
;
1929 if (where
== BORDER
)
1930 key
= KEYC_DOUBLECLICK6_BORDER
;
1932 case MOUSE_BUTTON_7
:
1934 key
= KEYC_DOUBLECLICK7_PANE
;
1935 if (where
== STATUS
)
1936 key
= KEYC_DOUBLECLICK7_STATUS
;
1937 if (where
== STATUS_LEFT
)
1938 key
= KEYC_DOUBLECLICK7_STATUS_LEFT
;
1939 if (where
== STATUS_RIGHT
)
1940 key
= KEYC_DOUBLECLICK7_STATUS_RIGHT
;
1941 if (where
== STATUS_DEFAULT
)
1942 key
= KEYC_DOUBLECLICK7_STATUS_DEFAULT
;
1943 if (where
== SCROLLBAR_UP
)
1944 key
= KEYC_DOUBLECLICK7_SCROLLBAR_UP
;
1945 if (where
== SCROLLBAR_SLIDER
)
1946 key
= KEYC_DOUBLECLICK7_SCROLLBAR_SLIDER
;
1947 if (where
== SCROLLBAR_DOWN
)
1948 key
= KEYC_DOUBLECLICK7_SCROLLBAR_DOWN
;
1949 if (where
== BORDER
)
1950 key
= KEYC_DOUBLECLICK7_BORDER
;
1952 case MOUSE_BUTTON_8
:
1954 key
= KEYC_DOUBLECLICK8_PANE
;
1955 if (where
== STATUS
)
1956 key
= KEYC_DOUBLECLICK8_STATUS
;
1957 if (where
== STATUS_LEFT
)
1958 key
= KEYC_DOUBLECLICK8_STATUS_LEFT
;
1959 if (where
== STATUS_RIGHT
)
1960 key
= KEYC_DOUBLECLICK8_STATUS_RIGHT
;
1961 if (where
== STATUS_DEFAULT
)
1962 key
= KEYC_DOUBLECLICK8_STATUS_DEFAULT
;
1963 if (where
== SCROLLBAR_UP
)
1964 key
= KEYC_DOUBLECLICK8_SCROLLBAR_UP
;
1965 if (where
== SCROLLBAR_SLIDER
)
1966 key
= KEYC_DOUBLECLICK8_SCROLLBAR_SLIDER
;
1967 if (where
== SCROLLBAR_DOWN
)
1968 key
= KEYC_DOUBLECLICK8_SCROLLBAR_DOWN
;
1969 if (where
== BORDER
)
1970 key
= KEYC_DOUBLECLICK8_BORDER
;
1972 case MOUSE_BUTTON_9
:
1974 key
= KEYC_DOUBLECLICK9_PANE
;
1975 if (where
== STATUS
)
1976 key
= KEYC_DOUBLECLICK9_STATUS
;
1977 if (where
== STATUS_LEFT
)
1978 key
= KEYC_DOUBLECLICK9_STATUS_LEFT
;
1979 if (where
== STATUS_RIGHT
)
1980 key
= KEYC_DOUBLECLICK9_STATUS_RIGHT
;
1981 if (where
== STATUS_DEFAULT
)
1982 key
= KEYC_DOUBLECLICK9_STATUS_DEFAULT
;
1983 if (where
== SCROLLBAR_UP
)
1984 key
= KEYC_DOUBLECLICK9_SCROLLBAR_UP
;
1985 if (where
== SCROLLBAR_SLIDER
)
1986 key
= KEYC_DOUBLECLICK9_SCROLLBAR_SLIDER
;
1987 if (where
== SCROLLBAR_DOWN
)
1988 key
= KEYC_DOUBLECLICK9_SCROLLBAR_DOWN
;
1989 if (where
== BORDER
)
1990 key
= KEYC_DOUBLECLICK9_BORDER
;
1992 case MOUSE_BUTTON_10
:
1994 key
= KEYC_DOUBLECLICK10_PANE
;
1995 if (where
== STATUS
)
1996 key
= KEYC_DOUBLECLICK10_STATUS
;
1997 if (where
== STATUS_LEFT
)
1998 key
= KEYC_DOUBLECLICK10_STATUS_LEFT
;
1999 if (where
== STATUS_RIGHT
)
2000 key
= KEYC_DOUBLECLICK10_STATUS_RIGHT
;
2001 if (where
== STATUS_DEFAULT
)
2002 key
= KEYC_DOUBLECLICK10_STATUS_DEFAULT
;
2003 if (where
== SCROLLBAR_UP
)
2004 key
= KEYC_DOUBLECLICK10_SCROLLBAR_UP
;
2005 if (where
== SCROLLBAR_SLIDER
)
2006 key
= KEYC_DOUBLECLICK10_SCROLLBAR_SLIDER
;
2007 if (where
== SCROLLBAR_DOWN
)
2008 key
= KEYC_DOUBLECLICK10_SCROLLBAR_DOWN
;
2009 if (where
== BORDER
)
2010 key
= KEYC_DOUBLECLICK10_BORDER
;
2012 case MOUSE_BUTTON_11
:
2014 key
= KEYC_DOUBLECLICK11_PANE
;
2015 if (where
== STATUS
)
2016 key
= KEYC_DOUBLECLICK11_STATUS
;
2017 if (where
== STATUS_LEFT
)
2018 key
= KEYC_DOUBLECLICK11_STATUS_LEFT
;
2019 if (where
== STATUS_RIGHT
)
2020 key
= KEYC_DOUBLECLICK11_STATUS_RIGHT
;
2021 if (where
== STATUS_DEFAULT
)
2022 key
= KEYC_DOUBLECLICK11_STATUS_DEFAULT
;
2023 if (where
== SCROLLBAR_UP
)
2024 key
= KEYC_DOUBLECLICK11_SCROLLBAR_UP
;
2025 if (where
== SCROLLBAR_SLIDER
)
2026 key
= KEYC_DOUBLECLICK11_SCROLLBAR_SLIDER
;
2027 if (where
== SCROLLBAR_DOWN
)
2028 key
= KEYC_DOUBLECLICK11_SCROLLBAR_DOWN
;
2029 if (where
== BORDER
)
2030 key
= KEYC_DOUBLECLICK11_BORDER
;
2035 switch (MOUSE_BUTTONS(b
)) {
2036 case MOUSE_BUTTON_1
:
2038 key
= KEYC_TRIPLECLICK1_PANE
;
2039 if (where
== STATUS
)
2040 key
= KEYC_TRIPLECLICK1_STATUS
;
2041 if (where
== STATUS_LEFT
)
2042 key
= KEYC_TRIPLECLICK1_STATUS_LEFT
;
2043 if (where
== STATUS_RIGHT
)
2044 key
= KEYC_TRIPLECLICK1_STATUS_RIGHT
;
2045 if (where
== STATUS_DEFAULT
)
2046 key
= KEYC_TRIPLECLICK1_STATUS_DEFAULT
;
2047 if (where
== SCROLLBAR_UP
)
2048 key
= KEYC_TRIPLECLICK1_SCROLLBAR_UP
;
2049 if (where
== SCROLLBAR_SLIDER
)
2050 key
= KEYC_TRIPLECLICK1_SCROLLBAR_SLIDER
;
2051 if (where
== SCROLLBAR_DOWN
)
2052 key
= KEYC_TRIPLECLICK1_SCROLLBAR_DOWN
;
2053 if (where
== BORDER
)
2054 key
= KEYC_TRIPLECLICK1_BORDER
;
2056 case MOUSE_BUTTON_2
:
2058 key
= KEYC_TRIPLECLICK2_PANE
;
2059 if (where
== STATUS
)
2060 key
= KEYC_TRIPLECLICK2_STATUS
;
2061 if (where
== STATUS_LEFT
)
2062 key
= KEYC_TRIPLECLICK2_STATUS_LEFT
;
2063 if (where
== STATUS_RIGHT
)
2064 key
= KEYC_TRIPLECLICK2_STATUS_RIGHT
;
2065 if (where
== STATUS_DEFAULT
)
2066 key
= KEYC_TRIPLECLICK2_STATUS_DEFAULT
;
2067 if (where
== SCROLLBAR_UP
)
2068 key
= KEYC_TRIPLECLICK2_SCROLLBAR_UP
;
2069 if (where
== SCROLLBAR_SLIDER
)
2070 key
= KEYC_TRIPLECLICK2_SCROLLBAR_SLIDER
;
2071 if (where
== SCROLLBAR_DOWN
)
2072 key
= KEYC_TRIPLECLICK2_SCROLLBAR_DOWN
;
2073 if (where
== BORDER
)
2074 key
= KEYC_TRIPLECLICK2_BORDER
;
2076 case MOUSE_BUTTON_3
:
2078 key
= KEYC_TRIPLECLICK3_PANE
;
2079 if (where
== STATUS
)
2080 key
= KEYC_TRIPLECLICK3_STATUS
;
2081 if (where
== STATUS_LEFT
)
2082 key
= KEYC_TRIPLECLICK3_STATUS_LEFT
;
2083 if (where
== STATUS_RIGHT
)
2084 key
= KEYC_TRIPLECLICK3_STATUS_RIGHT
;
2085 if (where
== STATUS_DEFAULT
)
2086 key
= KEYC_TRIPLECLICK3_STATUS_DEFAULT
;
2087 if (where
== SCROLLBAR_UP
)
2088 key
= KEYC_TRIPLECLICK3_SCROLLBAR_UP
;
2089 if (where
== SCROLLBAR_SLIDER
)
2090 key
= KEYC_TRIPLECLICK3_SCROLLBAR_SLIDER
;
2091 if (where
== SCROLLBAR_DOWN
)
2092 key
= KEYC_TRIPLECLICK3_SCROLLBAR_DOWN
;
2093 if (where
== BORDER
)
2094 key
= KEYC_TRIPLECLICK3_BORDER
;
2096 case MOUSE_BUTTON_6
:
2098 key
= KEYC_TRIPLECLICK6_PANE
;
2099 if (where
== STATUS
)
2100 key
= KEYC_TRIPLECLICK6_STATUS
;
2101 if (where
== STATUS_LEFT
)
2102 key
= KEYC_TRIPLECLICK6_STATUS_LEFT
;
2103 if (where
== STATUS_RIGHT
)
2104 key
= KEYC_TRIPLECLICK6_STATUS_RIGHT
;
2105 if (where
== STATUS_DEFAULT
)
2106 key
= KEYC_TRIPLECLICK6_STATUS_DEFAULT
;
2107 if (where
== SCROLLBAR_UP
)
2108 key
= KEYC_TRIPLECLICK6_SCROLLBAR_UP
;
2109 if (where
== SCROLLBAR_SLIDER
)
2110 key
= KEYC_TRIPLECLICK6_SCROLLBAR_SLIDER
;
2111 if (where
== SCROLLBAR_DOWN
)
2112 key
= KEYC_TRIPLECLICK6_SCROLLBAR_DOWN
;
2113 if (where
== BORDER
)
2114 key
= KEYC_TRIPLECLICK6_BORDER
;
2116 case MOUSE_BUTTON_7
:
2118 key
= KEYC_TRIPLECLICK7_PANE
;
2119 if (where
== STATUS
)
2120 key
= KEYC_TRIPLECLICK7_STATUS
;
2121 if (where
== STATUS_LEFT
)
2122 key
= KEYC_TRIPLECLICK7_STATUS_LEFT
;
2123 if (where
== STATUS_RIGHT
)
2124 key
= KEYC_TRIPLECLICK7_STATUS_RIGHT
;
2125 if (where
== STATUS_DEFAULT
)
2126 key
= KEYC_TRIPLECLICK7_STATUS_DEFAULT
;
2127 if (where
== SCROLLBAR_UP
)
2128 key
= KEYC_TRIPLECLICK7_SCROLLBAR_UP
;
2129 if (where
== SCROLLBAR_SLIDER
)
2130 key
= KEYC_TRIPLECLICK7_SCROLLBAR_SLIDER
;
2131 if (where
== SCROLLBAR_DOWN
)
2132 key
= KEYC_TRIPLECLICK7_SCROLLBAR_DOWN
;
2133 if (where
== BORDER
)
2134 key
= KEYC_TRIPLECLICK7_BORDER
;
2136 case MOUSE_BUTTON_8
:
2138 key
= KEYC_TRIPLECLICK8_PANE
;
2139 if (where
== STATUS
)
2140 key
= KEYC_TRIPLECLICK8_STATUS
;
2141 if (where
== STATUS_LEFT
)
2142 key
= KEYC_TRIPLECLICK8_STATUS_LEFT
;
2143 if (where
== STATUS_RIGHT
)
2144 key
= KEYC_TRIPLECLICK8_STATUS_RIGHT
;
2145 if (where
== STATUS_DEFAULT
)
2146 key
= KEYC_TRIPLECLICK8_STATUS_DEFAULT
;
2147 if (where
== SCROLLBAR_UP
)
2148 key
= KEYC_TRIPLECLICK8_SCROLLBAR_UP
;
2149 if (where
== SCROLLBAR_SLIDER
)
2150 key
= KEYC_TRIPLECLICK8_SCROLLBAR_SLIDER
;
2151 if (where
== SCROLLBAR_DOWN
)
2152 key
= KEYC_TRIPLECLICK8_SCROLLBAR_DOWN
;
2153 if (where
== BORDER
)
2154 key
= KEYC_TRIPLECLICK8_BORDER
;
2156 case MOUSE_BUTTON_9
:
2158 key
= KEYC_TRIPLECLICK9_PANE
;
2159 if (where
== STATUS
)
2160 key
= KEYC_TRIPLECLICK9_STATUS
;
2161 if (where
== STATUS_LEFT
)
2162 key
= KEYC_TRIPLECLICK9_STATUS_LEFT
;
2163 if (where
== STATUS_RIGHT
)
2164 key
= KEYC_TRIPLECLICK9_STATUS_RIGHT
;
2165 if (where
== STATUS_DEFAULT
)
2166 key
= KEYC_TRIPLECLICK9_STATUS_DEFAULT
;
2167 if (where
== SCROLLBAR_UP
)
2168 key
= KEYC_TRIPLECLICK9_SCROLLBAR_UP
;
2169 if (where
== SCROLLBAR_SLIDER
)
2170 key
= KEYC_TRIPLECLICK9_SCROLLBAR_SLIDER
;
2171 if (where
== SCROLLBAR_DOWN
)
2172 key
= KEYC_TRIPLECLICK9_SCROLLBAR_DOWN
;
2173 if (where
== BORDER
)
2174 key
= KEYC_TRIPLECLICK9_BORDER
;
2176 case MOUSE_BUTTON_10
:
2178 key
= KEYC_TRIPLECLICK10_PANE
;
2179 if (where
== STATUS
)
2180 key
= KEYC_TRIPLECLICK10_STATUS
;
2181 if (where
== STATUS_LEFT
)
2182 key
= KEYC_TRIPLECLICK10_STATUS_LEFT
;
2183 if (where
== STATUS_RIGHT
)
2184 key
= KEYC_TRIPLECLICK10_STATUS_RIGHT
;
2185 if (where
== STATUS_DEFAULT
)
2186 key
= KEYC_TRIPLECLICK10_STATUS_DEFAULT
;
2187 if (where
== SCROLLBAR_UP
)
2188 key
= KEYC_TRIPLECLICK10_SCROLLBAR_UP
;
2189 if (where
== SCROLLBAR_SLIDER
)
2190 key
= KEYC_TRIPLECLICK10_SCROLLBAR_SLIDER
;
2191 if (where
== SCROLLBAR_DOWN
)
2192 key
= KEYC_TRIPLECLICK10_SCROLLBAR_DOWN
;
2193 if (where
== BORDER
)
2194 key
= KEYC_TRIPLECLICK10_BORDER
;
2196 case MOUSE_BUTTON_11
:
2198 key
= KEYC_TRIPLECLICK11_PANE
;
2199 if (where
== STATUS
)
2200 key
= KEYC_TRIPLECLICK11_STATUS
;
2201 if (where
== STATUS_LEFT
)
2202 key
= KEYC_TRIPLECLICK11_STATUS_LEFT
;
2203 if (where
== STATUS_RIGHT
)
2204 key
= KEYC_TRIPLECLICK11_STATUS_RIGHT
;
2205 if (where
== STATUS_DEFAULT
)
2206 key
= KEYC_TRIPLECLICK11_STATUS_DEFAULT
;
2207 if (where
== SCROLLBAR_UP
)
2208 key
= KEYC_TRIPLECLICK11_SCROLLBAR_UP
;
2209 if (where
== SCROLLBAR_SLIDER
)
2210 key
= KEYC_TRIPLECLICK11_SCROLLBAR_SLIDER
;
2211 if (where
== SCROLLBAR_DOWN
)
2212 key
= KEYC_TRIPLECLICK11_SCROLLBAR_DOWN
;
2213 if (where
== BORDER
)
2214 key
= KEYC_TRIPLECLICK11_BORDER
;
2219 if (key
== KEYC_UNKNOWN
)
2220 return (KEYC_UNKNOWN
);
2223 /* Apply modifiers if any. */
2224 if (b
& MOUSE_MASK_META
)
2226 if (b
& MOUSE_MASK_CTRL
)
2228 if (b
& MOUSE_MASK_SHIFT
)
2231 if (log_get_level() != 0)
2232 log_debug("mouse key is %s", key_string_lookup_key (key
, 1));
2236 /* Is this a bracket paste key? */
2238 server_client_is_bracket_paste(struct client
*c
, key_code key
)
2240 if (key
== KEYC_PASTE_START
) {
2241 c
->flags
|= CLIENT_BRACKETPASTING
;
2242 log_debug("%s: bracket paste on", c
->name
);
2246 if (key
== KEYC_PASTE_END
) {
2247 c
->flags
&= ~CLIENT_BRACKETPASTING
;
2248 log_debug("%s: bracket paste off", c
->name
);
2252 return !!(c
->flags
& CLIENT_BRACKETPASTING
);
2255 /* Is this fast enough to probably be a paste? */
2257 server_client_is_assume_paste(struct client
*c
)
2259 struct session
*s
= c
->session
;
2263 if (c
->flags
& CLIENT_BRACKETPASTING
)
2265 if ((t
= options_get_number(s
->options
, "assume-paste-time")) == 0)
2268 timersub(&c
->activity_time
, &c
->last_activity_time
, &tv
);
2269 if (tv
.tv_sec
== 0 && tv
.tv_usec
< t
* 1000) {
2270 if (c
->flags
& CLIENT_ASSUMEPASTING
)
2272 c
->flags
|= CLIENT_ASSUMEPASTING
;
2273 log_debug("%s: assume paste on", c
->name
);
2276 if (c
->flags
& CLIENT_ASSUMEPASTING
) {
2277 c
->flags
&= ~CLIENT_ASSUMEPASTING
;
2278 log_debug("%s: assume paste off", c
->name
);
2283 /* Has the latest client changed? */
2285 server_client_update_latest(struct client
*c
)
2289 if (c
->session
== NULL
)
2291 w
= c
->session
->curw
->window
;
2297 if (options_get_number(w
->options
, "window-size") == WINDOW_SIZE_LATEST
)
2298 recalculate_size(w
, 0);
2300 notify_client("client-active", c
);
2303 /* Get repeat time. */
2305 server_client_repeat_time(struct client
*c
, struct key_binding
*bd
)
2307 struct session
*s
= c
->session
;
2308 u_int repeat
, initial
;
2310 if (~bd
->flags
& KEY_BINDING_REPEAT
)
2312 repeat
= options_get_number(s
->options
, "repeat-time");
2315 if ((~c
->flags
& CLIENT_REPEAT
) || bd
->key
!= c
->last_key
) {
2316 initial
= options_get_number(s
->options
, "initial-repeat-time");
2324 * Handle data key input from client. This owns and can modify the key event it
2325 * is given and is responsible for freeing it.
2327 static enum cmd_retval
2328 server_client_key_callback(struct cmdq_item
*item
, void *data
)
2330 struct client
*c
= cmdq_get_client(item
);
2331 struct key_event
*event
= data
;
2332 key_code key
= event
->key
;
2333 struct mouse_event
*m
= &event
->m
;
2334 struct session
*s
= c
->session
;
2336 struct window_pane
*wp
;
2337 struct window_mode_entry
*wme
;
2339 struct key_table
*table
, *first
;
2340 struct key_binding
*bd
;
2342 uint64_t flags
, prefix_delay
;
2343 struct cmd_find_state fs
;
2344 key_code key0
, prefix
, prefix2
;
2346 /* Check the client is good to accept input. */
2347 if (s
== NULL
|| (c
->flags
& CLIENT_UNATTACHEDFLAGS
))
2351 /* Update the activity timer. */
2352 memcpy(&c
->last_activity_time
, &c
->activity_time
,
2353 sizeof c
->last_activity_time
);
2354 if (gettimeofday(&c
->activity_time
, NULL
) != 0)
2355 fatal("gettimeofday failed");
2356 session_update_activity(s
, &c
->activity_time
);
2358 /* Check for mouse keys. */
2360 if (key
== KEYC_MOUSE
|| key
== KEYC_DOUBLECLICK
) {
2361 if (c
->flags
& CLIENT_READONLY
)
2363 key
= server_client_check_mouse(c
, event
);
2364 if (key
== KEYC_UNKNOWN
)
2371 * Mouse drag is in progress, so fire the callback (now that
2372 * the mouse event is valid).
2374 if ((key
& KEYC_MASK_KEY
) == KEYC_DRAGGING
) {
2375 c
->tty
.mouse_drag_update(c
, m
);
2381 /* Find affected pane. */
2382 if (!KEYC_IS_MOUSE(key
) || cmd_find_from_mouse(&fs
, m
, 0) != 0)
2383 cmd_find_from_client(&fs
, c
, 0);
2386 /* Forward mouse keys if disabled. */
2387 if (KEYC_IS_MOUSE(key
) && !options_get_number(s
->options
, "mouse"))
2390 /* Forward if bracket pasting. */
2391 if (server_client_is_bracket_paste (c
, key
))
2394 /* Treat everything as a regular key when pasting is detected. */
2395 if (!KEYC_IS_MOUSE(key
) &&
2396 key
!= KEYC_FOCUS_IN
&&
2397 key
!= KEYC_FOCUS_OUT
&&
2398 (~key
& KEYC_SENT
) &&
2399 server_client_is_assume_paste(c
))
2403 * Work out the current key table. If the pane is in a mode, use
2404 * the mode table instead of the default key table.
2406 if (server_client_is_default_key_table(c
, c
->keytable
) &&
2408 (wme
= TAILQ_FIRST(&wp
->modes
)) != NULL
&&
2409 wme
->mode
->key_table
!= NULL
)
2410 table
= key_bindings_get_table(wme
->mode
->key_table(wme
), 1);
2412 table
= c
->keytable
;
2417 * The prefix always takes precedence and forces a switch to the prefix
2418 * table, unless we are already there.
2420 prefix
= (key_code
)options_get_number(s
->options
, "prefix");
2421 prefix2
= (key_code
)options_get_number(s
->options
, "prefix2");
2422 key0
= (key
& (KEYC_MASK_KEY
|KEYC_MASK_MODIFIERS
));
2423 if ((key0
== (prefix
& (KEYC_MASK_KEY
|KEYC_MASK_MODIFIERS
)) ||
2424 key0
== (prefix2
& (KEYC_MASK_KEY
|KEYC_MASK_MODIFIERS
))) &&
2425 strcmp(table
->name
, "prefix") != 0) {
2426 server_client_set_key_table(c
, "prefix");
2427 server_status_client(c
);
2433 /* Log key table. */
2435 log_debug("key table %s (no pane)", table
->name
);
2437 log_debug("key table %s (pane %%%u)", table
->name
, wp
->id
);
2438 if (c
->flags
& CLIENT_REPEAT
)
2439 log_debug("currently repeating");
2441 bd
= key_bindings_get(table
, key0
);
2444 * If prefix-timeout is enabled and we're in the prefix table, see if
2445 * the timeout has been exceeded. Revert to the root table if so.
2447 prefix_delay
= options_get_number(global_options
, "prefix-timeout");
2448 if (prefix_delay
> 0 &&
2449 strcmp(table
->name
, "prefix") == 0 &&
2450 server_client_key_table_activity_diff(c
) > prefix_delay
) {
2452 * If repeating is active and this is a repeating binding,
2453 * ignore the timeout.
2456 (c
->flags
& CLIENT_REPEAT
) &&
2457 (bd
->flags
& KEY_BINDING_REPEAT
)) {
2458 log_debug("prefix timeout ignored, repeat is active");
2460 log_debug("prefix timeout exceeded");
2461 server_client_set_key_table(c
, NULL
);
2462 first
= table
= c
->keytable
;
2463 server_status_client(c
);
2468 /* Try to see if there is a key binding in the current table. */
2471 * Key was matched in this table. If currently repeating but a
2472 * non-repeating binding was found, stop repeating and try
2473 * again in the root table.
2475 if ((c
->flags
& CLIENT_REPEAT
) &&
2476 (~bd
->flags
& KEY_BINDING_REPEAT
)) {
2477 log_debug("found in key table %s (not repeating)",
2479 server_client_set_key_table(c
, NULL
);
2480 first
= table
= c
->keytable
;
2481 c
->flags
&= ~CLIENT_REPEAT
;
2482 server_status_client(c
);
2485 log_debug("found in key table %s", table
->name
);
2488 * Take a reference to this table to make sure the key binding
2489 * doesn't disappear.
2491 table
->references
++;
2494 * If this is a repeating key, start the timer. Otherwise reset
2495 * the client back to the root table.
2497 repeat
= server_client_repeat_time(c
, bd
);
2499 c
->flags
|= CLIENT_REPEAT
;
2500 c
->last_key
= bd
->key
;
2502 tv
.tv_sec
= repeat
/ 1000;
2503 tv
.tv_usec
= (repeat
% 1000) * 1000L;
2504 evtimer_del(&c
->repeat_timer
);
2505 evtimer_add(&c
->repeat_timer
, &tv
);
2507 c
->flags
&= ~CLIENT_REPEAT
;
2508 server_client_set_key_table(c
, NULL
);
2510 server_status_client(c
);
2512 /* Execute the key binding. */
2513 key_bindings_dispatch(bd
, item
, c
, event
, &fs
);
2514 key_bindings_unref_table(table
);
2519 * No match, try the ANY key.
2521 if (key0
!= KEYC_ANY
) {
2527 * Binding movement keys is useless since we only turn them on when the
2528 * application requests, so don't let them exit the prefix table.
2530 if (key
== KEYC_MOUSEMOVE_PANE
||
2531 key
== KEYC_MOUSEMOVE_STATUS
||
2532 key
== KEYC_MOUSEMOVE_STATUS_LEFT
||
2533 key
== KEYC_MOUSEMOVE_STATUS_RIGHT
||
2534 key
== KEYC_MOUSEMOVE_STATUS_DEFAULT
||
2535 key
== KEYC_MOUSEMOVE_BORDER
)
2539 * No match in this table. If not in the root table or if repeating
2540 * switch the client back to the root table and try again.
2542 log_debug("not found in key table %s", table
->name
);
2543 if (!server_client_is_default_key_table(c
, table
) ||
2544 (c
->flags
& CLIENT_REPEAT
)) {
2545 log_debug("trying in root table");
2546 server_client_set_key_table(c
, NULL
);
2547 table
= c
->keytable
;
2548 if (c
->flags
& CLIENT_REPEAT
)
2550 c
->flags
&= ~CLIENT_REPEAT
;
2551 server_status_client(c
);
2556 * No match in the root table either. If this wasn't the first table
2557 * tried, don't pass the key to the pane.
2559 if (first
!= table
&& (~flags
& CLIENT_REPEAT
)) {
2560 server_client_set_key_table(c
, NULL
);
2561 server_status_client(c
);
2566 if (c
->flags
& CLIENT_READONLY
)
2569 window_pane_key(wp
, c
, s
, wl
, key
, m
);
2573 if (c
->flags
& CLIENT_READONLY
)
2575 if (event
->buf
!= NULL
)
2576 window_pane_paste(wp
, event
->buf
, event
->len
);
2581 if (s
!= NULL
&& key
!= KEYC_FOCUS_OUT
)
2582 server_client_update_latest(c
);
2585 return (CMD_RETURN_NORMAL
);
2588 /* Handle a key event. */
2590 server_client_handle_key(struct client
*c
, struct key_event
*event
)
2592 struct session
*s
= c
->session
;
2593 struct cmdq_item
*item
;
2595 /* Check the client is good to accept input. */
2596 if (s
== NULL
|| (c
->flags
& CLIENT_UNATTACHEDFLAGS
))
2600 * Key presses in overlay mode and the command prompt are a special
2601 * case. The queue might be blocked so they need to be processed
2602 * immediately rather than queued.
2604 if (~c
->flags
& CLIENT_READONLY
) {
2605 if (c
->message_string
!= NULL
) {
2606 if (c
->message_ignore_keys
)
2608 status_message_clear(c
);
2610 if (c
->overlay_key
!= NULL
) {
2611 switch (c
->overlay_key(c
, c
->overlay_data
, event
)) {
2615 server_client_clear_overlay(c
);
2619 server_client_clear_overlay(c
);
2620 if (c
->prompt_string
!= NULL
) {
2621 if (status_prompt_key(c
, event
->key
) == 0)
2627 * Add the key to the queue so it happens after any commands queued by
2630 item
= cmdq_get_callback(server_client_key_callback
, event
);
2631 cmdq_append(c
, item
);
2635 /* Client functions that need to happen every loop. */
2637 server_client_loop(void)
2641 struct window_pane
*wp
;
2643 /* Check for window resize. This is done before redrawing. */
2644 RB_FOREACH(w
, windows
, &windows
)
2645 server_client_check_window_resize(w
);
2647 /* Check clients. */
2648 TAILQ_FOREACH(c
, &clients
, entry
) {
2649 server_client_check_exit(c
);
2650 if (c
->session
!= NULL
) {
2651 server_client_check_modes(c
);
2652 server_client_check_redraw(c
);
2653 server_client_reset_state(c
);
2658 * Any windows will have been redrawn as part of clients, so clear
2661 RB_FOREACH(w
, windows
, &windows
) {
2662 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
2664 server_client_check_pane_resize(wp
);
2665 server_client_check_pane_buffer(wp
);
2667 wp
->flags
&= ~(PANE_REDRAW
|PANE_REDRAWSCROLLBAR
);
2669 check_window_name(w
);
2673 /* Check if window needs to be resized. */
2675 server_client_check_window_resize(struct window
*w
)
2679 if (~w
->flags
& WINDOW_RESIZE
)
2682 TAILQ_FOREACH(wl
, &w
->winlinks
, wentry
) {
2683 if (wl
->session
->attached
!= 0 && wl
->session
->curw
== wl
)
2689 log_debug("%s: resizing window @%u", __func__
, w
->id
);
2690 resize_window(w
, w
->new_sx
, w
->new_sy
, w
->new_xpixel
, w
->new_ypixel
);
2693 /* Resize timer event. */
2695 server_client_resize_timer(__unused
int fd
, __unused
short events
, void *data
)
2697 struct window_pane
*wp
= data
;
2699 log_debug("%s: %%%u resize timer expired", __func__
, wp
->id
);
2700 evtimer_del(&wp
->resize_timer
);
2703 /* Check if pane should be resized. */
2705 server_client_check_pane_resize(struct window_pane
*wp
)
2707 struct window_pane_resize
*r
;
2708 struct window_pane_resize
*r1
;
2709 struct window_pane_resize
*first
;
2710 struct window_pane_resize
*last
;
2711 struct timeval tv
= { .tv_usec
= 250000 };
2713 if (TAILQ_EMPTY(&wp
->resize_queue
))
2716 if (!event_initialized(&wp
->resize_timer
))
2717 evtimer_set(&wp
->resize_timer
, server_client_resize_timer
, wp
);
2718 if (evtimer_pending(&wp
->resize_timer
, NULL
))
2721 log_debug("%s: %%%u needs to be resized", __func__
, wp
->id
);
2722 TAILQ_FOREACH(r
, &wp
->resize_queue
, entry
) {
2723 log_debug("queued resize: %ux%u -> %ux%u", r
->osx
, r
->osy
,
2728 * There are three cases that matter:
2730 * - Only one resize. It can just be applied.
2732 * - Multiple resizes and the ending size is different from the
2733 * starting size. We can discard all resizes except the most recent.
2735 * - Multiple resizes and the ending size is the same as the starting
2736 * size. We must resize at least twice to force the application to
2737 * redraw. So apply the first and leave the last on the queue for
2740 first
= TAILQ_FIRST(&wp
->resize_queue
);
2741 last
= TAILQ_LAST(&wp
->resize_queue
, window_pane_resizes
);
2742 if (first
== last
) {
2743 /* Only one resize. */
2744 window_pane_send_resize(wp
, first
->sx
, first
->sy
);
2745 TAILQ_REMOVE(&wp
->resize_queue
, first
, entry
);
2747 } else if (last
->sx
!= first
->osx
|| last
->sy
!= first
->osy
) {
2748 /* Multiple resizes ending up with a different size. */
2749 window_pane_send_resize(wp
, last
->sx
, last
->sy
);
2750 TAILQ_FOREACH_SAFE(r
, &wp
->resize_queue
, entry
, r1
) {
2751 TAILQ_REMOVE(&wp
->resize_queue
, r
, entry
);
2756 * Multiple resizes ending up with the same size. There will
2757 * not be more than one to the same size in succession so we
2758 * can just use the last-but-one on the list and leave the last
2759 * for later. We reduce the time until the next check to avoid
2760 * a long delay between the resizes.
2762 r
= TAILQ_PREV(last
, window_pane_resizes
, entry
);
2763 window_pane_send_resize(wp
, r
->sx
, r
->sy
);
2764 TAILQ_FOREACH_SAFE(r
, &wp
->resize_queue
, entry
, r1
) {
2767 TAILQ_REMOVE(&wp
->resize_queue
, r
, entry
);
2772 evtimer_add(&wp
->resize_timer
, &tv
);
2775 /* Check pane buffer size. */
2777 server_client_check_pane_buffer(struct window_pane
*wp
)
2779 struct evbuffer
*evb
= wp
->event
->input
;
2782 struct window_pane_offset
*wpo
;
2784 u_int attached_clients
= 0;
2788 * Work out the minimum used size. This is the most that can be removed
2791 minimum
= wp
->offset
.used
;
2792 if (wp
->pipe_fd
!= -1 && wp
->pipe_offset
.used
< minimum
)
2793 minimum
= wp
->pipe_offset
.used
;
2794 TAILQ_FOREACH(c
, &clients
, entry
) {
2795 if (c
->session
== NULL
)
2799 if (~c
->flags
& CLIENT_CONTROL
) {
2803 wpo
= control_pane_offset(c
, wp
, &flag
);
2812 window_pane_get_new_data(wp
, wpo
, &new_size
);
2813 log_debug("%s: %s has %zu bytes used and %zu left for %%%u",
2814 __func__
, c
->name
, wpo
->used
- wp
->base_offset
, new_size
,
2816 if (wpo
->used
< minimum
)
2817 minimum
= wpo
->used
;
2819 if (attached_clients
== 0)
2821 minimum
-= wp
->base_offset
;
2825 /* Drain the buffer. */
2826 log_debug("%s: %%%u has %zu minimum (of %zu) bytes used", __func__
,
2827 wp
->id
, minimum
, EVBUFFER_LENGTH(evb
));
2828 evbuffer_drain(evb
, minimum
);
2831 * Adjust the base offset. If it would roll over, all the offsets into
2832 * the buffer need to be adjusted.
2834 if (wp
->base_offset
> SIZE_MAX
- minimum
) {
2835 log_debug("%s: %%%u base offset has wrapped", __func__
, wp
->id
);
2836 wp
->offset
.used
-= wp
->base_offset
;
2837 if (wp
->pipe_fd
!= -1)
2838 wp
->pipe_offset
.used
-= wp
->base_offset
;
2839 TAILQ_FOREACH(c
, &clients
, entry
) {
2840 if (c
->session
== NULL
|| (~c
->flags
& CLIENT_CONTROL
))
2842 wpo
= control_pane_offset(c
, wp
, &flag
);
2843 if (wpo
!= NULL
&& !flag
)
2844 wpo
->used
-= wp
->base_offset
;
2846 wp
->base_offset
= minimum
;
2848 wp
->base_offset
+= minimum
;
2852 * If there is data remaining, and there are no clients able to consume
2853 * it, do not read any more. This is true when there are attached
2854 * clients, all of which are control clients which are not able to
2855 * accept any more data.
2857 log_debug("%s: pane %%%u is %s", __func__
, wp
->id
, off
? "off" : "on");
2859 bufferevent_disable(wp
->event
, EV_READ
);
2861 bufferevent_enable(wp
->event
, EV_READ
);
2865 * Update cursor position and mode settings. The scroll region and attributes
2866 * are cleared when idle (waiting for an event) as this is the most likely time
2867 * a user may interrupt tmux, for example with ~^Z in ssh(1). This is a
2868 * compromise between excessive resets and likelihood of an interrupt.
2870 * tty_region/tty_reset/tty_update_mode already take care of not resetting
2871 * things that are already in their default state.
2874 server_client_reset_state(struct client
*c
)
2876 struct tty
*tty
= &c
->tty
;
2877 struct window
*w
= c
->session
->curw
->window
;
2878 struct window_pane
*wp
= server_client_get_pane(c
), *loop
;
2879 struct screen
*s
= NULL
;
2880 struct options
*oo
= c
->session
->options
;
2881 int mode
= 0, cursor
, flags
, n
;
2882 u_int cx
= 0, cy
= 0, ox
, oy
, sx
, sy
;
2884 if (c
->flags
& (CLIENT_CONTROL
|CLIENT_SUSPENDED
))
2887 /* Disable the block flag. */
2888 flags
= (tty
->flags
& TTY_BLOCK
);
2889 tty
->flags
&= ~TTY_BLOCK
;
2891 /* Get mode from overlay if any, else from screen. */
2892 if (c
->overlay_draw
!= NULL
) {
2893 if (c
->overlay_mode
!= NULL
)
2894 s
= c
->overlay_mode(c
, c
->overlay_data
, &cx
, &cy
);
2895 } else if (c
->prompt_string
== NULL
)
2898 s
= c
->status
.active
;
2901 if (log_get_level() != 0) {
2902 log_debug("%s: client %s mode %s", __func__
, c
->name
,
2903 screen_mode_to_string(mode
));
2906 /* Reset region and margin. */
2907 tty_region_off(tty
);
2908 tty_margin_off(tty
);
2910 /* Move cursor to pane cursor and offset. */
2911 if (c
->prompt_string
!= NULL
) {
2912 n
= options_get_number(oo
, "status-position");
2916 n
= status_line_size(c
);
2922 cx
= c
->prompt_cursor
;
2923 } else if (c
->overlay_draw
== NULL
) {
2925 tty_window_offset(tty
, &ox
, &oy
, &sx
, &sy
);
2926 if (wp
->xoff
+ s
->cx
>= ox
&& wp
->xoff
+ s
->cx
<= ox
+ sx
&&
2927 wp
->yoff
+ s
->cy
>= oy
&& wp
->yoff
+ s
->cy
<= oy
+ sy
) {
2930 cx
= wp
->xoff
+ s
->cx
- ox
;
2931 cy
= wp
->yoff
+ s
->cy
- oy
;
2933 if (status_at_line(c
) == 0)
2934 cy
+= status_line_size(c
);
2937 mode
&= ~MODE_CURSOR
;
2939 log_debug("%s: cursor to %u,%u", __func__
, cx
, cy
);
2940 tty_cursor(tty
, cx
, cy
);
2943 * Set mouse mode if requested. To support dragging, always use button
2946 if (options_get_number(oo
, "mouse")) {
2947 if (c
->overlay_draw
== NULL
) {
2948 mode
&= ~ALL_MOUSE_MODES
;
2949 TAILQ_FOREACH(loop
, &w
->panes
, entry
) {
2950 if (loop
->screen
->mode
& MODE_MOUSE_ALL
)
2951 mode
|= MODE_MOUSE_ALL
;
2954 if (~mode
& MODE_MOUSE_ALL
)
2955 mode
|= MODE_MOUSE_BUTTON
;
2958 /* Clear bracketed paste mode if at the prompt. */
2959 if (c
->overlay_draw
== NULL
&& c
->prompt_string
!= NULL
)
2960 mode
&= ~MODE_BRACKETPASTE
;
2962 /* Set the terminal mode and reset attributes. */
2963 tty_update_mode(tty
, mode
, s
);
2966 /* All writing must be done, send a sync end (if it was started). */
2968 tty
->flags
|= flags
;
2971 /* Repeat time callback. */
2973 server_client_repeat_timer(__unused
int fd
, __unused
short events
, void *data
)
2975 struct client
*c
= data
;
2977 if (c
->flags
& CLIENT_REPEAT
) {
2978 server_client_set_key_table(c
, NULL
);
2979 c
->flags
&= ~CLIENT_REPEAT
;
2980 server_status_client(c
);
2984 /* Double-click callback. */
2986 server_client_click_timer(__unused
int fd
, __unused
short events
, void *data
)
2988 struct client
*c
= data
;
2989 struct key_event
*event
;
2991 log_debug("click timer expired");
2993 if (c
->flags
& CLIENT_TRIPLECLICK
) {
2995 * Waiting for a third click that hasn't happened, so this must
2996 * have been a double click.
2998 event
= xcalloc(1, sizeof *event
);
2999 event
->key
= KEYC_DOUBLECLICK
;
3000 memcpy(&event
->m
, &c
->click_event
, sizeof event
->m
);
3001 if (!server_client_handle_key(c
, event
)) {
3006 c
->flags
&= ~(CLIENT_DOUBLECLICK
|CLIENT_TRIPLECLICK
);
3009 /* Check if client should be exited. */
3011 server_client_check_exit(struct client
*c
)
3013 struct client_file
*cf
;
3014 const char *name
= c
->exit_session
;
3018 if (c
->flags
& (CLIENT_DEAD
|CLIENT_EXITED
))
3020 if (~c
->flags
& CLIENT_EXIT
)
3023 if (c
->flags
& CLIENT_CONTROL
) {
3025 if (!control_all_done(c
))
3028 RB_FOREACH(cf
, client_files
, &c
->files
) {
3029 if (EVBUFFER_LENGTH(cf
->buffer
) != 0)
3032 c
->flags
|= CLIENT_EXITED
;
3034 switch (c
->exit_type
) {
3035 case CLIENT_EXIT_RETURN
:
3036 if (c
->exit_message
!= NULL
)
3037 msize
= strlen(c
->exit_message
) + 1;
3040 size
= (sizeof c
->retval
) + msize
;
3041 data
= xmalloc(size
);
3042 memcpy(data
, &c
->retval
, sizeof c
->retval
);
3043 if (c
->exit_message
!= NULL
)
3044 memcpy(data
+ sizeof c
->retval
, c
->exit_message
, msize
);
3045 proc_send(c
->peer
, MSG_EXIT
, -1, data
, size
);
3048 case CLIENT_EXIT_SHUTDOWN
:
3049 proc_send(c
->peer
, MSG_SHUTDOWN
, -1, NULL
, 0);
3051 case CLIENT_EXIT_DETACH
:
3052 proc_send(c
->peer
, c
->exit_msgtype
, -1, name
, strlen(name
) + 1);
3055 free(c
->exit_session
);
3056 free(c
->exit_message
);
3059 /* Redraw timer callback. */
3061 server_client_redraw_timer(__unused
int fd
, __unused
short events
,
3062 __unused
void *data
)
3064 log_debug("redraw timer fired");
3068 * Check if modes need to be updated. Only modes in the current window are
3069 * updated and it is done when the status line is redrawn.
3072 server_client_check_modes(struct client
*c
)
3074 struct window
*w
= c
->session
->curw
->window
;
3075 struct window_pane
*wp
;
3076 struct window_mode_entry
*wme
;
3078 if (c
->flags
& (CLIENT_CONTROL
|CLIENT_SUSPENDED
))
3080 if (~c
->flags
& CLIENT_REDRAWSTATUS
)
3082 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
3083 wme
= TAILQ_FIRST(&wp
->modes
);
3084 if (wme
!= NULL
&& wme
->mode
->update
!= NULL
)
3085 wme
->mode
->update(wme
);
3089 /* Check for client redraws. */
3091 server_client_check_redraw(struct client
*c
)
3093 struct session
*s
= c
->session
;
3094 struct tty
*tty
= &c
->tty
;
3095 struct window
*w
= c
->session
->curw
->window
;
3096 struct window_pane
*wp
;
3097 int needed
, tty_flags
, mode
= tty
->mode
;
3098 uint64_t client_flags
= 0;
3099 int redraw_pane
, redraw_scrollbar_only
;
3101 struct timeval tv
= { .tv_usec
= 1000 };
3102 static struct event ev
;
3105 if (c
->flags
& (CLIENT_CONTROL
|CLIENT_SUSPENDED
))
3107 if (c
->flags
& CLIENT_ALLREDRAWFLAGS
) {
3108 log_debug("%s: redraw%s%s%s%s%s%s", c
->name
,
3109 (c
->flags
& CLIENT_REDRAWWINDOW
) ? " window" : "",
3110 (c
->flags
& CLIENT_REDRAWSTATUS
) ? " status" : "",
3111 (c
->flags
& CLIENT_REDRAWBORDERS
) ? " borders" : "",
3112 (c
->flags
& CLIENT_REDRAWOVERLAY
) ? " overlay" : "",
3113 (c
->flags
& CLIENT_REDRAWPANES
) ? " panes" : "",
3114 (c
->flags
& CLIENT_REDRAWSCROLLBARS
) ? " scrollbars" : "");
3118 * If there is outstanding data, defer the redraw until it has been
3119 * consumed. We can just add a timer to get out of the event loop and
3123 if (c
->flags
& CLIENT_ALLREDRAWFLAGS
)
3126 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
3127 if (wp
->flags
& PANE_REDRAW
) {
3129 client_flags
|= CLIENT_REDRAWPANES
;
3132 if (wp
->flags
& PANE_REDRAWSCROLLBAR
) {
3134 client_flags
|= CLIENT_REDRAWSCROLLBARS
;
3135 /* no break - later panes may need redraw */
3139 if (needed
&& (left
= EVBUFFER_LENGTH(tty
->out
)) != 0) {
3140 log_debug("%s: redraw deferred (%zu left)", c
->name
, left
);
3141 if (!evtimer_initialized(&ev
))
3142 evtimer_set(&ev
, server_client_redraw_timer
, NULL
);
3143 if (!evtimer_pending(&ev
, NULL
)) {
3144 log_debug("redraw timer started");
3145 evtimer_add(&ev
, &tv
);
3148 if (~c
->flags
& CLIENT_REDRAWWINDOW
) {
3149 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
3150 if (wp
->flags
& (PANE_REDRAW
)) {
3151 log_debug("%s: pane %%%u needs redraw",
3153 c
->redraw_panes
|= (1 << bit
);
3154 } else if (wp
->flags
& PANE_REDRAWSCROLLBAR
) {
3155 log_debug("%s: pane %%%u scrollbar "
3156 "needs redraw", c
->name
, wp
->id
);
3157 c
->redraw_scrollbars
|= (1 << bit
);
3161 * If more that 64 panes, give up and
3162 * just redraw the window.
3164 client_flags
&= ~(CLIENT_REDRAWPANES
|
3165 CLIENT_REDRAWSCROLLBARS
);
3166 client_flags
|= CLIENT_REDRAWWINDOW
;
3170 if (c
->redraw_panes
!= 0)
3171 c
->flags
|= CLIENT_REDRAWPANES
;
3172 if (c
->redraw_scrollbars
!= 0)
3173 c
->flags
|= CLIENT_REDRAWSCROLLBARS
;
3175 c
->flags
|= client_flags
;
3178 log_debug("%s: redraw needed", c
->name
);
3180 tty_flags
= tty
->flags
& (TTY_BLOCK
|TTY_FREEZE
|TTY_NOCURSOR
);
3181 tty
->flags
= (tty
->flags
& ~(TTY_BLOCK
|TTY_FREEZE
))|TTY_NOCURSOR
;
3183 if (~c
->flags
& CLIENT_REDRAWWINDOW
) {
3185 * If not redrawing the entire window, check whether each pane
3186 * needs to be redrawn.
3188 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
3190 redraw_scrollbar_only
= 0;
3191 if (wp
->flags
& PANE_REDRAW
)
3193 else if (c
->flags
& CLIENT_REDRAWPANES
) {
3194 if (c
->redraw_panes
& (1 << bit
))
3196 } else if (c
->flags
& CLIENT_REDRAWSCROLLBARS
) {
3197 if (c
->redraw_scrollbars
& (1 << bit
))
3198 redraw_scrollbar_only
= 1;
3201 if (!redraw_pane
&& !redraw_scrollbar_only
)
3203 if (redraw_scrollbar_only
) {
3204 log_debug("%s: redrawing (scrollbar only) pane "
3205 "%%%u", __func__
, wp
->id
);
3207 log_debug("%s: redrawing pane %%%u", __func__
,
3210 screen_redraw_pane(c
, wp
, redraw_scrollbar_only
);
3212 c
->redraw_panes
= 0;
3213 c
->redraw_scrollbars
= 0;
3214 c
->flags
&= ~(CLIENT_REDRAWPANES
|CLIENT_REDRAWSCROLLBARS
);
3217 if (c
->flags
& CLIENT_ALLREDRAWFLAGS
) {
3218 if (options_get_number(s
->options
, "set-titles")) {
3219 server_client_set_title(c
);
3220 server_client_set_path(c
);
3222 screen_redraw_screen(c
);
3225 tty
->flags
= (tty
->flags
& ~TTY_NOCURSOR
)|(tty_flags
& TTY_NOCURSOR
);
3226 tty_update_mode(tty
, mode
, NULL
);
3227 tty
->flags
= (tty
->flags
& ~(TTY_BLOCK
|TTY_FREEZE
|TTY_NOCURSOR
))|
3230 c
->flags
&= ~(CLIENT_ALLREDRAWFLAGS
|CLIENT_STATUSFORCE
);
3234 * We would have deferred the redraw unless the output buffer
3235 * was empty, so we can record how many bytes the redraw
3238 c
->redraw
= EVBUFFER_LENGTH(tty
->out
);
3239 log_debug("%s: redraw added %zu bytes", c
->name
, c
->redraw
);
3243 /* Set client title. */
3245 server_client_set_title(struct client
*c
)
3247 struct session
*s
= c
->session
;
3248 const char *template;
3250 struct format_tree
*ft
;
3252 template = options_get_string(s
->options
, "set-titles-string");
3254 ft
= format_create(c
, NULL
, FORMAT_NONE
, 0);
3255 format_defaults(ft
, c
, NULL
, NULL
, NULL
);
3257 title
= format_expand_time(ft
, template);
3258 if (c
->title
== NULL
|| strcmp(title
, c
->title
) != 0) {
3260 c
->title
= xstrdup(title
);
3261 tty_set_title(&c
->tty
, c
->title
);
3268 /* Set client path. */
3270 server_client_set_path(struct client
*c
)
3272 struct session
*s
= c
->session
;
3275 if (s
->curw
== NULL
)
3277 if (s
->curw
->window
->active
->base
.path
== NULL
)
3280 path
= s
->curw
->window
->active
->base
.path
;
3281 if (c
->path
== NULL
|| strcmp(path
, c
->path
) != 0) {
3283 c
->path
= xstrdup(path
);
3284 tty_set_path(&c
->tty
, c
->path
);
3288 /* Dispatch message from client. */
3290 server_client_dispatch(struct imsg
*imsg
, void *arg
)
3292 struct client
*c
= arg
;
3296 if (c
->flags
& CLIENT_DEAD
)
3300 server_client_lost(c
);
3304 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
3306 switch (imsg
->hdr
.type
) {
3307 case MSG_IDENTIFY_CLIENTPID
:
3308 case MSG_IDENTIFY_CWD
:
3309 case MSG_IDENTIFY_ENVIRON
:
3310 case MSG_IDENTIFY_FEATURES
:
3311 case MSG_IDENTIFY_FLAGS
:
3312 case MSG_IDENTIFY_LONGFLAGS
:
3313 case MSG_IDENTIFY_STDIN
:
3314 case MSG_IDENTIFY_STDOUT
:
3315 case MSG_IDENTIFY_TERM
:
3316 case MSG_IDENTIFY_TERMINFO
:
3317 case MSG_IDENTIFY_TTYNAME
:
3318 case MSG_IDENTIFY_DONE
:
3319 server_client_dispatch_identify(c
, imsg
);
3322 server_client_dispatch_command(c
, imsg
);
3326 fatalx("bad MSG_RESIZE size");
3328 if (c
->flags
& CLIENT_CONTROL
)
3330 server_client_update_latest(c
);
3331 tty_resize(&c
->tty
);
3332 tty_repeat_requests(&c
->tty
);
3333 recalculate_sizes();
3334 if (c
->overlay_resize
== NULL
)
3335 server_client_clear_overlay(c
);
3337 c
->overlay_resize(c
, c
->overlay_data
);
3338 server_redraw_client(c
);
3339 if (c
->session
!= NULL
)
3340 notify_client("client-resized", c
);
3344 fatalx("bad MSG_EXITING size");
3345 server_client_set_session(c
, NULL
);
3346 recalculate_sizes();
3348 proc_send(c
->peer
, MSG_EXITED
, -1, NULL
, 0);
3353 fatalx("bad MSG_WAKEUP size");
3355 if (!(c
->flags
& CLIENT_SUSPENDED
))
3357 c
->flags
&= ~CLIENT_SUSPENDED
;
3359 if (c
->fd
== -1 || c
->session
== NULL
) /* exited already */
3363 if (gettimeofday(&c
->activity_time
, NULL
) != 0)
3364 fatal("gettimeofday failed");
3366 tty_start_tty(&c
->tty
);
3367 server_redraw_client(c
);
3368 recalculate_sizes();
3371 session_update_activity(s
, &c
->activity_time
);
3375 fatalx("bad MSG_SHELL size");
3377 server_client_dispatch_shell(c
);
3379 case MSG_WRITE_READY
:
3380 file_write_ready(&c
->files
, imsg
);
3383 file_read_data(&c
->files
, imsg
);
3386 file_read_done(&c
->files
, imsg
);
3391 /* Callback when command is not allowed. */
3392 static enum cmd_retval
3393 server_client_read_only(struct cmdq_item
*item
, __unused
void *data
)
3395 cmdq_error(item
, "client is read-only");
3396 return (CMD_RETURN_ERROR
);
3399 /* Callback when command is done. */
3400 static enum cmd_retval
3401 server_client_command_done(struct cmdq_item
*item
, __unused
void *data
)
3403 struct client
*c
= cmdq_get_client(item
);
3405 if (~c
->flags
& CLIENT_ATTACHED
)
3406 c
->flags
|= CLIENT_EXIT
;
3407 else if (~c
->flags
& CLIENT_EXIT
) {
3408 if (c
->flags
& CLIENT_CONTROL
)
3410 tty_send_requests(&c
->tty
);
3412 return (CMD_RETURN_NORMAL
);
3415 /* Handle command message. */
3417 server_client_dispatch_command(struct client
*c
, struct imsg
*imsg
)
3419 struct msg_command data
;
3423 char **argv
, *cause
;
3424 struct cmd_parse_result
*pr
;
3425 struct args_value
*values
;
3426 struct cmdq_item
*new_item
;
3428 if (c
->flags
& CLIENT_EXIT
)
3431 if (imsg
->hdr
.len
- IMSG_HEADER_SIZE
< sizeof data
)
3432 fatalx("bad MSG_COMMAND size");
3433 memcpy(&data
, imsg
->data
, sizeof data
);
3435 buf
= (char *)imsg
->data
+ sizeof data
;
3436 len
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
- sizeof data
;
3437 if (len
> 0 && buf
[len
- 1] != '\0')
3438 fatalx("bad MSG_COMMAND string");
3441 if (cmd_unpack_argv(buf
, len
, argc
, &argv
) != 0) {
3442 cause
= xstrdup("command too long");
3448 argv
= xcalloc(1, sizeof *argv
);
3449 *argv
= xstrdup("new-session");
3452 values
= args_from_vector(argc
, argv
);
3453 pr
= cmd_parse_from_arguments(values
, argc
, NULL
);
3454 switch (pr
->status
) {
3455 case CMD_PARSE_ERROR
:
3458 case CMD_PARSE_SUCCESS
:
3461 args_free_values(values
, argc
);
3463 cmd_free_argv(argc
, argv
);
3465 if ((c
->flags
& CLIENT_READONLY
) &&
3466 !cmd_list_all_have(pr
->cmdlist
, CMD_READONLY
))
3467 new_item
= cmdq_get_callback(server_client_read_only
, NULL
);
3469 new_item
= cmdq_get_command(pr
->cmdlist
, NULL
);
3470 cmdq_append(c
, new_item
);
3471 cmdq_append(c
, cmdq_get_callback(server_client_command_done
, NULL
));
3473 cmd_list_free(pr
->cmdlist
);
3477 cmd_free_argv(argc
, argv
);
3479 cmdq_append(c
, cmdq_get_error(cause
));
3482 c
->flags
|= CLIENT_EXIT
;
3485 /* Handle identify message. */
3487 server_client_dispatch_identify(struct client
*c
, struct imsg
*imsg
)
3489 const char *data
, *home
;
3495 if (c
->flags
& CLIENT_IDENTIFIED
)
3496 fatalx("out-of-order identify message");
3499 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
3501 switch (imsg
->hdr
.type
) {
3502 case MSG_IDENTIFY_FEATURES
:
3503 if (datalen
!= sizeof feat
)
3504 fatalx("bad MSG_IDENTIFY_FEATURES size");
3505 memcpy(&feat
, data
, sizeof feat
);
3506 c
->term_features
|= feat
;
3507 log_debug("client %p IDENTIFY_FEATURES %s", c
,
3508 tty_get_features(feat
));
3510 case MSG_IDENTIFY_FLAGS
:
3511 if (datalen
!= sizeof flags
)
3512 fatalx("bad MSG_IDENTIFY_FLAGS size");
3513 memcpy(&flags
, data
, sizeof flags
);
3515 log_debug("client %p IDENTIFY_FLAGS %#x", c
, flags
);
3517 case MSG_IDENTIFY_LONGFLAGS
:
3518 if (datalen
!= sizeof longflags
)
3519 fatalx("bad MSG_IDENTIFY_LONGFLAGS size");
3520 memcpy(&longflags
, data
, sizeof longflags
);
3521 c
->flags
|= longflags
;
3522 log_debug("client %p IDENTIFY_LONGFLAGS %#llx", c
,
3523 (unsigned long long)longflags
);
3525 case MSG_IDENTIFY_TERM
:
3526 if (datalen
== 0 || data
[datalen
- 1] != '\0')
3527 fatalx("bad MSG_IDENTIFY_TERM string");
3529 c
->term_name
= xstrdup("unknown");
3531 c
->term_name
= xstrdup(data
);
3532 log_debug("client %p IDENTIFY_TERM %s", c
, data
);
3534 case MSG_IDENTIFY_TERMINFO
:
3535 if (datalen
== 0 || data
[datalen
- 1] != '\0')
3536 fatalx("bad MSG_IDENTIFY_TERMINFO string");
3537 c
->term_caps
= xreallocarray(c
->term_caps
, c
->term_ncaps
+ 1,
3538 sizeof *c
->term_caps
);
3539 c
->term_caps
[c
->term_ncaps
++] = xstrdup(data
);
3540 log_debug("client %p IDENTIFY_TERMINFO %s", c
, data
);
3542 case MSG_IDENTIFY_TTYNAME
:
3543 if (datalen
== 0 || data
[datalen
- 1] != '\0')
3544 fatalx("bad MSG_IDENTIFY_TTYNAME string");
3545 c
->ttyname
= xstrdup(data
);
3546 log_debug("client %p IDENTIFY_TTYNAME %s", c
, data
);
3548 case MSG_IDENTIFY_CWD
:
3549 if (datalen
== 0 || data
[datalen
- 1] != '\0')
3550 fatalx("bad MSG_IDENTIFY_CWD string");
3551 if (access(data
, X_OK
) == 0)
3552 c
->cwd
= xstrdup(data
);
3553 else if ((home
= find_home()) != NULL
)
3554 c
->cwd
= xstrdup(home
);
3556 c
->cwd
= xstrdup("/");
3557 log_debug("client %p IDENTIFY_CWD %s", c
, data
);
3559 case MSG_IDENTIFY_STDIN
:
3561 fatalx("bad MSG_IDENTIFY_STDIN size");
3562 c
->fd
= imsg_get_fd(imsg
);
3563 log_debug("client %p IDENTIFY_STDIN %d", c
, c
->fd
);
3565 case MSG_IDENTIFY_STDOUT
:
3567 fatalx("bad MSG_IDENTIFY_STDOUT size");
3568 c
->out_fd
= imsg_get_fd(imsg
);
3569 log_debug("client %p IDENTIFY_STDOUT %d", c
, c
->out_fd
);
3571 case MSG_IDENTIFY_ENVIRON
:
3572 if (datalen
== 0 || data
[datalen
- 1] != '\0')
3573 fatalx("bad MSG_IDENTIFY_ENVIRON string");
3574 if (strchr(data
, '=') != NULL
)
3575 environ_put(c
->environ
, data
, 0);
3576 log_debug("client %p IDENTIFY_ENVIRON %s", c
, data
);
3578 case MSG_IDENTIFY_CLIENTPID
:
3579 if (datalen
!= sizeof c
->pid
)
3580 fatalx("bad MSG_IDENTIFY_CLIENTPID size");
3581 memcpy(&c
->pid
, data
, sizeof c
->pid
);
3582 log_debug("client %p IDENTIFY_CLIENTPID %ld", c
, (long)c
->pid
);
3588 if (imsg
->hdr
.type
!= MSG_IDENTIFY_DONE
)
3590 c
->flags
|= CLIENT_IDENTIFIED
;
3592 if (*c
->ttyname
!= '\0')
3593 name
= xstrdup(c
->ttyname
);
3595 xasprintf(&name
, "client-%ld", (long)c
->pid
);
3597 log_debug("client %p name is %s", c
, c
->name
);
3600 c
->fd
= open(c
->ttyname
, O_RDWR
|O_NOCTTY
);
3601 c
->out_fd
= dup(c
->fd
);
3604 if (c
->flags
& CLIENT_CONTROL
)
3606 else if (c
->fd
!= -1) {
3607 if (tty_init(&c
->tty
, c
) != 0) {
3611 tty_resize(&c
->tty
);
3612 c
->flags
|= CLIENT_TERMINAL
;
3619 * If this is the first client, load configuration files. Any later
3620 * clients are allowed to continue with their command even if the
3621 * config has not been loaded - they might have been run from inside it
3623 if ((~c
->flags
& CLIENT_EXIT
) &&
3625 c
== TAILQ_FIRST(&clients
))
3629 /* Handle shell message. */
3631 server_client_dispatch_shell(struct client
*c
)
3635 shell
= options_get_string(global_s_options
, "default-shell");
3636 if (!checkshell(shell
))
3637 shell
= _PATH_BSHELL
;
3638 proc_send(c
->peer
, MSG_SHELL
, -1, shell
, strlen(shell
) + 1);
3640 proc_kill_peer(c
->peer
);
3643 /* Get client working directory. */
3645 server_client_get_cwd(struct client
*c
, struct session
*s
)
3649 if (!cfg_finished
&& cfg_client
!= NULL
)
3650 return (cfg_client
->cwd
);
3651 if (c
!= NULL
&& c
->session
== NULL
&& c
->cwd
!= NULL
)
3653 if (s
!= NULL
&& s
->cwd
!= NULL
)
3655 if (c
!= NULL
&& (s
= c
->session
) != NULL
&& s
->cwd
!= NULL
)
3657 if ((home
= find_home()) != NULL
)
3662 /* Get control client flags. */
3664 server_client_control_flags(struct client
*c
, const char *next
)
3666 if (strcmp(next
, "pause-after") == 0) {
3668 return (CLIENT_CONTROL_PAUSEAFTER
);
3670 if (sscanf(next
, "pause-after=%u", &c
->pause_age
) == 1) {
3671 c
->pause_age
*= 1000;
3672 return (CLIENT_CONTROL_PAUSEAFTER
);
3674 if (strcmp(next
, "no-output") == 0)
3675 return (CLIENT_CONTROL_NOOUTPUT
);
3676 if (strcmp(next
, "wait-exit") == 0)
3677 return (CLIENT_CONTROL_WAITEXIT
);
3681 /* Set client flags. */
3683 server_client_set_flags(struct client
*c
, const char *flags
)
3685 char *s
, *copy
, *next
;
3689 s
= copy
= xstrdup(flags
);
3690 while ((next
= strsep(&s
, ",")) != NULL
) {
3691 not = (*next
== '!');
3695 if (c
->flags
& CLIENT_CONTROL
)
3696 flag
= server_client_control_flags(c
, next
);
3699 if (strcmp(next
, "read-only") == 0)
3700 flag
= CLIENT_READONLY
;
3701 else if (strcmp(next
, "ignore-size") == 0)
3702 flag
= CLIENT_IGNORESIZE
;
3703 else if (strcmp(next
, "active-pane") == 0)
3704 flag
= CLIENT_ACTIVEPANE
;
3705 else if (strcmp(next
, "no-detach-on-destroy") == 0)
3706 flag
= CLIENT_NO_DETACH_ON_DESTROY
;
3710 log_debug("client %s set flag %s", c
->name
, next
);
3712 if (c
->flags
& CLIENT_READONLY
)
3713 flag
&= ~CLIENT_READONLY
;
3717 if (flag
== CLIENT_CONTROL_NOOUTPUT
)
3718 control_reset_offsets(c
);
3721 proc_send(c
->peer
, MSG_FLAGS
, -1, &c
->flags
, sizeof c
->flags
);
3724 /* Get client flags. This is only flags useful to show to users. */
3726 server_client_get_flags(struct client
*c
)
3732 if (c
->flags
& CLIENT_ATTACHED
)
3733 strlcat(s
, "attached,", sizeof s
);
3734 if (c
->flags
& CLIENT_FOCUSED
)
3735 strlcat(s
, "focused,", sizeof s
);
3736 if (c
->flags
& CLIENT_CONTROL
)
3737 strlcat(s
, "control-mode,", sizeof s
);
3738 if (c
->flags
& CLIENT_IGNORESIZE
)
3739 strlcat(s
, "ignore-size,", sizeof s
);
3740 if (c
->flags
& CLIENT_NO_DETACH_ON_DESTROY
)
3741 strlcat(s
, "no-detach-on-destroy,", sizeof s
);
3742 if (c
->flags
& CLIENT_CONTROL_NOOUTPUT
)
3743 strlcat(s
, "no-output,", sizeof s
);
3744 if (c
->flags
& CLIENT_CONTROL_WAITEXIT
)
3745 strlcat(s
, "wait-exit,", sizeof s
);
3746 if (c
->flags
& CLIENT_CONTROL_PAUSEAFTER
) {
3747 xsnprintf(tmp
, sizeof tmp
, "pause-after=%u,",
3748 c
->pause_age
/ 1000);
3749 strlcat(s
, tmp
, sizeof s
);
3751 if (c
->flags
& CLIENT_READONLY
)
3752 strlcat(s
, "read-only,", sizeof s
);
3753 if (c
->flags
& CLIENT_ACTIVEPANE
)
3754 strlcat(s
, "active-pane,", sizeof s
);
3755 if (c
->flags
& CLIENT_SUSPENDED
)
3756 strlcat(s
, "suspended,", sizeof s
);
3757 if (c
->flags
& CLIENT_UTF8
)
3758 strlcat(s
, "UTF-8,", sizeof s
);
3760 s
[strlen(s
) - 1] = '\0';
3764 /* Get client window. */
3765 struct client_window
*
3766 server_client_get_client_window(struct client
*c
, u_int id
)
3768 struct client_window cw
= { .window
= id
};
3770 return (RB_FIND(client_windows
, &c
->windows
, &cw
));
3773 /* Add client window. */
3774 struct client_window
*
3775 server_client_add_client_window(struct client
*c
, u_int id
)
3777 struct client_window
*cw
;
3779 cw
= server_client_get_client_window(c
, id
);
3781 cw
= xcalloc(1, sizeof *cw
);
3783 RB_INSERT(client_windows
, &c
->windows
, cw
);
3788 /* Get client active pane. */
3789 struct window_pane
*
3790 server_client_get_pane(struct client
*c
)
3792 struct session
*s
= c
->session
;
3793 struct client_window
*cw
;
3798 if (~c
->flags
& CLIENT_ACTIVEPANE
)
3799 return (s
->curw
->window
->active
);
3800 cw
= server_client_get_client_window(c
, s
->curw
->window
->id
);
3802 return (s
->curw
->window
->active
);
3806 /* Set client active pane. */
3808 server_client_set_pane(struct client
*c
, struct window_pane
*wp
)
3810 struct session
*s
= c
->session
;
3811 struct client_window
*cw
;
3816 cw
= server_client_add_client_window(c
, s
->curw
->window
->id
);
3818 log_debug("%s pane now %%%u", c
->name
, wp
->id
);
3821 /* Remove pane from client lists. */
3823 server_client_remove_pane(struct window_pane
*wp
)
3826 struct window
*w
= wp
->window
;
3827 struct client_window
*cw
;
3829 TAILQ_FOREACH(c
, &clients
, entry
) {
3830 cw
= server_client_get_client_window(c
, w
->id
);
3831 if (cw
!= NULL
&& cw
->pane
== wp
) {
3832 RB_REMOVE(client_windows
, &c
->windows
, cw
);
3838 /* Print to a client. */
3840 server_client_print(struct client
*c
, int parse
, struct evbuffer
*evb
)
3842 void *data
= EVBUFFER_DATA(evb
);
3843 size_t size
= EVBUFFER_LENGTH(evb
);
3844 struct window_pane
*wp
;
3845 struct window_mode_entry
*wme
;
3846 char *sanitized
, *msg
, *line
;
3849 utf8_stravisx(&msg
, data
, size
,
3850 VIS_OCTAL
|VIS_CSTYLE
|VIS_NOSLASH
);
3851 log_debug("%s: %s", __func__
, msg
);
3853 msg
= EVBUFFER_DATA(evb
);
3854 if (msg
[size
- 1] != '\0')
3855 evbuffer_add(evb
, "", 1);
3861 if (c
->session
== NULL
|| (c
->flags
& CLIENT_CONTROL
)) {
3862 if (~c
->flags
& CLIENT_UTF8
) {
3863 sanitized
= utf8_sanitize(msg
);
3864 if (c
->flags
& CLIENT_CONTROL
)
3865 control_write(c
, "%s", sanitized
);
3867 file_print(c
, "%s\n", sanitized
);
3870 if (c
->flags
& CLIENT_CONTROL
)
3871 control_write(c
, "%s", msg
);
3873 file_print(c
, "%s\n", msg
);
3878 wp
= server_client_get_pane(c
);
3879 wme
= TAILQ_FIRST(&wp
->modes
);
3880 if (wme
== NULL
|| wme
->mode
!= &window_view_mode
)
3881 window_pane_set_mode(wp
, NULL
, &window_view_mode
, NULL
, NULL
);
3884 line
= evbuffer_readln(evb
, NULL
, EVBUFFER_EOL_LF
);
3886 window_copy_add(wp
, 1, "%s", line
);
3889 } while (line
!= NULL
);
3891 size
= EVBUFFER_LENGTH(evb
);
3893 line
= EVBUFFER_DATA(evb
);
3894 window_copy_add(wp
, 1, "%.*s", (int)size
, line
);
3897 window_copy_add(wp
, 0, "%s", msg
);