1 /* $OpenBSD$ */ 2 3 /* 4 * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com> 5 * 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. 9 * 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. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/ioctl.h> 21 #include <sys/uio.h> 22 23 #include <errno.h> 24 #include <fcntl.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <time.h> 28 #include <unistd.h> 29 30 #include "tmux.h" 31 32 static void server_client_free(int, short, void *); 33 static void server_client_check_pane_resize(struct window_pane *); 34 static void server_client_check_pane_buffer(struct window_pane *); 35 static void server_client_check_window_resize(struct window *); 36 static key_code server_client_check_mouse(struct client *, struct key_event *); 37 static void server_client_repeat_timer(int, short, void *); 38 static void server_client_click_timer(int, short, void *); 39 static void server_client_check_exit(struct client *); 40 static void server_client_check_redraw(struct client *); 41 static void server_client_check_modes(struct client *); 42 static void server_client_set_title(struct client *); 43 static void server_client_set_path(struct client *); 44 static void server_client_reset_state(struct client *); 45 static int server_client_is_bracket_pasting(struct client *, key_code); 46 static int server_client_assume_paste(struct session *); 47 static void server_client_update_latest(struct client *); 48 49 static void server_client_dispatch(struct imsg *, void *); 50 static void server_client_dispatch_command(struct client *, struct imsg *); 51 static void server_client_dispatch_identify(struct client *, struct imsg *); 52 static void server_client_dispatch_shell(struct client *); 53 54 /* Compare client windows. */ 55 static int 56 server_client_window_cmp(struct client_window *cw1, 57 struct client_window *cw2) 58 { 59 if (cw1->window < cw2->window) 60 return (-1); 61 if (cw1->window > cw2->window) 62 return (1); 63 return (0); 64 } 65 RB_GENERATE(client_windows, client_window, entry, server_client_window_cmp); 66 67 /* Number of attached clients. */ 68 u_int 69 server_client_how_many(void) 70 { 71 struct client *c; 72 u_int n; 73 74 n = 0; 75 TAILQ_FOREACH(c, &clients, entry) { 76 if (c->session != NULL && (~c->flags & CLIENT_UNATTACHEDFLAGS)) 77 n++; 78 } 79 return (n); 80 } 81 82 /* Overlay timer callback. */ 83 static void 84 server_client_overlay_timer(__unused int fd, __unused short events, void *data) 85 { 86 server_client_clear_overlay(data); 87 } 88 89 /* Set an overlay on client. */ 90 void 91 server_client_set_overlay(struct client *c, u_int delay, 92 overlay_check_cb checkcb, overlay_mode_cb modecb, 93 overlay_draw_cb drawcb, overlay_key_cb keycb, overlay_free_cb freecb, 94 overlay_resize_cb resizecb, void *data) 95 { 96 struct timeval tv; 97 98 if (c->overlay_draw != NULL) 99 server_client_clear_overlay(c); 100 101 tv.tv_sec = delay / 1000; 102 tv.tv_usec = (delay % 1000) * 1000L; 103 104 if (event_initialized(&c->overlay_timer)) 105 evtimer_del(&c->overlay_timer); 106 evtimer_set(&c->overlay_timer, server_client_overlay_timer, c); 107 if (delay != 0) 108 evtimer_add(&c->overlay_timer, &tv); 109 110 c->overlay_check = checkcb; 111 c->overlay_mode = modecb; 112 c->overlay_draw = drawcb; 113 c->overlay_key = keycb; 114 c->overlay_free = freecb; 115 c->overlay_resize = resizecb; 116 c->overlay_data = data; 117 118 if (c->overlay_check == NULL) 119 c->tty.flags |= TTY_FREEZE; 120 if (c->overlay_mode == NULL) 121 c->tty.flags |= TTY_NOCURSOR; 122 server_redraw_client(c); 123 } 124 125 /* Clear overlay mode on client. */ 126 void 127 server_client_clear_overlay(struct client *c) 128 { 129 if (c->overlay_draw == NULL) 130 return; 131 132 if (event_initialized(&c->overlay_timer)) 133 evtimer_del(&c->overlay_timer); 134 135 if (c->overlay_free != NULL) 136 c->overlay_free(c, c->overlay_data); 137 138 c->overlay_check = NULL; 139 c->overlay_mode = NULL; 140 c->overlay_draw = NULL; 141 c->overlay_key = NULL; 142 c->overlay_free = NULL; 143 c->overlay_data = NULL; 144 145 c->tty.flags &= ~(TTY_FREEZE|TTY_NOCURSOR); 146 server_redraw_client(c); 147 } 148 149 /* 150 * Given overlay position and dimensions, return parts of the input range which 151 * are visible. 152 */ 153 void 154 server_client_overlay_range(u_int x, u_int y, u_int sx, u_int sy, u_int px, 155 u_int py, u_int nx, struct overlay_ranges *r) 156 { 157 u_int ox, onx; 158 159 /* Return up to 2 ranges. */ 160 r->px[2] = 0; 161 r->nx[2] = 0; 162 163 /* Trivial case of no overlap in the y direction. */ 164 if (py < y || py > y + sy - 1) { 165 r->px[0] = px; 166 r->nx[0] = nx; 167 r->px[1] = 0; 168 r->nx[1] = 0; 169 return; 170 } 171 172 /* Visible bit to the left of the popup. */ 173 if (px < x) { 174 r->px[0] = px; 175 r->nx[0] = x - px; 176 if (r->nx[0] > nx) 177 r->nx[0] = nx; 178 } else { 179 r->px[0] = 0; 180 r->nx[0] = 0; 181 } 182 183 /* Visible bit to the right of the popup. */ 184 ox = x + sx; 185 if (px > ox) 186 ox = px; 187 onx = px + nx; 188 if (onx > ox) { 189 r->px[1] = ox; 190 r->nx[1] = onx - ox; 191 } else { 192 r->px[1] = 0; 193 r->nx[1] = 0; 194 } 195 } 196 197 /* Check if this client is inside this server. */ 198 int 199 server_client_check_nested(struct client *c) 200 { 201 struct environ_entry *envent; 202 struct window_pane *wp; 203 204 envent = environ_find(c->environ, "TMUX"); 205 if (envent == NULL || *envent->value == '\0') 206 return (0); 207 208 RB_FOREACH(wp, window_pane_tree, &all_window_panes) { 209 if (strcmp(wp->tty, c->ttyname) == 0) 210 return (1); 211 } 212 return (0); 213 } 214 215 /* Set client key table. */ 216 void 217 server_client_set_key_table(struct client *c, const char *name) 218 { 219 if (name == NULL) 220 name = server_client_get_key_table(c); 221 222 key_bindings_unref_table(c->keytable); 223 c->keytable = key_bindings_get_table(name, 1); 224 c->keytable->references++; 225 if (gettimeofday(&c->keytable->activity_time, NULL) != 0) 226 fatal("gettimeofday failed"); 227 } 228 229 static uint64_t 230 server_client_key_table_activity_diff(struct client *c) 231 { 232 struct timeval diff; 233 234 timersub(&c->activity_time, &c->keytable->activity_time, &diff); 235 return ((diff.tv_sec * 1000ULL) + (diff.tv_usec / 1000ULL)); 236 } 237 238 /* Get default key table. */ 239 const char * 240 server_client_get_key_table(struct client *c) 241 { 242 struct session *s = c->session; 243 const char *name; 244 245 if (s == NULL) 246 return ("root"); 247 248 name = options_get_string(s->options, "key-table"); 249 if (*name == '\0') 250 return ("root"); 251 return (name); 252 } 253 254 /* Is this table the default key table? */ 255 static int 256 server_client_is_default_key_table(struct client *c, struct key_table *table) 257 { 258 return (strcmp(table->name, server_client_get_key_table(c)) == 0); 259 } 260 261 /* Create a new client. */ 262 struct client * 263 server_client_create(int fd) 264 { 265 struct client *c; 266 267 setblocking(fd, 0); 268 269 c = xcalloc(1, sizeof *c); 270 c->references = 1; 271 c->peer = proc_add_peer(server_proc, fd, server_client_dispatch, c); 272 273 if (gettimeofday(&c->creation_time, NULL) != 0) 274 fatal("gettimeofday failed"); 275 memcpy(&c->activity_time, &c->creation_time, sizeof c->activity_time); 276 277 c->environ = environ_create(); 278 279 c->fd = -1; 280 c->out_fd = -1; 281 282 c->queue = cmdq_new(); 283 RB_INIT(&c->windows); 284 RB_INIT(&c->files); 285 286 c->tty.sx = 80; 287 c->tty.sy = 24; 288 289 status_init(c); 290 c->flags |= CLIENT_FOCUSED; 291 292 c->keytable = key_bindings_get_table("root", 1); 293 c->keytable->references++; 294 295 evtimer_set(&c->repeat_timer, server_client_repeat_timer, c); 296 evtimer_set(&c->click_timer, server_client_click_timer, c); 297 298 TAILQ_INSERT_TAIL(&clients, c, entry); 299 log_debug("new client %p", c); 300 return (c); 301 } 302 303 /* Open client terminal if needed. */ 304 int 305 server_client_open(struct client *c, char **cause) 306 { 307 const char *ttynam = _PATH_TTY; 308 309 if (c->flags & CLIENT_CONTROL) 310 return (0); 311 312 if (strcmp(c->ttyname, ttynam) == 0|| 313 ((isatty(STDIN_FILENO) && 314 (ttynam = ttyname(STDIN_FILENO)) != NULL && 315 strcmp(c->ttyname, ttynam) == 0) || 316 (isatty(STDOUT_FILENO) && 317 (ttynam = ttyname(STDOUT_FILENO)) != NULL && 318 strcmp(c->ttyname, ttynam) == 0) || 319 (isatty(STDERR_FILENO) && 320 (ttynam = ttyname(STDERR_FILENO)) != NULL && 321 strcmp(c->ttyname, ttynam) == 0))) { 322 xasprintf(cause, "can't use %s", c->ttyname); 323 return (-1); 324 } 325 326 if (!(c->flags & CLIENT_TERMINAL)) { 327 *cause = xstrdup("not a terminal"); 328 return (-1); 329 } 330 331 if (tty_open(&c->tty, cause) != 0) 332 return (-1); 333 334 return (0); 335 } 336 337 /* Lost an attached client. */ 338 static void 339 server_client_attached_lost(struct client *c) 340 { 341 struct session *s; 342 struct window *w; 343 struct client *loop; 344 struct client *found; 345 346 log_debug("lost attached client %p", c); 347 348 /* 349 * By this point the session in the client has been cleared so walk all 350 * windows to find any with this client as the latest. 351 */ 352 RB_FOREACH(w, windows, &windows) { 353 if (w->latest != c) 354 continue; 355 356 found = NULL; 357 TAILQ_FOREACH(loop, &clients, entry) { 358 s = loop->session; 359 if (loop == c || s == NULL || s->curw->window != w) 360 continue; 361 if (found == NULL || timercmp(&loop->activity_time, 362 &found->activity_time, >)) 363 found = loop; 364 } 365 if (found != NULL) 366 server_client_update_latest(found); 367 } 368 } 369 370 /* Set client session. */ 371 void 372 server_client_set_session(struct client *c, struct session *s) 373 { 374 struct session *old = c->session; 375 376 if (s != NULL && c->session != NULL && c->session != s) 377 c->last_session = c->session; 378 else if (s == NULL) 379 c->last_session = NULL; 380 c->session = s; 381 c->flags |= CLIENT_FOCUSED; 382 383 if (old != NULL && old->curw != NULL) 384 window_update_focus(old->curw->window); 385 if (s != NULL) { 386 recalculate_sizes(); 387 window_update_focus(s->curw->window); 388 session_update_activity(s, NULL); 389 gettimeofday(&s->last_attached_time, NULL); 390 s->curw->flags &= ~WINLINK_ALERTFLAGS; 391 s->curw->window->latest = c; 392 alerts_check_session(s); 393 tty_update_client_offset(c); 394 status_timer_start(c); 395 notify_client("client-session-changed", c); 396 server_redraw_client(c); 397 } 398 399 server_check_unattached(); 400 server_update_socket(); 401 } 402 403 /* Lost a client. */ 404 void 405 server_client_lost(struct client *c) 406 { 407 struct client_file *cf, *cf1; 408 struct client_window *cw, *cw1; 409 410 c->flags |= CLIENT_DEAD; 411 412 server_client_clear_overlay(c); 413 status_prompt_clear(c); 414 status_message_clear(c); 415 416 RB_FOREACH_SAFE(cf, client_files, &c->files, cf1) { 417 cf->error = EINTR; 418 file_fire_done(cf); 419 } 420 RB_FOREACH_SAFE(cw, client_windows, &c->windows, cw1) { 421 RB_REMOVE(client_windows, &c->windows, cw); 422 free(cw); 423 } 424 425 TAILQ_REMOVE(&clients, c, entry); 426 log_debug("lost client %p", c); 427 428 if (c->flags & CLIENT_ATTACHED) { 429 server_client_attached_lost(c); 430 notify_client("client-detached", c); 431 } 432 433 if (c->flags & CLIENT_CONTROL) 434 control_stop(c); 435 if (c->flags & CLIENT_TERMINAL) 436 tty_free(&c->tty); 437 free(c->ttyname); 438 free(c->clipboard_panes); 439 440 free(c->term_name); 441 free(c->term_type); 442 tty_term_free_list(c->term_caps, c->term_ncaps); 443 444 status_free(c); 445 446 free(c->title); 447 free(__UNCONST(c->cwd)); 448 449 evtimer_del(&c->repeat_timer); 450 evtimer_del(&c->click_timer); 451 452 key_bindings_unref_table(c->keytable); 453 454 free(c->message_string); 455 if (event_initialized(&c->message_timer)) 456 evtimer_del(&c->message_timer); 457 458 free(c->prompt_saved); 459 free(c->prompt_string); 460 free(c->prompt_buffer); 461 462 format_lost_client(c); 463 environ_free(c->environ); 464 465 proc_remove_peer(c->peer); 466 c->peer = NULL; 467 468 if (c->out_fd != -1) 469 close(c->out_fd); 470 if (c->fd != -1) { 471 close(c->fd); 472 c->fd = -1; 473 } 474 server_client_unref(c); 475 476 server_add_accept(0); /* may be more file descriptors now */ 477 478 recalculate_sizes(); 479 server_check_unattached(); 480 server_update_socket(); 481 } 482 483 /* Remove reference from a client. */ 484 void 485 server_client_unref(struct client *c) 486 { 487 log_debug("unref client %p (%d references)", c, c->references); 488 489 c->references--; 490 if (c->references == 0) 491 event_once(-1, EV_TIMEOUT, server_client_free, c, NULL); 492 } 493 494 /* Free dead client. */ 495 static void 496 server_client_free(__unused int fd, __unused short events, void *arg) 497 { 498 struct client *c = arg; 499 500 log_debug("free client %p (%d references)", c, c->references); 501 502 cmdq_free(c->queue); 503 504 if (c->references == 0) { 505 free(__UNCONST(c->name)); 506 free(c); 507 } 508 } 509 510 /* Suspend a client. */ 511 void 512 server_client_suspend(struct client *c) 513 { 514 struct session *s = c->session; 515 516 if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS)) 517 return; 518 519 tty_stop_tty(&c->tty); 520 c->flags |= CLIENT_SUSPENDED; 521 proc_send(c->peer, MSG_SUSPEND, -1, NULL, 0); 522 } 523 524 /* Detach a client. */ 525 void 526 server_client_detach(struct client *c, enum msgtype msgtype) 527 { 528 struct session *s = c->session; 529 530 if (s == NULL || (c->flags & CLIENT_NODETACHFLAGS)) 531 return; 532 533 c->flags |= CLIENT_EXIT; 534 535 c->exit_type = CLIENT_EXIT_DETACH; 536 c->exit_msgtype = msgtype; 537 c->exit_session = xstrdup(s->name); 538 } 539 540 /* Execute command to replace a client. */ 541 void 542 server_client_exec(struct client *c, const char *cmd) 543 { 544 struct session *s = c->session; 545 char *msg; 546 const char *shell; 547 size_t cmdsize, shellsize; 548 549 if (*cmd == '\0') 550 return; 551 cmdsize = strlen(cmd) + 1; 552 553 if (s != NULL) 554 shell = options_get_string(s->options, "default-shell"); 555 else 556 shell = options_get_string(global_s_options, "default-shell"); 557 if (!checkshell(shell)) 558 shell = _PATH_BSHELL; 559 shellsize = strlen(shell) + 1; 560 561 msg = xmalloc(cmdsize + shellsize); 562 memcpy(msg, cmd, cmdsize); 563 memcpy(msg + cmdsize, shell, shellsize); 564 565 proc_send(c->peer, MSG_EXEC, -1, msg, cmdsize + shellsize); 566 free(msg); 567 } 568 569 /* Check for mouse keys. */ 570 static key_code 571 server_client_check_mouse(struct client *c, struct key_event *event) 572 { 573 struct mouse_event *m = &event->m; 574 struct session *s = c->session, *fs; 575 struct winlink *fwl; 576 struct window_pane *wp, *fwp; 577 u_int x, y, b, sx, sy, px, py; 578 int ignore = 0; 579 key_code key; 580 struct timeval tv; 581 struct style_range *sr; 582 enum { NOTYPE, 583 MOVE, 584 DOWN, 585 UP, 586 DRAG, 587 WHEEL, 588 SECOND, 589 DOUBLE, 590 TRIPLE } type = NOTYPE; 591 enum { NOWHERE, 592 PANE, 593 STATUS, 594 STATUS_LEFT, 595 STATUS_RIGHT, 596 STATUS_DEFAULT, 597 BORDER } where = NOWHERE; 598 599 log_debug("%s mouse %02x at %u,%u (last %u,%u) (%d)", c->name, m->b, 600 m->x, m->y, m->lx, m->ly, c->tty.mouse_drag_flag); 601 602 /* What type of event is this? */ 603 if (event->key == KEYC_DOUBLECLICK) { 604 type = DOUBLE; 605 x = m->x, y = m->y, b = m->b; 606 ignore = 1; 607 log_debug("double-click at %u,%u", x, y); 608 } else if ((m->sgr_type != ' ' && 609 MOUSE_DRAG(m->sgr_b) && 610 MOUSE_RELEASE(m->sgr_b)) || 611 (m->sgr_type == ' ' && 612 MOUSE_DRAG(m->b) && 613 MOUSE_RELEASE(m->b) && 614 MOUSE_RELEASE(m->lb))) { 615 type = MOVE; 616 x = m->x, y = m->y, b = 0; 617 log_debug("move at %u,%u", x, y); 618 } else if (MOUSE_DRAG(m->b)) { 619 type = DRAG; 620 if (c->tty.mouse_drag_flag) { 621 x = m->x, y = m->y, b = m->b; 622 if (x == m->lx && y == m->ly) 623 return (KEYC_UNKNOWN); 624 log_debug("drag update at %u,%u", x, y); 625 } else { 626 x = m->lx, y = m->ly, b = m->lb; 627 log_debug("drag start at %u,%u", x, y); 628 } 629 } else if (MOUSE_WHEEL(m->b)) { 630 type = WHEEL; 631 x = m->x, y = m->y, b = m->b; 632 log_debug("wheel at %u,%u", x, y); 633 } else if (MOUSE_RELEASE(m->b)) { 634 type = UP; 635 x = m->x, y = m->y, b = m->lb; 636 if (m->sgr_type == 'm') 637 b = m->sgr_b; 638 log_debug("up at %u,%u", x, y); 639 } else { 640 if (c->flags & CLIENT_DOUBLECLICK) { 641 evtimer_del(&c->click_timer); 642 c->flags &= ~CLIENT_DOUBLECLICK; 643 if (m->b == c->click_button) { 644 type = SECOND; 645 x = m->x, y = m->y, b = m->b; 646 log_debug("second-click at %u,%u", x, y); 647 c->flags |= CLIENT_TRIPLECLICK; 648 } 649 } else if (c->flags & CLIENT_TRIPLECLICK) { 650 evtimer_del(&c->click_timer); 651 c->flags &= ~CLIENT_TRIPLECLICK; 652 if (m->b == c->click_button) { 653 type = TRIPLE; 654 x = m->x, y = m->y, b = m->b; 655 log_debug("triple-click at %u,%u", x, y); 656 goto have_event; 657 } 658 } 659 660 /* DOWN is the only remaining event type. */ 661 if (type == NOTYPE) { 662 type = DOWN; 663 x = m->x, y = m->y, b = m->b; 664 log_debug("down at %u,%u", x, y); 665 c->flags |= CLIENT_DOUBLECLICK; 666 } 667 668 if (KEYC_CLICK_TIMEOUT != 0) { 669 memcpy(&c->click_event, m, sizeof c->click_event); 670 c->click_button = m->b; 671 672 log_debug("click timer started"); 673 tv.tv_sec = KEYC_CLICK_TIMEOUT / 1000; 674 tv.tv_usec = (KEYC_CLICK_TIMEOUT % 1000) * 1000L; 675 evtimer_del(&c->click_timer); 676 evtimer_add(&c->click_timer, &tv); 677 } 678 } 679 680 have_event: 681 if (type == NOTYPE) 682 return (KEYC_UNKNOWN); 683 684 /* Save the session. */ 685 m->s = s->id; 686 m->w = -1; 687 m->wp = -1; 688 m->ignore = ignore; 689 690 /* Is this on the status line? */ 691 m->statusat = status_at_line(c); 692 m->statuslines = status_line_size(c); 693 if (m->statusat != -1 && 694 y >= (u_int)m->statusat && 695 y < m->statusat + m->statuslines) { 696 sr = status_get_range(c, x, y - m->statusat); 697 if (sr == NULL) { 698 where = STATUS_DEFAULT; 699 } else { 700 switch (sr->type) { 701 case STYLE_RANGE_NONE: 702 return (KEYC_UNKNOWN); 703 case STYLE_RANGE_LEFT: 704 log_debug("mouse range: left"); 705 where = STATUS_LEFT; 706 break; 707 case STYLE_RANGE_RIGHT: 708 log_debug("mouse range: right"); 709 where = STATUS_RIGHT; 710 break; 711 case STYLE_RANGE_PANE: 712 fwp = window_pane_find_by_id(sr->argument); 713 if (fwp == NULL) 714 return (KEYC_UNKNOWN); 715 m->wp = sr->argument; 716 717 log_debug("mouse range: pane %%%u", m->wp); 718 where = STATUS; 719 break; 720 case STYLE_RANGE_WINDOW: 721 fwl = winlink_find_by_index(&s->windows, 722 sr->argument); 723 if (fwl == NULL) 724 return (KEYC_UNKNOWN); 725 m->w = fwl->window->id; 726 727 log_debug("mouse range: window @%u", m->w); 728 where = STATUS; 729 break; 730 case STYLE_RANGE_SESSION: 731 fs = session_find_by_id(sr->argument); 732 if (fs == NULL) 733 return (KEYC_UNKNOWN); 734 m->s = sr->argument; 735 736 log_debug("mouse range: session $%u", m->s); 737 where = STATUS; 738 break; 739 case STYLE_RANGE_USER: 740 where = STATUS; 741 break; 742 } 743 } 744 } 745 746 /* Not on status line. Adjust position and check for border or pane. */ 747 if (where == NOWHERE) { 748 px = x; 749 if (m->statusat == 0 && y >= m->statuslines) 750 py = y - m->statuslines; 751 else if (m->statusat > 0 && y >= (u_int)m->statusat) 752 py = m->statusat - 1; 753 else 754 py = y; 755 756 tty_window_offset(&c->tty, &m->ox, &m->oy, &sx, &sy); 757 log_debug("mouse window @%u at %u,%u (%ux%u)", 758 s->curw->window->id, m->ox, m->oy, sx, sy); 759 if (px > sx || py > sy) 760 return (KEYC_UNKNOWN); 761 px = px + m->ox; 762 py = py + m->oy; 763 764 /* Try the pane borders if not zoomed. */ 765 if (~s->curw->window->flags & WINDOW_ZOOMED) { 766 TAILQ_FOREACH(wp, &s->curw->window->panes, entry) { 767 if ((wp->xoff + wp->sx == px && 768 wp->yoff <= 1 + py && 769 wp->yoff + wp->sy >= py) || 770 (wp->yoff + wp->sy == py && 771 wp->xoff <= 1 + px && 772 wp->xoff + wp->sx >= px)) 773 break; 774 } 775 if (wp != NULL) 776 where = BORDER; 777 } 778 779 /* Otherwise try inside the pane. */ 780 if (where == NOWHERE) { 781 wp = window_get_active_at(s->curw->window, px, py); 782 if (wp != NULL) 783 where = PANE; 784 else 785 return (KEYC_UNKNOWN); 786 } 787 if (where == PANE) 788 log_debug("mouse %u,%u on pane %%%u", x, y, wp->id); 789 else if (where == BORDER) 790 log_debug("mouse on pane %%%u border", wp->id); 791 m->wp = wp->id; 792 m->w = wp->window->id; 793 } 794 795 /* Stop dragging if needed. */ 796 if (type != DRAG && type != WHEEL && c->tty.mouse_drag_flag != 0) { 797 if (c->tty.mouse_drag_release != NULL) 798 c->tty.mouse_drag_release(c, m); 799 800 c->tty.mouse_drag_update = NULL; 801 c->tty.mouse_drag_release = NULL; 802 803 /* 804 * End a mouse drag by passing a MouseDragEnd key corresponding 805 * to the button that started the drag. 806 */ 807 switch (c->tty.mouse_drag_flag - 1) { 808 case MOUSE_BUTTON_1: 809 if (where == PANE) 810 key = KEYC_MOUSEDRAGEND1_PANE; 811 if (where == STATUS) 812 key = KEYC_MOUSEDRAGEND1_STATUS; 813 if (where == STATUS_LEFT) 814 key = KEYC_MOUSEDRAGEND1_STATUS_LEFT; 815 if (where == STATUS_RIGHT) 816 key = KEYC_MOUSEDRAGEND1_STATUS_RIGHT; 817 if (where == STATUS_DEFAULT) 818 key = KEYC_MOUSEDRAGEND1_STATUS_DEFAULT; 819 if (where == BORDER) 820 key = KEYC_MOUSEDRAGEND1_BORDER; 821 break; 822 case MOUSE_BUTTON_2: 823 if (where == PANE) 824 key = KEYC_MOUSEDRAGEND2_PANE; 825 if (where == STATUS) 826 key = KEYC_MOUSEDRAGEND2_STATUS; 827 if (where == STATUS_LEFT) 828 key = KEYC_MOUSEDRAGEND2_STATUS_LEFT; 829 if (where == STATUS_RIGHT) 830 key = KEYC_MOUSEDRAGEND2_STATUS_RIGHT; 831 if (where == STATUS_DEFAULT) 832 key = KEYC_MOUSEDRAGEND2_STATUS_DEFAULT; 833 if (where == BORDER) 834 key = KEYC_MOUSEDRAGEND2_BORDER; 835 break; 836 case MOUSE_BUTTON_3: 837 if (where == PANE) 838 key = KEYC_MOUSEDRAGEND3_PANE; 839 if (where == STATUS) 840 key = KEYC_MOUSEDRAGEND3_STATUS; 841 if (where == STATUS_LEFT) 842 key = KEYC_MOUSEDRAGEND3_STATUS_LEFT; 843 if (where == STATUS_RIGHT) 844 key = KEYC_MOUSEDRAGEND3_STATUS_RIGHT; 845 if (where == STATUS_DEFAULT) 846 key = KEYC_MOUSEDRAGEND3_STATUS_DEFAULT; 847 if (where == BORDER) 848 key = KEYC_MOUSEDRAGEND3_BORDER; 849 break; 850 case MOUSE_BUTTON_6: 851 if (where == PANE) 852 key = KEYC_MOUSEDRAGEND6_PANE; 853 if (where == STATUS) 854 key = KEYC_MOUSEDRAGEND6_STATUS; 855 if (where == STATUS_LEFT) 856 key = KEYC_MOUSEDRAGEND6_STATUS_LEFT; 857 if (where == STATUS_RIGHT) 858 key = KEYC_MOUSEDRAGEND6_STATUS_RIGHT; 859 if (where == STATUS_DEFAULT) 860 key = KEYC_MOUSEDRAGEND6_STATUS_DEFAULT; 861 if (where == BORDER) 862 key = KEYC_MOUSEDRAGEND6_BORDER; 863 break; 864 case MOUSE_BUTTON_7: 865 if (where == PANE) 866 key = KEYC_MOUSEDRAGEND7_PANE; 867 if (where == STATUS) 868 key = KEYC_MOUSEDRAGEND7_STATUS; 869 if (where == STATUS_LEFT) 870 key = KEYC_MOUSEDRAGEND7_STATUS_LEFT; 871 if (where == STATUS_RIGHT) 872 key = KEYC_MOUSEDRAGEND7_STATUS_RIGHT; 873 if (where == STATUS_DEFAULT) 874 key = KEYC_MOUSEDRAGEND7_STATUS_DEFAULT; 875 if (where == BORDER) 876 key = KEYC_MOUSEDRAGEND7_BORDER; 877 break; 878 case MOUSE_BUTTON_8: 879 if (where == PANE) 880 key = KEYC_MOUSEDRAGEND8_PANE; 881 if (where == STATUS) 882 key = KEYC_MOUSEDRAGEND8_STATUS; 883 if (where == STATUS_LEFT) 884 key = KEYC_MOUSEDRAGEND8_STATUS_LEFT; 885 if (where == STATUS_RIGHT) 886 key = KEYC_MOUSEDRAGEND8_STATUS_RIGHT; 887 if (where == STATUS_DEFAULT) 888 key = KEYC_MOUSEDRAGEND8_STATUS_DEFAULT; 889 if (where == BORDER) 890 key = KEYC_MOUSEDRAGEND8_BORDER; 891 break; 892 case MOUSE_BUTTON_9: 893 if (where == PANE) 894 key = KEYC_MOUSEDRAGEND9_PANE; 895 if (where == STATUS) 896 key = KEYC_MOUSEDRAGEND9_STATUS; 897 if (where == STATUS_LEFT) 898 key = KEYC_MOUSEDRAGEND9_STATUS_LEFT; 899 if (where == STATUS_RIGHT) 900 key = KEYC_MOUSEDRAGEND9_STATUS_RIGHT; 901 if (where == STATUS_DEFAULT) 902 key = KEYC_MOUSEDRAGEND9_STATUS_DEFAULT; 903 if (where == BORDER) 904 key = KEYC_MOUSEDRAGEND9_BORDER; 905 break; 906 case MOUSE_BUTTON_10: 907 if (where == PANE) 908 key = KEYC_MOUSEDRAGEND10_PANE; 909 if (where == STATUS) 910 key = KEYC_MOUSEDRAGEND10_STATUS; 911 if (where == STATUS_LEFT) 912 key = KEYC_MOUSEDRAGEND10_STATUS_LEFT; 913 if (where == STATUS_RIGHT) 914 key = KEYC_MOUSEDRAGEND10_STATUS_RIGHT; 915 if (where == STATUS_DEFAULT) 916 key = KEYC_MOUSEDRAGEND10_STATUS_DEFAULT; 917 if (where == BORDER) 918 key = KEYC_MOUSEDRAGEND10_BORDER; 919 break; 920 case MOUSE_BUTTON_11: 921 if (where == PANE) 922 key = KEYC_MOUSEDRAGEND11_PANE; 923 if (where == STATUS) 924 key = KEYC_MOUSEDRAGEND11_STATUS; 925 if (where == STATUS_LEFT) 926 key = KEYC_MOUSEDRAGEND11_STATUS_LEFT; 927 if (where == STATUS_RIGHT) 928 key = KEYC_MOUSEDRAGEND11_STATUS_RIGHT; 929 if (where == STATUS_DEFAULT) 930 key = KEYC_MOUSEDRAGEND11_STATUS_DEFAULT; 931 if (where == BORDER) 932 key = KEYC_MOUSEDRAGEND11_BORDER; 933 break; 934 default: 935 key = KEYC_MOUSE; 936 break; 937 } 938 c->tty.mouse_drag_flag = 0; 939 goto out; 940 } 941 942 /* Convert to a key binding. */ 943 key = KEYC_UNKNOWN; 944 switch (type) { 945 case NOTYPE: 946 break; 947 case MOVE: 948 if (where == PANE) 949 key = KEYC_MOUSEMOVE_PANE; 950 if (where == STATUS) 951 key = KEYC_MOUSEMOVE_STATUS; 952 if (where == STATUS_LEFT) 953 key = KEYC_MOUSEMOVE_STATUS_LEFT; 954 if (where == STATUS_RIGHT) 955 key = KEYC_MOUSEMOVE_STATUS_RIGHT; 956 if (where == STATUS_DEFAULT) 957 key = KEYC_MOUSEMOVE_STATUS_DEFAULT; 958 if (where == BORDER) 959 key = KEYC_MOUSEMOVE_BORDER; 960 break; 961 case DRAG: 962 if (c->tty.mouse_drag_update != NULL) 963 key = KEYC_DRAGGING; 964 else { 965 switch (MOUSE_BUTTONS(b)) { 966 case MOUSE_BUTTON_1: 967 if (where == PANE) 968 key = KEYC_MOUSEDRAG1_PANE; 969 if (where == STATUS) 970 key = KEYC_MOUSEDRAG1_STATUS; 971 if (where == STATUS_LEFT) 972 key = KEYC_MOUSEDRAG1_STATUS_LEFT; 973 if (where == STATUS_RIGHT) 974 key = KEYC_MOUSEDRAG1_STATUS_RIGHT; 975 if (where == STATUS_DEFAULT) 976 key = KEYC_MOUSEDRAG1_STATUS_DEFAULT; 977 if (where == BORDER) 978 key = KEYC_MOUSEDRAG1_BORDER; 979 break; 980 case MOUSE_BUTTON_2: 981 if (where == PANE) 982 key = KEYC_MOUSEDRAG2_PANE; 983 if (where == STATUS) 984 key = KEYC_MOUSEDRAG2_STATUS; 985 if (where == STATUS_LEFT) 986 key = KEYC_MOUSEDRAG2_STATUS_LEFT; 987 if (where == STATUS_RIGHT) 988 key = KEYC_MOUSEDRAG2_STATUS_RIGHT; 989 if (where == STATUS_DEFAULT) 990 key = KEYC_MOUSEDRAG2_STATUS_DEFAULT; 991 if (where == BORDER) 992 key = KEYC_MOUSEDRAG2_BORDER; 993 break; 994 case MOUSE_BUTTON_3: 995 if (where == PANE) 996 key = KEYC_MOUSEDRAG3_PANE; 997 if (where == STATUS) 998 key = KEYC_MOUSEDRAG3_STATUS; 999 if (where == STATUS_LEFT) 1000 key = KEYC_MOUSEDRAG3_STATUS_LEFT; 1001 if (where == STATUS_RIGHT) 1002 key = KEYC_MOUSEDRAG3_STATUS_RIGHT; 1003 if (where == STATUS_DEFAULT) 1004 key = KEYC_MOUSEDRAG3_STATUS_DEFAULT; 1005 if (where == BORDER) 1006 key = KEYC_MOUSEDRAG3_BORDER; 1007 break; 1008 case MOUSE_BUTTON_6: 1009 if (where == PANE) 1010 key = KEYC_MOUSEDRAG6_PANE; 1011 if (where == STATUS) 1012 key = KEYC_MOUSEDRAG6_STATUS; 1013 if (where == STATUS_LEFT) 1014 key = KEYC_MOUSEDRAG6_STATUS_LEFT; 1015 if (where == STATUS_RIGHT) 1016 key = KEYC_MOUSEDRAG6_STATUS_RIGHT; 1017 if (where == STATUS_DEFAULT) 1018 key = KEYC_MOUSEDRAG6_STATUS_DEFAULT; 1019 if (where == BORDER) 1020 key = KEYC_MOUSEDRAG6_BORDER; 1021 break; 1022 case MOUSE_BUTTON_7: 1023 if (where == PANE) 1024 key = KEYC_MOUSEDRAG7_PANE; 1025 if (where == STATUS) 1026 key = KEYC_MOUSEDRAG7_STATUS; 1027 if (where == STATUS_LEFT) 1028 key = KEYC_MOUSEDRAG7_STATUS_LEFT; 1029 if (where == STATUS_RIGHT) 1030 key = KEYC_MOUSEDRAG7_STATUS_RIGHT; 1031 if (where == STATUS_DEFAULT) 1032 key = KEYC_MOUSEDRAG7_STATUS_DEFAULT; 1033 if (where == BORDER) 1034 key = KEYC_MOUSEDRAG7_BORDER; 1035 break; 1036 case MOUSE_BUTTON_8: 1037 if (where == PANE) 1038 key = KEYC_MOUSEDRAG8_PANE; 1039 if (where == STATUS) 1040 key = KEYC_MOUSEDRAG8_STATUS; 1041 if (where == STATUS_LEFT) 1042 key = KEYC_MOUSEDRAG8_STATUS_LEFT; 1043 if (where == STATUS_RIGHT) 1044 key = KEYC_MOUSEDRAG8_STATUS_RIGHT; 1045 if (where == STATUS_DEFAULT) 1046 key = KEYC_MOUSEDRAG8_STATUS_DEFAULT; 1047 if (where == BORDER) 1048 key = KEYC_MOUSEDRAG8_BORDER; 1049 break; 1050 case MOUSE_BUTTON_9: 1051 if (where == PANE) 1052 key = KEYC_MOUSEDRAG9_PANE; 1053 if (where == STATUS) 1054 key = KEYC_MOUSEDRAG9_STATUS; 1055 if (where == STATUS_LEFT) 1056 key = KEYC_MOUSEDRAG9_STATUS_LEFT; 1057 if (where == STATUS_RIGHT) 1058 key = KEYC_MOUSEDRAG9_STATUS_RIGHT; 1059 if (where == STATUS_DEFAULT) 1060 key = KEYC_MOUSEDRAG9_STATUS_DEFAULT; 1061 if (where == BORDER) 1062 key = KEYC_MOUSEDRAG9_BORDER; 1063 break; 1064 case MOUSE_BUTTON_10: 1065 if (where == PANE) 1066 key = KEYC_MOUSEDRAG10_PANE; 1067 if (where == STATUS) 1068 key = KEYC_MOUSEDRAG10_STATUS; 1069 if (where == STATUS_LEFT) 1070 key = KEYC_MOUSEDRAG10_STATUS_LEFT; 1071 if (where == STATUS_RIGHT) 1072 key = KEYC_MOUSEDRAG10_STATUS_RIGHT; 1073 if (where == STATUS_DEFAULT) 1074 key = KEYC_MOUSEDRAG10_STATUS_DEFAULT; 1075 if (where == BORDER) 1076 key = KEYC_MOUSEDRAG10_BORDER; 1077 break; 1078 case MOUSE_BUTTON_11: 1079 if (where == PANE) 1080 key = KEYC_MOUSEDRAG11_PANE; 1081 if (where == STATUS) 1082 key = KEYC_MOUSEDRAG11_STATUS; 1083 if (where == STATUS_LEFT) 1084 key = KEYC_MOUSEDRAG11_STATUS_LEFT; 1085 if (where == STATUS_RIGHT) 1086 key = KEYC_MOUSEDRAG11_STATUS_RIGHT; 1087 if (where == STATUS_DEFAULT) 1088 key = KEYC_MOUSEDRAG11_STATUS_DEFAULT; 1089 if (where == BORDER) 1090 key = KEYC_MOUSEDRAG11_BORDER; 1091 break; 1092 } 1093 } 1094 1095 /* 1096 * Begin a drag by setting the flag to a non-zero value that 1097 * corresponds to the mouse button in use. 1098 */ 1099 c->tty.mouse_drag_flag = MOUSE_BUTTONS(b) + 1; 1100 break; 1101 case WHEEL: 1102 if (MOUSE_BUTTONS(b) == MOUSE_WHEEL_UP) { 1103 if (where == PANE) 1104 key = KEYC_WHEELUP_PANE; 1105 if (where == STATUS) 1106 key = KEYC_WHEELUP_STATUS; 1107 if (where == STATUS_LEFT) 1108 key = KEYC_WHEELUP_STATUS_LEFT; 1109 if (where == STATUS_RIGHT) 1110 key = KEYC_WHEELUP_STATUS_RIGHT; 1111 if (where == STATUS_DEFAULT) 1112 key = KEYC_WHEELUP_STATUS_DEFAULT; 1113 if (where == BORDER) 1114 key = KEYC_WHEELUP_BORDER; 1115 } else { 1116 if (where == PANE) 1117 key = KEYC_WHEELDOWN_PANE; 1118 if (where == STATUS) 1119 key = KEYC_WHEELDOWN_STATUS; 1120 if (where == STATUS_LEFT) 1121 key = KEYC_WHEELDOWN_STATUS_LEFT; 1122 if (where == STATUS_RIGHT) 1123 key = KEYC_WHEELDOWN_STATUS_RIGHT; 1124 if (where == STATUS_DEFAULT) 1125 key = KEYC_WHEELDOWN_STATUS_DEFAULT; 1126 if (where == BORDER) 1127 key = KEYC_WHEELDOWN_BORDER; 1128 } 1129 break; 1130 case UP: 1131 switch (MOUSE_BUTTONS(b)) { 1132 case MOUSE_BUTTON_1: 1133 if (where == PANE) 1134 key = KEYC_MOUSEUP1_PANE; 1135 if (where == STATUS) 1136 key = KEYC_MOUSEUP1_STATUS; 1137 if (where == STATUS_LEFT) 1138 key = KEYC_MOUSEUP1_STATUS_LEFT; 1139 if (where == STATUS_RIGHT) 1140 key = KEYC_MOUSEUP1_STATUS_RIGHT; 1141 if (where == STATUS_DEFAULT) 1142 key = KEYC_MOUSEUP1_STATUS_DEFAULT; 1143 if (where == BORDER) 1144 key = KEYC_MOUSEUP1_BORDER; 1145 break; 1146 case MOUSE_BUTTON_2: 1147 if (where == PANE) 1148 key = KEYC_MOUSEUP2_PANE; 1149 if (where == STATUS) 1150 key = KEYC_MOUSEUP2_STATUS; 1151 if (where == STATUS_LEFT) 1152 key = KEYC_MOUSEUP2_STATUS_LEFT; 1153 if (where == STATUS_RIGHT) 1154 key = KEYC_MOUSEUP2_STATUS_RIGHT; 1155 if (where == STATUS_DEFAULT) 1156 key = KEYC_MOUSEUP2_STATUS_DEFAULT; 1157 if (where == BORDER) 1158 key = KEYC_MOUSEUP2_BORDER; 1159 break; 1160 case MOUSE_BUTTON_3: 1161 if (where == PANE) 1162 key = KEYC_MOUSEUP3_PANE; 1163 if (where == STATUS) 1164 key = KEYC_MOUSEUP3_STATUS; 1165 if (where == STATUS_LEFT) 1166 key = KEYC_MOUSEUP3_STATUS_LEFT; 1167 if (where == STATUS_RIGHT) 1168 key = KEYC_MOUSEUP3_STATUS_RIGHT; 1169 if (where == STATUS_DEFAULT) 1170 key = KEYC_MOUSEUP3_STATUS_DEFAULT; 1171 if (where == BORDER) 1172 key = KEYC_MOUSEUP3_BORDER; 1173 break; 1174 case MOUSE_BUTTON_6: 1175 if (where == PANE) 1176 key = KEYC_MOUSEUP6_PANE; 1177 if (where == STATUS) 1178 key = KEYC_MOUSEUP6_STATUS; 1179 if (where == STATUS_LEFT) 1180 key = KEYC_MOUSEUP6_STATUS_LEFT; 1181 if (where == STATUS_RIGHT) 1182 key = KEYC_MOUSEUP6_STATUS_RIGHT; 1183 if (where == STATUS_DEFAULT) 1184 key = KEYC_MOUSEUP6_STATUS_DEFAULT; 1185 if (where == BORDER) 1186 key = KEYC_MOUSEUP6_BORDER; 1187 break; 1188 case MOUSE_BUTTON_7: 1189 if (where == PANE) 1190 key = KEYC_MOUSEUP7_PANE; 1191 if (where == STATUS) 1192 key = KEYC_MOUSEUP7_STATUS; 1193 if (where == STATUS_LEFT) 1194 key = KEYC_MOUSEUP7_STATUS_LEFT; 1195 if (where == STATUS_RIGHT) 1196 key = KEYC_MOUSEUP7_STATUS_RIGHT; 1197 if (where == STATUS_DEFAULT) 1198 key = KEYC_MOUSEUP7_STATUS_DEFAULT; 1199 if (where == BORDER) 1200 key = KEYC_MOUSEUP7_BORDER; 1201 break; 1202 case MOUSE_BUTTON_8: 1203 if (where == PANE) 1204 key = KEYC_MOUSEUP8_PANE; 1205 if (where == STATUS) 1206 key = KEYC_MOUSEUP8_STATUS; 1207 if (where == STATUS_LEFT) 1208 key = KEYC_MOUSEUP8_STATUS_LEFT; 1209 if (where == STATUS_RIGHT) 1210 key = KEYC_MOUSEUP8_STATUS_RIGHT; 1211 if (where == STATUS_DEFAULT) 1212 key = KEYC_MOUSEUP8_STATUS_DEFAULT; 1213 if (where == BORDER) 1214 key = KEYC_MOUSEUP8_BORDER; 1215 break; 1216 case MOUSE_BUTTON_9: 1217 if (where == PANE) 1218 key = KEYC_MOUSEUP9_PANE; 1219 if (where == STATUS) 1220 key = KEYC_MOUSEUP9_STATUS; 1221 if (where == STATUS_LEFT) 1222 key = KEYC_MOUSEUP9_STATUS_LEFT; 1223 if (where == STATUS_RIGHT) 1224 key = KEYC_MOUSEUP9_STATUS_RIGHT; 1225 if (where == STATUS_DEFAULT) 1226 key = KEYC_MOUSEUP9_STATUS_DEFAULT; 1227 if (where == BORDER) 1228 key = KEYC_MOUSEUP9_BORDER; 1229 break; 1230 case MOUSE_BUTTON_10: 1231 if (where == PANE) 1232 key = KEYC_MOUSEUP1_PANE; 1233 if (where == STATUS) 1234 key = KEYC_MOUSEUP1_STATUS; 1235 if (where == STATUS_LEFT) 1236 key = KEYC_MOUSEUP1_STATUS_LEFT; 1237 if (where == STATUS_RIGHT) 1238 key = KEYC_MOUSEUP1_STATUS_RIGHT; 1239 if (where == STATUS_DEFAULT) 1240 key = KEYC_MOUSEUP1_STATUS_DEFAULT; 1241 if (where == BORDER) 1242 key = KEYC_MOUSEUP1_BORDER; 1243 break; 1244 case MOUSE_BUTTON_11: 1245 if (where == PANE) 1246 key = KEYC_MOUSEUP11_PANE; 1247 if (where == STATUS) 1248 key = KEYC_MOUSEUP11_STATUS; 1249 if (where == STATUS_LEFT) 1250 key = KEYC_MOUSEUP11_STATUS_LEFT; 1251 if (where == STATUS_RIGHT) 1252 key = KEYC_MOUSEUP11_STATUS_RIGHT; 1253 if (where == STATUS_DEFAULT) 1254 key = KEYC_MOUSEUP11_STATUS_DEFAULT; 1255 if (where == BORDER) 1256 key = KEYC_MOUSEUP11_BORDER; 1257 break; 1258 } 1259 break; 1260 case DOWN: 1261 switch (MOUSE_BUTTONS(b)) { 1262 case MOUSE_BUTTON_1: 1263 if (where == PANE) 1264 key = KEYC_MOUSEDOWN1_PANE; 1265 if (where == STATUS) 1266 key = KEYC_MOUSEDOWN1_STATUS; 1267 if (where == STATUS_LEFT) 1268 key = KEYC_MOUSEDOWN1_STATUS_LEFT; 1269 if (where == STATUS_RIGHT) 1270 key = KEYC_MOUSEDOWN1_STATUS_RIGHT; 1271 if (where == STATUS_DEFAULT) 1272 key = KEYC_MOUSEDOWN1_STATUS_DEFAULT; 1273 if (where == BORDER) 1274 key = KEYC_MOUSEDOWN1_BORDER; 1275 break; 1276 case MOUSE_BUTTON_2: 1277 if (where == PANE) 1278 key = KEYC_MOUSEDOWN2_PANE; 1279 if (where == STATUS) 1280 key = KEYC_MOUSEDOWN2_STATUS; 1281 if (where == STATUS_LEFT) 1282 key = KEYC_MOUSEDOWN2_STATUS_LEFT; 1283 if (where == STATUS_RIGHT) 1284 key = KEYC_MOUSEDOWN2_STATUS_RIGHT; 1285 if (where == STATUS_DEFAULT) 1286 key = KEYC_MOUSEDOWN2_STATUS_DEFAULT; 1287 if (where == BORDER) 1288 key = KEYC_MOUSEDOWN2_BORDER; 1289 break; 1290 case MOUSE_BUTTON_3: 1291 if (where == PANE) 1292 key = KEYC_MOUSEDOWN3_PANE; 1293 if (where == STATUS) 1294 key = KEYC_MOUSEDOWN3_STATUS; 1295 if (where == STATUS_LEFT) 1296 key = KEYC_MOUSEDOWN3_STATUS_LEFT; 1297 if (where == STATUS_RIGHT) 1298 key = KEYC_MOUSEDOWN3_STATUS_RIGHT; 1299 if (where == STATUS_DEFAULT) 1300 key = KEYC_MOUSEDOWN3_STATUS_DEFAULT; 1301 if (where == BORDER) 1302 key = KEYC_MOUSEDOWN3_BORDER; 1303 break; 1304 case MOUSE_BUTTON_6: 1305 if (where == PANE) 1306 key = KEYC_MOUSEDOWN6_PANE; 1307 if (where == STATUS) 1308 key = KEYC_MOUSEDOWN6_STATUS; 1309 if (where == STATUS_LEFT) 1310 key = KEYC_MOUSEDOWN6_STATUS_LEFT; 1311 if (where == STATUS_RIGHT) 1312 key = KEYC_MOUSEDOWN6_STATUS_RIGHT; 1313 if (where == STATUS_DEFAULT) 1314 key = KEYC_MOUSEDOWN6_STATUS_DEFAULT; 1315 if (where == BORDER) 1316 key = KEYC_MOUSEDOWN6_BORDER; 1317 break; 1318 case MOUSE_BUTTON_7: 1319 if (where == PANE) 1320 key = KEYC_MOUSEDOWN7_PANE; 1321 if (where == STATUS) 1322 key = KEYC_MOUSEDOWN7_STATUS; 1323 if (where == STATUS_LEFT) 1324 key = KEYC_MOUSEDOWN7_STATUS_LEFT; 1325 if (where == STATUS_RIGHT) 1326 key = KEYC_MOUSEDOWN7_STATUS_RIGHT; 1327 if (where == STATUS_DEFAULT) 1328 key = KEYC_MOUSEDOWN7_STATUS_DEFAULT; 1329 if (where == BORDER) 1330 key = KEYC_MOUSEDOWN7_BORDER; 1331 break; 1332 case MOUSE_BUTTON_8: 1333 if (where == PANE) 1334 key = KEYC_MOUSEDOWN8_PANE; 1335 if (where == STATUS) 1336 key = KEYC_MOUSEDOWN8_STATUS; 1337 if (where == STATUS_LEFT) 1338 key = KEYC_MOUSEDOWN8_STATUS_LEFT; 1339 if (where == STATUS_RIGHT) 1340 key = KEYC_MOUSEDOWN8_STATUS_RIGHT; 1341 if (where == STATUS_DEFAULT) 1342 key = KEYC_MOUSEDOWN8_STATUS_DEFAULT; 1343 if (where == BORDER) 1344 key = KEYC_MOUSEDOWN8_BORDER; 1345 break; 1346 case MOUSE_BUTTON_9: 1347 if (where == PANE) 1348 key = KEYC_MOUSEDOWN9_PANE; 1349 if (where == STATUS) 1350 key = KEYC_MOUSEDOWN9_STATUS; 1351 if (where == STATUS_LEFT) 1352 key = KEYC_MOUSEDOWN9_STATUS_LEFT; 1353 if (where == STATUS_RIGHT) 1354 key = KEYC_MOUSEDOWN9_STATUS_RIGHT; 1355 if (where == STATUS_DEFAULT) 1356 key = KEYC_MOUSEDOWN9_STATUS_DEFAULT; 1357 if (where == BORDER) 1358 key = KEYC_MOUSEDOWN9_BORDER; 1359 break; 1360 case MOUSE_BUTTON_10: 1361 if (where == PANE) 1362 key = KEYC_MOUSEDOWN10_PANE; 1363 if (where == STATUS) 1364 key = KEYC_MOUSEDOWN10_STATUS; 1365 if (where == STATUS_LEFT) 1366 key = KEYC_MOUSEDOWN10_STATUS_LEFT; 1367 if (where == STATUS_RIGHT) 1368 key = KEYC_MOUSEDOWN10_STATUS_RIGHT; 1369 if (where == STATUS_DEFAULT) 1370 key = KEYC_MOUSEDOWN10_STATUS_DEFAULT; 1371 if (where == BORDER) 1372 key = KEYC_MOUSEDOWN10_BORDER; 1373 break; 1374 case MOUSE_BUTTON_11: 1375 if (where == PANE) 1376 key = KEYC_MOUSEDOWN11_PANE; 1377 if (where == STATUS) 1378 key = KEYC_MOUSEDOWN11_STATUS; 1379 if (where == STATUS_LEFT) 1380 key = KEYC_MOUSEDOWN11_STATUS_LEFT; 1381 if (where == STATUS_RIGHT) 1382 key = KEYC_MOUSEDOWN11_STATUS_RIGHT; 1383 if (where == STATUS_DEFAULT) 1384 key = KEYC_MOUSEDOWN11_STATUS_DEFAULT; 1385 if (where == BORDER) 1386 key = KEYC_MOUSEDOWN11_BORDER; 1387 break; 1388 } 1389 break; 1390 case SECOND: 1391 switch (MOUSE_BUTTONS(b)) { 1392 case MOUSE_BUTTON_1: 1393 if (where == PANE) 1394 key = KEYC_SECONDCLICK1_PANE; 1395 if (where == STATUS) 1396 key = KEYC_SECONDCLICK1_STATUS; 1397 if (where == STATUS_LEFT) 1398 key = KEYC_SECONDCLICK1_STATUS_LEFT; 1399 if (where == STATUS_RIGHT) 1400 key = KEYC_SECONDCLICK1_STATUS_RIGHT; 1401 if (where == STATUS_DEFAULT) 1402 key = KEYC_SECONDCLICK1_STATUS_DEFAULT; 1403 if (where == BORDER) 1404 key = KEYC_SECONDCLICK1_BORDER; 1405 break; 1406 case MOUSE_BUTTON_2: 1407 if (where == PANE) 1408 key = KEYC_SECONDCLICK2_PANE; 1409 if (where == STATUS) 1410 key = KEYC_SECONDCLICK2_STATUS; 1411 if (where == STATUS_LEFT) 1412 key = KEYC_SECONDCLICK2_STATUS_LEFT; 1413 if (where == STATUS_RIGHT) 1414 key = KEYC_SECONDCLICK2_STATUS_RIGHT; 1415 if (where == STATUS_DEFAULT) 1416 key = KEYC_SECONDCLICK2_STATUS_DEFAULT; 1417 if (where == BORDER) 1418 key = KEYC_SECONDCLICK2_BORDER; 1419 break; 1420 case MOUSE_BUTTON_3: 1421 if (where == PANE) 1422 key = KEYC_SECONDCLICK3_PANE; 1423 if (where == STATUS) 1424 key = KEYC_SECONDCLICK3_STATUS; 1425 if (where == STATUS_LEFT) 1426 key = KEYC_SECONDCLICK3_STATUS_LEFT; 1427 if (where == STATUS_RIGHT) 1428 key = KEYC_SECONDCLICK3_STATUS_RIGHT; 1429 if (where == STATUS_DEFAULT) 1430 key = KEYC_SECONDCLICK3_STATUS_DEFAULT; 1431 if (where == BORDER) 1432 key = KEYC_SECONDCLICK3_BORDER; 1433 break; 1434 case MOUSE_BUTTON_6: 1435 if (where == PANE) 1436 key = KEYC_SECONDCLICK6_PANE; 1437 if (where == STATUS) 1438 key = KEYC_SECONDCLICK6_STATUS; 1439 if (where == STATUS_LEFT) 1440 key = KEYC_SECONDCLICK6_STATUS_LEFT; 1441 if (where == STATUS_RIGHT) 1442 key = KEYC_SECONDCLICK6_STATUS_RIGHT; 1443 if (where == STATUS_DEFAULT) 1444 key = KEYC_SECONDCLICK6_STATUS_DEFAULT; 1445 if (where == BORDER) 1446 key = KEYC_SECONDCLICK6_BORDER; 1447 break; 1448 case MOUSE_BUTTON_7: 1449 if (where == PANE) 1450 key = KEYC_SECONDCLICK7_PANE; 1451 if (where == STATUS) 1452 key = KEYC_SECONDCLICK7_STATUS; 1453 if (where == STATUS_LEFT) 1454 key = KEYC_SECONDCLICK7_STATUS_LEFT; 1455 if (where == STATUS_RIGHT) 1456 key = KEYC_SECONDCLICK7_STATUS_RIGHT; 1457 if (where == STATUS_DEFAULT) 1458 key = KEYC_SECONDCLICK7_STATUS_DEFAULT; 1459 if (where == BORDER) 1460 key = KEYC_SECONDCLICK7_BORDER; 1461 break; 1462 case MOUSE_BUTTON_8: 1463 if (where == PANE) 1464 key = KEYC_SECONDCLICK8_PANE; 1465 if (where == STATUS) 1466 key = KEYC_SECONDCLICK8_STATUS; 1467 if (where == STATUS_LEFT) 1468 key = KEYC_SECONDCLICK8_STATUS_LEFT; 1469 if (where == STATUS_RIGHT) 1470 key = KEYC_SECONDCLICK8_STATUS_RIGHT; 1471 if (where == STATUS_DEFAULT) 1472 key = KEYC_SECONDCLICK8_STATUS_DEFAULT; 1473 if (where == BORDER) 1474 key = KEYC_SECONDCLICK8_BORDER; 1475 break; 1476 case MOUSE_BUTTON_9: 1477 if (where == PANE) 1478 key = KEYC_SECONDCLICK9_PANE; 1479 if (where == STATUS) 1480 key = KEYC_SECONDCLICK9_STATUS; 1481 if (where == STATUS_LEFT) 1482 key = KEYC_SECONDCLICK9_STATUS_LEFT; 1483 if (where == STATUS_RIGHT) 1484 key = KEYC_SECONDCLICK9_STATUS_RIGHT; 1485 if (where == STATUS_DEFAULT) 1486 key = KEYC_SECONDCLICK9_STATUS_DEFAULT; 1487 if (where == BORDER) 1488 key = KEYC_SECONDCLICK9_BORDER; 1489 break; 1490 case MOUSE_BUTTON_10: 1491 if (where == PANE) 1492 key = KEYC_SECONDCLICK10_PANE; 1493 if (where == STATUS) 1494 key = KEYC_SECONDCLICK10_STATUS; 1495 if (where == STATUS_LEFT) 1496 key = KEYC_SECONDCLICK10_STATUS_LEFT; 1497 if (where == STATUS_RIGHT) 1498 key = KEYC_SECONDCLICK10_STATUS_RIGHT; 1499 if (where == STATUS_DEFAULT) 1500 key = KEYC_SECONDCLICK10_STATUS_DEFAULT; 1501 if (where == BORDER) 1502 key = KEYC_SECONDCLICK10_BORDER; 1503 break; 1504 case MOUSE_BUTTON_11: 1505 if (where == PANE) 1506 key = KEYC_SECONDCLICK11_PANE; 1507 if (where == STATUS) 1508 key = KEYC_SECONDCLICK11_STATUS; 1509 if (where == STATUS_LEFT) 1510 key = KEYC_SECONDCLICK11_STATUS_LEFT; 1511 if (where == STATUS_RIGHT) 1512 key = KEYC_SECONDCLICK11_STATUS_RIGHT; 1513 if (where == STATUS_DEFAULT) 1514 key = KEYC_SECONDCLICK11_STATUS_DEFAULT; 1515 if (where == BORDER) 1516 key = KEYC_SECONDCLICK11_BORDER; 1517 break; 1518 } 1519 break; 1520 case DOUBLE: 1521 switch (MOUSE_BUTTONS(b)) { 1522 case MOUSE_BUTTON_1: 1523 if (where == PANE) 1524 key = KEYC_DOUBLECLICK1_PANE; 1525 if (where == STATUS) 1526 key = KEYC_DOUBLECLICK1_STATUS; 1527 if (where == STATUS_LEFT) 1528 key = KEYC_DOUBLECLICK1_STATUS_LEFT; 1529 if (where == STATUS_RIGHT) 1530 key = KEYC_DOUBLECLICK1_STATUS_RIGHT; 1531 if (where == STATUS_DEFAULT) 1532 key = KEYC_DOUBLECLICK1_STATUS_DEFAULT; 1533 if (where == BORDER) 1534 key = KEYC_DOUBLECLICK1_BORDER; 1535 break; 1536 case MOUSE_BUTTON_2: 1537 if (where == PANE) 1538 key = KEYC_DOUBLECLICK2_PANE; 1539 if (where == STATUS) 1540 key = KEYC_DOUBLECLICK2_STATUS; 1541 if (where == STATUS_LEFT) 1542 key = KEYC_DOUBLECLICK2_STATUS_LEFT; 1543 if (where == STATUS_RIGHT) 1544 key = KEYC_DOUBLECLICK2_STATUS_RIGHT; 1545 if (where == STATUS_DEFAULT) 1546 key = KEYC_DOUBLECLICK2_STATUS_DEFAULT; 1547 if (where == BORDER) 1548 key = KEYC_DOUBLECLICK2_BORDER; 1549 break; 1550 case MOUSE_BUTTON_3: 1551 if (where == PANE) 1552 key = KEYC_DOUBLECLICK3_PANE; 1553 if (where == STATUS) 1554 key = KEYC_DOUBLECLICK3_STATUS; 1555 if (where == STATUS_LEFT) 1556 key = KEYC_DOUBLECLICK3_STATUS_LEFT; 1557 if (where == STATUS_RIGHT) 1558 key = KEYC_DOUBLECLICK3_STATUS_RIGHT; 1559 if (where == STATUS_DEFAULT) 1560 key = KEYC_DOUBLECLICK3_STATUS_DEFAULT; 1561 if (where == BORDER) 1562 key = KEYC_DOUBLECLICK3_BORDER; 1563 break; 1564 case MOUSE_BUTTON_6: 1565 if (where == PANE) 1566 key = KEYC_DOUBLECLICK6_PANE; 1567 if (where == STATUS) 1568 key = KEYC_DOUBLECLICK6_STATUS; 1569 if (where == STATUS_LEFT) 1570 key = KEYC_DOUBLECLICK6_STATUS_LEFT; 1571 if (where == STATUS_RIGHT) 1572 key = KEYC_DOUBLECLICK6_STATUS_RIGHT; 1573 if (where == STATUS_DEFAULT) 1574 key = KEYC_DOUBLECLICK6_STATUS_DEFAULT; 1575 if (where == BORDER) 1576 key = KEYC_DOUBLECLICK6_BORDER; 1577 break; 1578 case MOUSE_BUTTON_7: 1579 if (where == PANE) 1580 key = KEYC_DOUBLECLICK7_PANE; 1581 if (where == STATUS) 1582 key = KEYC_DOUBLECLICK7_STATUS; 1583 if (where == STATUS_LEFT) 1584 key = KEYC_DOUBLECLICK7_STATUS_LEFT; 1585 if (where == STATUS_RIGHT) 1586 key = KEYC_DOUBLECLICK7_STATUS_RIGHT; 1587 if (where == STATUS_DEFAULT) 1588 key = KEYC_DOUBLECLICK7_STATUS_DEFAULT; 1589 if (where == BORDER) 1590 key = KEYC_DOUBLECLICK7_BORDER; 1591 break; 1592 case MOUSE_BUTTON_8: 1593 if (where == PANE) 1594 key = KEYC_DOUBLECLICK8_PANE; 1595 if (where == STATUS) 1596 key = KEYC_DOUBLECLICK8_STATUS; 1597 if (where == STATUS_LEFT) 1598 key = KEYC_DOUBLECLICK8_STATUS_LEFT; 1599 if (where == STATUS_RIGHT) 1600 key = KEYC_DOUBLECLICK8_STATUS_RIGHT; 1601 if (where == STATUS_DEFAULT) 1602 key = KEYC_DOUBLECLICK8_STATUS_DEFAULT; 1603 if (where == BORDER) 1604 key = KEYC_DOUBLECLICK8_BORDER; 1605 break; 1606 case MOUSE_BUTTON_9: 1607 if (where == PANE) 1608 key = KEYC_DOUBLECLICK9_PANE; 1609 if (where == STATUS) 1610 key = KEYC_DOUBLECLICK9_STATUS; 1611 if (where == STATUS_LEFT) 1612 key = KEYC_DOUBLECLICK9_STATUS_LEFT; 1613 if (where == STATUS_RIGHT) 1614 key = KEYC_DOUBLECLICK9_STATUS_RIGHT; 1615 if (where == STATUS_DEFAULT) 1616 key = KEYC_DOUBLECLICK9_STATUS_DEFAULT; 1617 if (where == BORDER) 1618 key = KEYC_DOUBLECLICK9_BORDER; 1619 break; 1620 case MOUSE_BUTTON_10: 1621 if (where == PANE) 1622 key = KEYC_DOUBLECLICK10_PANE; 1623 if (where == STATUS) 1624 key = KEYC_DOUBLECLICK10_STATUS; 1625 if (where == STATUS_LEFT) 1626 key = KEYC_DOUBLECLICK10_STATUS_LEFT; 1627 if (where == STATUS_RIGHT) 1628 key = KEYC_DOUBLECLICK10_STATUS_RIGHT; 1629 if (where == STATUS_DEFAULT) 1630 key = KEYC_DOUBLECLICK10_STATUS_DEFAULT; 1631 if (where == BORDER) 1632 key = KEYC_DOUBLECLICK10_BORDER; 1633 break; 1634 case MOUSE_BUTTON_11: 1635 if (where == PANE) 1636 key = KEYC_DOUBLECLICK11_PANE; 1637 if (where == STATUS) 1638 key = KEYC_DOUBLECLICK11_STATUS; 1639 if (where == STATUS_LEFT) 1640 key = KEYC_DOUBLECLICK11_STATUS_LEFT; 1641 if (where == STATUS_RIGHT) 1642 key = KEYC_DOUBLECLICK11_STATUS_RIGHT; 1643 if (where == STATUS_DEFAULT) 1644 key = KEYC_DOUBLECLICK11_STATUS_DEFAULT; 1645 if (where == BORDER) 1646 key = KEYC_DOUBLECLICK11_BORDER; 1647 break; 1648 } 1649 break; 1650 case TRIPLE: 1651 switch (MOUSE_BUTTONS(b)) { 1652 case MOUSE_BUTTON_1: 1653 if (where == PANE) 1654 key = KEYC_TRIPLECLICK1_PANE; 1655 if (where == STATUS) 1656 key = KEYC_TRIPLECLICK1_STATUS; 1657 if (where == STATUS_LEFT) 1658 key = KEYC_TRIPLECLICK1_STATUS_LEFT; 1659 if (where == STATUS_RIGHT) 1660 key = KEYC_TRIPLECLICK1_STATUS_RIGHT; 1661 if (where == STATUS_DEFAULT) 1662 key = KEYC_TRIPLECLICK1_STATUS_DEFAULT; 1663 if (where == BORDER) 1664 key = KEYC_TRIPLECLICK1_BORDER; 1665 break; 1666 case MOUSE_BUTTON_2: 1667 if (where == PANE) 1668 key = KEYC_TRIPLECLICK2_PANE; 1669 if (where == STATUS) 1670 key = KEYC_TRIPLECLICK2_STATUS; 1671 if (where == STATUS_LEFT) 1672 key = KEYC_TRIPLECLICK2_STATUS_LEFT; 1673 if (where == STATUS_RIGHT) 1674 key = KEYC_TRIPLECLICK2_STATUS_RIGHT; 1675 if (where == STATUS_DEFAULT) 1676 key = KEYC_TRIPLECLICK2_STATUS_DEFAULT; 1677 if (where == BORDER) 1678 key = KEYC_TRIPLECLICK2_BORDER; 1679 break; 1680 case MOUSE_BUTTON_3: 1681 if (where == PANE) 1682 key = KEYC_TRIPLECLICK3_PANE; 1683 if (where == STATUS) 1684 key = KEYC_TRIPLECLICK3_STATUS; 1685 if (where == STATUS_LEFT) 1686 key = KEYC_TRIPLECLICK3_STATUS_LEFT; 1687 if (where == STATUS_RIGHT) 1688 key = KEYC_TRIPLECLICK3_STATUS_RIGHT; 1689 if (where == STATUS_DEFAULT) 1690 key = KEYC_TRIPLECLICK3_STATUS_DEFAULT; 1691 if (where == BORDER) 1692 key = KEYC_TRIPLECLICK3_BORDER; 1693 break; 1694 case MOUSE_BUTTON_6: 1695 if (where == PANE) 1696 key = KEYC_TRIPLECLICK6_PANE; 1697 if (where == STATUS) 1698 key = KEYC_TRIPLECLICK6_STATUS; 1699 if (where == STATUS_LEFT) 1700 key = KEYC_TRIPLECLICK6_STATUS_LEFT; 1701 if (where == STATUS_RIGHT) 1702 key = KEYC_TRIPLECLICK6_STATUS_RIGHT; 1703 if (where == STATUS_DEFAULT) 1704 key = KEYC_TRIPLECLICK6_STATUS_DEFAULT; 1705 if (where == BORDER) 1706 key = KEYC_TRIPLECLICK6_BORDER; 1707 break; 1708 case MOUSE_BUTTON_7: 1709 if (where == PANE) 1710 key = KEYC_TRIPLECLICK7_PANE; 1711 if (where == STATUS) 1712 key = KEYC_TRIPLECLICK7_STATUS; 1713 if (where == STATUS_LEFT) 1714 key = KEYC_TRIPLECLICK7_STATUS_LEFT; 1715 if (where == STATUS_RIGHT) 1716 key = KEYC_TRIPLECLICK7_STATUS_RIGHT; 1717 if (where == STATUS_DEFAULT) 1718 key = KEYC_TRIPLECLICK7_STATUS_DEFAULT; 1719 if (where == BORDER) 1720 key = KEYC_TRIPLECLICK7_BORDER; 1721 break; 1722 case MOUSE_BUTTON_8: 1723 if (where == PANE) 1724 key = KEYC_TRIPLECLICK8_PANE; 1725 if (where == STATUS) 1726 key = KEYC_TRIPLECLICK8_STATUS; 1727 if (where == STATUS_LEFT) 1728 key = KEYC_TRIPLECLICK8_STATUS_LEFT; 1729 if (where == STATUS_RIGHT) 1730 key = KEYC_TRIPLECLICK8_STATUS_RIGHT; 1731 if (where == STATUS_DEFAULT) 1732 key = KEYC_TRIPLECLICK8_STATUS_DEFAULT; 1733 if (where == BORDER) 1734 key = KEYC_TRIPLECLICK8_BORDER; 1735 break; 1736 case MOUSE_BUTTON_9: 1737 if (where == PANE) 1738 key = KEYC_TRIPLECLICK9_PANE; 1739 if (where == STATUS) 1740 key = KEYC_TRIPLECLICK9_STATUS; 1741 if (where == STATUS_LEFT) 1742 key = KEYC_TRIPLECLICK9_STATUS_LEFT; 1743 if (where == STATUS_RIGHT) 1744 key = KEYC_TRIPLECLICK9_STATUS_RIGHT; 1745 if (where == STATUS_DEFAULT) 1746 key = KEYC_TRIPLECLICK9_STATUS_DEFAULT; 1747 if (where == BORDER) 1748 key = KEYC_TRIPLECLICK9_BORDER; 1749 break; 1750 case MOUSE_BUTTON_10: 1751 if (where == PANE) 1752 key = KEYC_TRIPLECLICK10_PANE; 1753 if (where == STATUS) 1754 key = KEYC_TRIPLECLICK10_STATUS; 1755 if (where == STATUS_LEFT) 1756 key = KEYC_TRIPLECLICK10_STATUS_LEFT; 1757 if (where == STATUS_RIGHT) 1758 key = KEYC_TRIPLECLICK10_STATUS_RIGHT; 1759 if (where == STATUS_DEFAULT) 1760 key = KEYC_TRIPLECLICK10_STATUS_DEFAULT; 1761 if (where == BORDER) 1762 key = KEYC_TRIPLECLICK10_BORDER; 1763 break; 1764 case MOUSE_BUTTON_11: 1765 if (where == PANE) 1766 key = KEYC_TRIPLECLICK11_PANE; 1767 if (where == STATUS) 1768 key = KEYC_TRIPLECLICK11_STATUS; 1769 if (where == STATUS_LEFT) 1770 key = KEYC_TRIPLECLICK11_STATUS_LEFT; 1771 if (where == STATUS_RIGHT) 1772 key = KEYC_TRIPLECLICK11_STATUS_RIGHT; 1773 if (where == STATUS_DEFAULT) 1774 key = KEYC_TRIPLECLICK11_STATUS_DEFAULT; 1775 if (where == BORDER) 1776 key = KEYC_TRIPLECLICK11_BORDER; 1777 break; 1778 } 1779 break; 1780 } 1781 if (key == KEYC_UNKNOWN) 1782 return (KEYC_UNKNOWN); 1783 1784 out: 1785 /* Apply modifiers if any. */ 1786 if (b & MOUSE_MASK_META) 1787 key |= KEYC_META; 1788 if (b & MOUSE_MASK_CTRL) 1789 key |= KEYC_CTRL; 1790 if (b & MOUSE_MASK_SHIFT) 1791 key |= KEYC_SHIFT; 1792 1793 if (log_get_level() != 0) 1794 log_debug("mouse key is %s", key_string_lookup_key (key, 1)); 1795 return (key); 1796 } 1797 1798 /* Is this a bracket paste key? */ 1799 static int 1800 server_client_is_bracket_pasting(struct client *c, key_code key) 1801 { 1802 if (key == KEYC_PASTE_START) { 1803 c->flags |= CLIENT_BRACKETPASTING; 1804 log_debug("%s: bracket paste on", c->name); 1805 return (1); 1806 } 1807 1808 if (key == KEYC_PASTE_END) { 1809 c->flags &= ~CLIENT_BRACKETPASTING; 1810 log_debug("%s: bracket paste off", c->name); 1811 return (1); 1812 } 1813 1814 return !!(c->flags & CLIENT_BRACKETPASTING); 1815 } 1816 1817 /* Is this fast enough to probably be a paste? */ 1818 static int 1819 server_client_assume_paste(struct session *s) 1820 { 1821 struct timeval tv; 1822 int t; 1823 1824 if ((t = options_get_number(s->options, "assume-paste-time")) == 0) 1825 return (0); 1826 1827 timersub(&s->activity_time, &s->last_activity_time, &tv); 1828 if (tv.tv_sec == 0 && tv.tv_usec < t * 1000) { 1829 log_debug("session %s pasting (flag %d)", s->name, 1830 !!(s->flags & SESSION_PASTING)); 1831 if (s->flags & SESSION_PASTING) 1832 return (1); 1833 s->flags |= SESSION_PASTING; 1834 return (0); 1835 } 1836 log_debug("session %s not pasting", s->name); 1837 s->flags &= ~SESSION_PASTING; 1838 return (0); 1839 } 1840 1841 /* Has the latest client changed? */ 1842 static void 1843 server_client_update_latest(struct client *c) 1844 { 1845 struct window *w; 1846 1847 if (c->session == NULL) 1848 return; 1849 w = c->session->curw->window; 1850 1851 if (w->latest == c) 1852 return; 1853 w->latest = c; 1854 1855 if (options_get_number(w->options, "window-size") == WINDOW_SIZE_LATEST) 1856 recalculate_size(w, 0); 1857 1858 notify_client("client-active", c); 1859 } 1860 1861 /* 1862 * Handle data key input from client. This owns and can modify the key event it 1863 * is given and is responsible for freeing it. 1864 */ 1865 static enum cmd_retval 1866 server_client_key_callback(struct cmdq_item *item, void *data) 1867 { 1868 struct client *c = cmdq_get_client(item); 1869 struct key_event *event = data; 1870 key_code key = event->key; 1871 struct mouse_event *m = &event->m; 1872 struct session *s = c->session; 1873 struct winlink *wl; 1874 struct window_pane *wp; 1875 struct window_mode_entry *wme; 1876 struct timeval tv; 1877 struct key_table *table, *first; 1878 struct key_binding *bd; 1879 int xtimeout; 1880 uint64_t flags, prefix_delay; 1881 struct cmd_find_state fs; 1882 key_code key0, prefix, prefix2; 1883 1884 /* Check the client is good to accept input. */ 1885 if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS)) 1886 goto out; 1887 wl = s->curw; 1888 1889 /* Update the activity timer. */ 1890 if (gettimeofday(&c->activity_time, NULL) != 0) 1891 fatal("gettimeofday failed"); 1892 session_update_activity(s, &c->activity_time); 1893 1894 /* Check for mouse keys. */ 1895 m->valid = 0; 1896 if (key == KEYC_MOUSE || key == KEYC_DOUBLECLICK) { 1897 if (c->flags & CLIENT_READONLY) 1898 goto out; 1899 key = server_client_check_mouse(c, event); 1900 if (key == KEYC_UNKNOWN) 1901 goto out; 1902 1903 m->valid = 1; 1904 m->key = key; 1905 1906 /* 1907 * Mouse drag is in progress, so fire the callback (now that 1908 * the mouse event is valid). 1909 */ 1910 if ((key & KEYC_MASK_KEY) == KEYC_DRAGGING) { 1911 c->tty.mouse_drag_update(c, m); 1912 goto out; 1913 } 1914 event->key = key; 1915 } 1916 1917 /* Find affected pane. */ 1918 if (!KEYC_IS_MOUSE(key) || cmd_find_from_mouse(&fs, m, 0) != 0) 1919 cmd_find_from_client(&fs, c, 0); 1920 wp = fs.wp; 1921 1922 /* Forward mouse keys if disabled. */ 1923 if (KEYC_IS_MOUSE(key) && !options_get_number(s->options, "mouse")) 1924 goto forward_key; 1925 1926 /* Forward if bracket pasting. */ 1927 if (server_client_is_bracket_pasting(c, key)) 1928 goto forward_key; 1929 1930 /* Treat everything as a regular key when pasting is detected. */ 1931 if (!KEYC_IS_MOUSE(key) && 1932 (~key & KEYC_SENT) && 1933 server_client_assume_paste(s)) 1934 goto forward_key; 1935 1936 /* 1937 * Work out the current key table. If the pane is in a mode, use 1938 * the mode table instead of the default key table. 1939 */ 1940 if (server_client_is_default_key_table(c, c->keytable) && 1941 wp != NULL && 1942 (wme = TAILQ_FIRST(&wp->modes)) != NULL && 1943 wme->mode->key_table != NULL) 1944 table = key_bindings_get_table(wme->mode->key_table(wme), 1); 1945 else 1946 table = c->keytable; 1947 first = table; 1948 1949 table_changed: 1950 /* 1951 * The prefix always takes precedence and forces a switch to the prefix 1952 * table, unless we are already there. 1953 */ 1954 prefix = (key_code)options_get_number(s->options, "prefix"); 1955 prefix2 = (key_code)options_get_number(s->options, "prefix2"); 1956 key0 = (key & (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS)); 1957 if ((key0 == (prefix & (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS)) || 1958 key0 == (prefix2 & (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS))) && 1959 strcmp(table->name, "prefix") != 0) { 1960 server_client_set_key_table(c, "prefix"); 1961 server_status_client(c); 1962 goto out; 1963 } 1964 flags = c->flags; 1965 1966 try_again: 1967 /* Log key table. */ 1968 if (wp == NULL) 1969 log_debug("key table %s (no pane)", table->name); 1970 else 1971 log_debug("key table %s (pane %%%u)", table->name, wp->id); 1972 if (c->flags & CLIENT_REPEAT) 1973 log_debug("currently repeating"); 1974 1975 bd = key_bindings_get(table, key0); 1976 1977 /* 1978 * If prefix-timeout is enabled and we're in the prefix table, see if 1979 * the timeout has been exceeded. Revert to the root table if so. 1980 */ 1981 prefix_delay = options_get_number(global_options, "prefix-timeout"); 1982 if (prefix_delay > 0 && 1983 strcmp(table->name, "prefix") == 0 && 1984 server_client_key_table_activity_diff(c) > prefix_delay) { 1985 /* 1986 * If repeating is active and this is a repeating binding, 1987 * ignore the timeout. 1988 */ 1989 if (bd != NULL && 1990 (c->flags & CLIENT_REPEAT) && 1991 (bd->flags & KEY_BINDING_REPEAT)) { 1992 log_debug("prefix timeout ignored, repeat is active"); 1993 } else { 1994 log_debug("prefix timeout exceeded"); 1995 server_client_set_key_table(c, NULL); 1996 first = table = c->keytable; 1997 server_status_client(c); 1998 goto table_changed; 1999 } 2000 } 2001 2002 /* Try to see if there is a key binding in the current table. */ 2003 if (bd != NULL) { 2004 /* 2005 * Key was matched in this table. If currently repeating but a 2006 * non-repeating binding was found, stop repeating and try 2007 * again in the root table. 2008 */ 2009 if ((c->flags & CLIENT_REPEAT) && 2010 (~bd->flags & KEY_BINDING_REPEAT)) { 2011 log_debug("found in key table %s (not repeating)", 2012 table->name); 2013 server_client_set_key_table(c, NULL); 2014 first = table = c->keytable; 2015 c->flags &= ~CLIENT_REPEAT; 2016 server_status_client(c); 2017 goto table_changed; 2018 } 2019 log_debug("found in key table %s", table->name); 2020 2021 /* 2022 * Take a reference to this table to make sure the key binding 2023 * doesn't disappear. 2024 */ 2025 table->references++; 2026 2027 /* 2028 * If this is a repeating key, start the timer. Otherwise reset 2029 * the client back to the root table. 2030 */ 2031 xtimeout = options_get_number(s->options, "repeat-time"); 2032 if (xtimeout != 0 && (bd->flags & KEY_BINDING_REPEAT)) { 2033 c->flags |= CLIENT_REPEAT; 2034 2035 tv.tv_sec = xtimeout / 1000; 2036 tv.tv_usec = (xtimeout % 1000) * 1000L; 2037 evtimer_del(&c->repeat_timer); 2038 evtimer_add(&c->repeat_timer, &tv); 2039 } else { 2040 c->flags &= ~CLIENT_REPEAT; 2041 server_client_set_key_table(c, NULL); 2042 } 2043 server_status_client(c); 2044 2045 /* Execute the key binding. */ 2046 key_bindings_dispatch(bd, item, c, event, &fs); 2047 key_bindings_unref_table(table); 2048 goto out; 2049 } 2050 2051 /* 2052 * No match, try the ANY key. 2053 */ 2054 if (key0 != KEYC_ANY) { 2055 key0 = KEYC_ANY; 2056 goto try_again; 2057 } 2058 2059 /* 2060 * Binding movement keys is useless since we only turn them on when the 2061 * application requests, so don't let them exit the prefix table. 2062 */ 2063 if (key == KEYC_MOUSEMOVE_PANE || 2064 key == KEYC_MOUSEMOVE_STATUS || 2065 key == KEYC_MOUSEMOVE_STATUS_LEFT || 2066 key == KEYC_MOUSEMOVE_STATUS_RIGHT || 2067 key == KEYC_MOUSEMOVE_STATUS_DEFAULT || 2068 key == KEYC_MOUSEMOVE_BORDER) 2069 goto forward_key; 2070 2071 /* 2072 * No match in this table. If not in the root table or if repeating 2073 * switch the client back to the root table and try again. 2074 */ 2075 log_debug("not found in key table %s", table->name); 2076 if (!server_client_is_default_key_table(c, table) || 2077 (c->flags & CLIENT_REPEAT)) { 2078 log_debug("trying in root table"); 2079 server_client_set_key_table(c, NULL); 2080 table = c->keytable; 2081 if (c->flags & CLIENT_REPEAT) 2082 first = table; 2083 c->flags &= ~CLIENT_REPEAT; 2084 server_status_client(c); 2085 goto table_changed; 2086 } 2087 2088 /* 2089 * No match in the root table either. If this wasn't the first table 2090 * tried, don't pass the key to the pane. 2091 */ 2092 if (first != table && (~flags & CLIENT_REPEAT)) { 2093 server_client_set_key_table(c, NULL); 2094 server_status_client(c); 2095 goto out; 2096 } 2097 2098 forward_key: 2099 if (c->flags & CLIENT_READONLY) 2100 goto out; 2101 if (wp != NULL) 2102 window_pane_key(wp, c, s, wl, key, m); 2103 2104 out: 2105 if (s != NULL && key != KEYC_FOCUS_OUT) 2106 server_client_update_latest(c); 2107 free(event); 2108 return (CMD_RETURN_NORMAL); 2109 } 2110 2111 /* Handle a key event. */ 2112 int 2113 server_client_handle_key(struct client *c, struct key_event *event) 2114 { 2115 struct session *s = c->session; 2116 struct cmdq_item *item; 2117 2118 /* Check the client is good to accept input. */ 2119 if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS)) 2120 return (0); 2121 2122 /* 2123 * Key presses in overlay mode and the command prompt are a special 2124 * case. The queue might be blocked so they need to be processed 2125 * immediately rather than queued. 2126 */ 2127 if (~c->flags & CLIENT_READONLY) { 2128 if (c->message_string != NULL) { 2129 if (c->message_ignore_keys) 2130 return (0); 2131 status_message_clear(c); 2132 } 2133 if (c->overlay_key != NULL) { 2134 switch (c->overlay_key(c, c->overlay_data, event)) { 2135 case 0: 2136 return (0); 2137 case 1: 2138 server_client_clear_overlay(c); 2139 return (0); 2140 } 2141 } 2142 server_client_clear_overlay(c); 2143 if (c->prompt_string != NULL) { 2144 if (status_prompt_key(c, event->key) == 0) 2145 return (0); 2146 } 2147 } 2148 2149 /* 2150 * Add the key to the queue so it happens after any commands queued by 2151 * previous keys. 2152 */ 2153 item = cmdq_get_callback(server_client_key_callback, event); 2154 cmdq_append(c, item); 2155 return (1); 2156 } 2157 2158 /* Client functions that need to happen every loop. */ 2159 void 2160 server_client_loop(void) 2161 { 2162 struct client *c; 2163 struct window *w; 2164 struct window_pane *wp; 2165 2166 /* Check for window resize. This is done before redrawing. */ 2167 RB_FOREACH(w, windows, &windows) 2168 server_client_check_window_resize(w); 2169 2170 /* Check clients. */ 2171 TAILQ_FOREACH(c, &clients, entry) { 2172 server_client_check_exit(c); 2173 if (c->session != NULL) { 2174 server_client_check_modes(c); 2175 server_client_check_redraw(c); 2176 server_client_reset_state(c); 2177 } 2178 } 2179 2180 /* 2181 * Any windows will have been redrawn as part of clients, so clear 2182 * their flags now. 2183 */ 2184 RB_FOREACH(w, windows, &windows) { 2185 TAILQ_FOREACH(wp, &w->panes, entry) { 2186 if (wp->fd != -1) { 2187 server_client_check_pane_resize(wp); 2188 server_client_check_pane_buffer(wp); 2189 } 2190 wp->flags &= ~PANE_REDRAW; 2191 } 2192 check_window_name(w); 2193 } 2194 } 2195 2196 /* Check if window needs to be resized. */ 2197 static void 2198 server_client_check_window_resize(struct window *w) 2199 { 2200 struct winlink *wl; 2201 2202 if (~w->flags & WINDOW_RESIZE) 2203 return; 2204 2205 TAILQ_FOREACH(wl, &w->winlinks, wentry) { 2206 if (wl->session->attached != 0 && wl->session->curw == wl) 2207 break; 2208 } 2209 if (wl == NULL) 2210 return; 2211 2212 log_debug("%s: resizing window @%u", __func__, w->id); 2213 resize_window(w, w->new_sx, w->new_sy, w->new_xpixel, w->new_ypixel); 2214 } 2215 2216 /* Resize timer event. */ 2217 static void 2218 server_client_resize_timer(__unused int fd, __unused short events, void *data) 2219 { 2220 struct window_pane *wp = data; 2221 2222 log_debug("%s: %%%u resize timer expired", __func__, wp->id); 2223 evtimer_del(&wp->resize_timer); 2224 } 2225 2226 /* Check if pane should be resized. */ 2227 static void 2228 server_client_check_pane_resize(struct window_pane *wp) 2229 { 2230 struct window_pane_resize *r; 2231 struct window_pane_resize *r1; 2232 struct window_pane_resize *first; 2233 struct window_pane_resize *last; 2234 struct timeval tv = { .tv_usec = 250000 }; 2235 2236 if (TAILQ_EMPTY(&wp->resize_queue)) 2237 return; 2238 2239 if (!event_initialized(&wp->resize_timer)) 2240 evtimer_set(&wp->resize_timer, server_client_resize_timer, wp); 2241 if (evtimer_pending(&wp->resize_timer, NULL)) 2242 return; 2243 2244 log_debug("%s: %%%u needs to be resized", __func__, wp->id); 2245 TAILQ_FOREACH(r, &wp->resize_queue, entry) { 2246 log_debug("queued resize: %ux%u -> %ux%u", r->osx, r->osy, 2247 r->sx, r->sy); 2248 } 2249 2250 /* 2251 * There are three cases that matter: 2252 * 2253 * - Only one resize. It can just be applied. 2254 * 2255 * - Multiple resizes and the ending size is different from the 2256 * starting size. We can discard all resizes except the most recent. 2257 * 2258 * - Multiple resizes and the ending size is the same as the starting 2259 * size. We must resize at least twice to force the application to 2260 * redraw. So apply the first and leave the last on the queue for 2261 * next time. 2262 */ 2263 first = TAILQ_FIRST(&wp->resize_queue); 2264 last = TAILQ_LAST(&wp->resize_queue, window_pane_resizes); 2265 if (first == last) { 2266 /* Only one resize. */ 2267 window_pane_send_resize(wp, first->sx, first->sy); 2268 TAILQ_REMOVE(&wp->resize_queue, first, entry); 2269 free(first); 2270 } else if (last->sx != first->osx || last->sy != first->osy) { 2271 /* Multiple resizes ending up with a different size. */ 2272 window_pane_send_resize(wp, last->sx, last->sy); 2273 TAILQ_FOREACH_SAFE(r, &wp->resize_queue, entry, r1) { 2274 TAILQ_REMOVE(&wp->resize_queue, r, entry); 2275 free(r); 2276 } 2277 } else { 2278 /* 2279 * Multiple resizes ending up with the same size. There will 2280 * not be more than one to the same size in succession so we 2281 * can just use the last-but-one on the list and leave the last 2282 * for later. We reduce the time until the next check to avoid 2283 * a long delay between the resizes. 2284 */ 2285 r = TAILQ_PREV(last, window_pane_resizes, entry); 2286 window_pane_send_resize(wp, r->sx, r->sy); 2287 TAILQ_FOREACH_SAFE(r, &wp->resize_queue, entry, r1) { 2288 if (r == last) 2289 break; 2290 TAILQ_REMOVE(&wp->resize_queue, r, entry); 2291 free(r); 2292 } 2293 tv.tv_usec = 10000; 2294 } 2295 evtimer_add(&wp->resize_timer, &tv); 2296 } 2297 2298 /* Check pane buffer size. */ 2299 static void 2300 server_client_check_pane_buffer(struct window_pane *wp) 2301 { 2302 struct evbuffer *evb = wp->event->input; 2303 size_t minimum; 2304 struct client *c; 2305 struct window_pane_offset *wpo; 2306 int off = 1, flag; 2307 u_int attached_clients = 0; 2308 size_t new_size; 2309 2310 /* 2311 * Work out the minimum used size. This is the most that can be removed 2312 * from the buffer. 2313 */ 2314 minimum = wp->offset.used; 2315 if (wp->pipe_fd != -1 && wp->pipe_offset.used < minimum) 2316 minimum = wp->pipe_offset.used; 2317 TAILQ_FOREACH(c, &clients, entry) { 2318 if (c->session == NULL) 2319 continue; 2320 attached_clients++; 2321 2322 if (~c->flags & CLIENT_CONTROL) { 2323 off = 0; 2324 continue; 2325 } 2326 wpo = control_pane_offset(c, wp, &flag); 2327 if (wpo == NULL) { 2328 if (!flag) 2329 off = 0; 2330 continue; 2331 } 2332 if (!flag) 2333 off = 0; 2334 2335 window_pane_get_new_data(wp, wpo, &new_size); 2336 log_debug("%s: %s has %zu bytes used and %zu left for %%%u", 2337 __func__, c->name, wpo->used - wp->base_offset, new_size, 2338 wp->id); 2339 if (wpo->used < minimum) 2340 minimum = wpo->used; 2341 } 2342 if (attached_clients == 0) 2343 off = 0; 2344 minimum -= wp->base_offset; 2345 if (minimum == 0) 2346 goto out; 2347 2348 /* Drain the buffer. */ 2349 log_debug("%s: %%%u has %zu minimum (of %zu) bytes used", __func__, 2350 wp->id, minimum, EVBUFFER_LENGTH(evb)); 2351 evbuffer_drain(evb, minimum); 2352 2353 /* 2354 * Adjust the base offset. If it would roll over, all the offsets into 2355 * the buffer need to be adjusted. 2356 */ 2357 if (wp->base_offset > SIZE_MAX - minimum) { 2358 log_debug("%s: %%%u base offset has wrapped", __func__, wp->id); 2359 wp->offset.used -= wp->base_offset; 2360 if (wp->pipe_fd != -1) 2361 wp->pipe_offset.used -= wp->base_offset; 2362 TAILQ_FOREACH(c, &clients, entry) { 2363 if (c->session == NULL || (~c->flags & CLIENT_CONTROL)) 2364 continue; 2365 wpo = control_pane_offset(c, wp, &flag); 2366 if (wpo != NULL && !flag) 2367 wpo->used -= wp->base_offset; 2368 } 2369 wp->base_offset = minimum; 2370 } else 2371 wp->base_offset += minimum; 2372 2373 out: 2374 /* 2375 * If there is data remaining, and there are no clients able to consume 2376 * it, do not read any more. This is true when there are attached 2377 * clients, all of which are control clients which are not able to 2378 * accept any more data. 2379 */ 2380 log_debug("%s: pane %%%u is %s", __func__, wp->id, off ? "off" : "on"); 2381 if (off) 2382 bufferevent_disable(wp->event, EV_READ); 2383 else 2384 bufferevent_enable(wp->event, EV_READ); 2385 } 2386 2387 /* 2388 * Update cursor position and mode settings. The scroll region and attributes 2389 * are cleared when idle (waiting for an event) as this is the most likely time 2390 * a user may interrupt tmux, for example with ~^Z in ssh(1). This is a 2391 * compromise between excessive resets and likelihood of an interrupt. 2392 * 2393 * tty_region/tty_reset/tty_update_mode already take care of not resetting 2394 * things that are already in their default state. 2395 */ 2396 static void 2397 server_client_reset_state(struct client *c) 2398 { 2399 struct tty *tty = &c->tty; 2400 struct window *w = c->session->curw->window; 2401 struct window_pane *wp = server_client_get_pane(c), *loop; 2402 struct screen *s = NULL; 2403 struct options *oo = c->session->options; 2404 int mode = 0, cursor, flags, n; 2405 u_int cx = 0, cy = 0, ox, oy, sx, sy; 2406 2407 if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED)) 2408 return; 2409 2410 /* Disable the block flag. */ 2411 flags = (tty->flags & TTY_BLOCK); 2412 tty->flags &= ~TTY_BLOCK; 2413 2414 /* Get mode from overlay if any, else from screen. */ 2415 if (c->overlay_draw != NULL) { 2416 if (c->overlay_mode != NULL) 2417 s = c->overlay_mode(c, c->overlay_data, &cx, &cy); 2418 } else 2419 s = wp->screen; 2420 if (s != NULL) 2421 mode = s->mode; 2422 if (log_get_level() != 0) { 2423 log_debug("%s: client %s mode %s", __func__, c->name, 2424 screen_mode_to_string(mode)); 2425 } 2426 2427 /* Reset region and margin. */ 2428 tty_region_off(tty); 2429 tty_margin_off(tty); 2430 2431 /* Move cursor to pane cursor and offset. */ 2432 if (c->prompt_string != NULL) { 2433 n = options_get_number(c->session->options, "status-position"); 2434 if (n == 0) 2435 cy = 0; 2436 else { 2437 n = status_line_size(c); 2438 if (n == 0) 2439 cy = tty->sy - 1; 2440 else 2441 cy = tty->sy - n; 2442 } 2443 cx = c->prompt_cursor; 2444 mode &= ~MODE_CURSOR; 2445 } else if (c->overlay_draw == NULL) { 2446 cursor = 0; 2447 tty_window_offset(tty, &ox, &oy, &sx, &sy); 2448 if (wp->xoff + s->cx >= ox && wp->xoff + s->cx <= ox + sx && 2449 wp->yoff + s->cy >= oy && wp->yoff + s->cy <= oy + sy) { 2450 cursor = 1; 2451 2452 cx = wp->xoff + s->cx - ox; 2453 cy = wp->yoff + s->cy - oy; 2454 2455 if (status_at_line(c) == 0) 2456 cy += status_line_size(c); 2457 } 2458 if (!cursor) 2459 mode &= ~MODE_CURSOR; 2460 } 2461 log_debug("%s: cursor to %u,%u", __func__, cx, cy); 2462 tty_cursor(tty, cx, cy); 2463 2464 /* 2465 * Set mouse mode if requested. To support dragging, always use button 2466 * mode. 2467 */ 2468 if (options_get_number(oo, "mouse")) { 2469 if (c->overlay_draw == NULL) { 2470 mode &= ~ALL_MOUSE_MODES; 2471 TAILQ_FOREACH(loop, &w->panes, entry) { 2472 if (loop->screen->mode & MODE_MOUSE_ALL) 2473 mode |= MODE_MOUSE_ALL; 2474 } 2475 } 2476 if (~mode & MODE_MOUSE_ALL) 2477 mode |= MODE_MOUSE_BUTTON; 2478 } 2479 2480 /* Clear bracketed paste mode if at the prompt. */ 2481 if (c->overlay_draw == NULL && c->prompt_string != NULL) 2482 mode &= ~MODE_BRACKETPASTE; 2483 2484 /* Set the terminal mode and reset attributes. */ 2485 tty_update_mode(tty, mode, s); 2486 tty_reset(tty); 2487 2488 /* All writing must be done, send a sync end (if it was started). */ 2489 tty_sync_end(tty); 2490 tty->flags |= flags; 2491 } 2492 2493 /* Repeat time callback. */ 2494 static void 2495 server_client_repeat_timer(__unused int fd, __unused short events, void *data) 2496 { 2497 struct client *c = data; 2498 2499 if (c->flags & CLIENT_REPEAT) { 2500 server_client_set_key_table(c, NULL); 2501 c->flags &= ~CLIENT_REPEAT; 2502 server_status_client(c); 2503 } 2504 } 2505 2506 /* Double-click callback. */ 2507 static void 2508 server_client_click_timer(__unused int fd, __unused short events, void *data) 2509 { 2510 struct client *c = data; 2511 struct key_event *event; 2512 2513 log_debug("click timer expired"); 2514 2515 if (c->flags & CLIENT_TRIPLECLICK) { 2516 /* 2517 * Waiting for a third click that hasn't happened, so this must 2518 * have been a double click. 2519 */ 2520 event = xmalloc(sizeof *event); 2521 event->key = KEYC_DOUBLECLICK; 2522 memcpy(&event->m, &c->click_event, sizeof event->m); 2523 if (!server_client_handle_key(c, event)) 2524 free(event); 2525 } 2526 c->flags &= ~(CLIENT_DOUBLECLICK|CLIENT_TRIPLECLICK); 2527 } 2528 2529 /* Check if client should be exited. */ 2530 static void 2531 server_client_check_exit(struct client *c) 2532 { 2533 struct client_file *cf; 2534 const char *name = c->exit_session; 2535 char *data; 2536 size_t size, msize; 2537 2538 if (c->flags & (CLIENT_DEAD|CLIENT_EXITED)) 2539 return; 2540 if (~c->flags & CLIENT_EXIT) 2541 return; 2542 2543 if (c->flags & CLIENT_CONTROL) { 2544 control_discard(c); 2545 if (!control_all_done(c)) 2546 return; 2547 } 2548 RB_FOREACH(cf, client_files, &c->files) { 2549 if (EVBUFFER_LENGTH(cf->buffer) != 0) 2550 return; 2551 } 2552 c->flags |= CLIENT_EXITED; 2553 2554 switch (c->exit_type) { 2555 case CLIENT_EXIT_RETURN: 2556 if (c->exit_message != NULL) 2557 msize = strlen(c->exit_message) + 1; 2558 else 2559 msize = 0; 2560 size = (sizeof c->retval) + msize; 2561 data = xmalloc(size); 2562 memcpy(data, &c->retval, sizeof c->retval); 2563 if (c->exit_message != NULL) 2564 memcpy(data + sizeof c->retval, c->exit_message, msize); 2565 proc_send(c->peer, MSG_EXIT, -1, data, size); 2566 free(data); 2567 break; 2568 case CLIENT_EXIT_SHUTDOWN: 2569 proc_send(c->peer, MSG_SHUTDOWN, -1, NULL, 0); 2570 break; 2571 case CLIENT_EXIT_DETACH: 2572 proc_send(c->peer, c->exit_msgtype, -1, name, strlen(name) + 1); 2573 break; 2574 } 2575 free(c->exit_session); 2576 free(c->exit_message); 2577 } 2578 2579 /* Redraw timer callback. */ 2580 static void 2581 server_client_redraw_timer(__unused int fd, __unused short events, 2582 __unused void *data) 2583 { 2584 log_debug("redraw timer fired"); 2585 } 2586 2587 /* 2588 * Check if modes need to be updated. Only modes in the current window are 2589 * updated and it is done when the status line is redrawn. 2590 */ 2591 static void 2592 server_client_check_modes(struct client *c) 2593 { 2594 struct window *w = c->session->curw->window; 2595 struct window_pane *wp; 2596 struct window_mode_entry *wme; 2597 2598 if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED)) 2599 return; 2600 if (~c->flags & CLIENT_REDRAWSTATUS) 2601 return; 2602 TAILQ_FOREACH(wp, &w->panes, entry) { 2603 wme = TAILQ_FIRST(&wp->modes); 2604 if (wme != NULL && wme->mode->update != NULL) 2605 wme->mode->update(wme); 2606 } 2607 } 2608 2609 /* Check for client redraws. */ 2610 static void 2611 server_client_check_redraw(struct client *c) 2612 { 2613 struct session *s = c->session; 2614 struct tty *tty = &c->tty; 2615 struct window *w = c->session->curw->window; 2616 struct window_pane *wp; 2617 int needed, tty_flags, mode = tty->mode; 2618 uint64_t client_flags = 0; 2619 int redraw; 2620 u_int bit = 0; 2621 struct timeval tv = { .tv_usec = 1000 }; 2622 static struct event ev; 2623 size_t left; 2624 2625 if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED)) 2626 return; 2627 if (c->flags & CLIENT_ALLREDRAWFLAGS) { 2628 log_debug("%s: redraw%s%s%s%s%s", c->name, 2629 (c->flags & CLIENT_REDRAWWINDOW) ? " window" : "", 2630 (c->flags & CLIENT_REDRAWSTATUS) ? " status" : "", 2631 (c->flags & CLIENT_REDRAWBORDERS) ? " borders" : "", 2632 (c->flags & CLIENT_REDRAWOVERLAY) ? " overlay" : "", 2633 (c->flags & CLIENT_REDRAWPANES) ? " panes" : ""); 2634 } 2635 2636 /* 2637 * If there is outstanding data, defer the redraw until it has been 2638 * consumed. We can just add a timer to get out of the event loop and 2639 * end up back here. 2640 */ 2641 needed = 0; 2642 if (c->flags & CLIENT_ALLREDRAWFLAGS) 2643 needed = 1; 2644 else { 2645 TAILQ_FOREACH(wp, &w->panes, entry) { 2646 if (wp->flags & PANE_REDRAW) { 2647 needed = 1; 2648 break; 2649 } 2650 } 2651 if (needed) 2652 client_flags |= CLIENT_REDRAWPANES; 2653 } 2654 if (needed && (left = EVBUFFER_LENGTH(tty->out)) != 0) { 2655 log_debug("%s: redraw deferred (%zu left)", c->name, left); 2656 if (!evtimer_initialized(&ev)) 2657 evtimer_set(&ev, server_client_redraw_timer, NULL); 2658 if (!evtimer_pending(&ev, NULL)) { 2659 log_debug("redraw timer started"); 2660 evtimer_add(&ev, &tv); 2661 } 2662 2663 if (~c->flags & CLIENT_REDRAWWINDOW) { 2664 TAILQ_FOREACH(wp, &w->panes, entry) { 2665 if (wp->flags & PANE_REDRAW) { 2666 log_debug("%s: pane %%%u needs redraw", 2667 c->name, wp->id); 2668 c->redraw_panes |= (1 << bit); 2669 } 2670 if (++bit == 64) { 2671 /* 2672 * If more that 64 panes, give up and 2673 * just redraw the window. 2674 */ 2675 client_flags &= CLIENT_REDRAWPANES; 2676 client_flags |= CLIENT_REDRAWWINDOW; 2677 break; 2678 } 2679 } 2680 if (c->redraw_panes != 0) 2681 c->flags |= CLIENT_REDRAWPANES; 2682 } 2683 c->flags |= client_flags; 2684 return; 2685 } else if (needed) 2686 log_debug("%s: redraw needed", c->name); 2687 2688 tty_flags = tty->flags & (TTY_BLOCK|TTY_FREEZE|TTY_NOCURSOR); 2689 tty->flags = (tty->flags & ~(TTY_BLOCK|TTY_FREEZE))|TTY_NOCURSOR; 2690 2691 if (~c->flags & CLIENT_REDRAWWINDOW) { 2692 /* 2693 * If not redrawing the entire window, check whether each pane 2694 * needs to be redrawn. 2695 */ 2696 TAILQ_FOREACH(wp, &w->panes, entry) { 2697 redraw = 0; 2698 if (wp->flags & PANE_REDRAW) 2699 redraw = 1; 2700 else if (c->flags & CLIENT_REDRAWPANES) 2701 redraw = !!(c->redraw_panes & (1 << bit)); 2702 bit++; 2703 if (!redraw) 2704 continue; 2705 log_debug("%s: redrawing pane %%%u", __func__, wp->id); 2706 screen_redraw_pane(c, wp); 2707 } 2708 c->redraw_panes = 0; 2709 c->flags &= ~CLIENT_REDRAWPANES; 2710 } 2711 2712 if (c->flags & CLIENT_ALLREDRAWFLAGS) { 2713 if (options_get_number(s->options, "set-titles")) { 2714 server_client_set_title(c); 2715 server_client_set_path(c); 2716 } 2717 screen_redraw_screen(c); 2718 } 2719 2720 tty->flags = (tty->flags & ~TTY_NOCURSOR)|(tty_flags & TTY_NOCURSOR); 2721 tty_update_mode(tty, mode, NULL); 2722 tty->flags = (tty->flags & ~(TTY_BLOCK|TTY_FREEZE|TTY_NOCURSOR))| 2723 tty_flags; 2724 2725 c->flags &= ~(CLIENT_ALLREDRAWFLAGS|CLIENT_STATUSFORCE); 2726 2727 if (needed) { 2728 /* 2729 * We would have deferred the redraw unless the output buffer 2730 * was empty, so we can record how many bytes the redraw 2731 * generated. 2732 */ 2733 c->redraw = EVBUFFER_LENGTH(tty->out); 2734 log_debug("%s: redraw added %zu bytes", c->name, c->redraw); 2735 } 2736 } 2737 2738 /* Set client title. */ 2739 static void 2740 server_client_set_title(struct client *c) 2741 { 2742 struct session *s = c->session; 2743 const char *template; 2744 char *title; 2745 struct format_tree *ft; 2746 2747 template = options_get_string(s->options, "set-titles-string"); 2748 2749 ft = format_create(c, NULL, FORMAT_NONE, 0); 2750 format_defaults(ft, c, NULL, NULL, NULL); 2751 2752 title = format_expand_time(ft, template); 2753 if (c->title == NULL || strcmp(title, c->title) != 0) { 2754 free(c->title); 2755 c->title = xstrdup(title); 2756 tty_set_title(&c->tty, c->title); 2757 } 2758 free(title); 2759 2760 format_free(ft); 2761 } 2762 2763 /* Set client path. */ 2764 static void 2765 server_client_set_path(struct client *c) 2766 { 2767 struct session *s = c->session; 2768 const char *path; 2769 2770 if (s->curw == NULL) 2771 return; 2772 if (s->curw->window->active->base.path == NULL) 2773 path = ""; 2774 else 2775 path = s->curw->window->active->base.path; 2776 if (c->path == NULL || strcmp(path, c->path) != 0) { 2777 free(c->path); 2778 c->path = xstrdup(path); 2779 tty_set_path(&c->tty, c->path); 2780 } 2781 } 2782 2783 /* Dispatch message from client. */ 2784 static void 2785 server_client_dispatch(struct imsg *imsg, void *arg) 2786 { 2787 struct client *c = arg; 2788 ssize_t datalen; 2789 struct session *s; 2790 2791 if (c->flags & CLIENT_DEAD) 2792 return; 2793 2794 if (imsg == NULL) { 2795 server_client_lost(c); 2796 return; 2797 } 2798 2799 datalen = imsg->hdr.len - IMSG_HEADER_SIZE; 2800 2801 switch (imsg->hdr.type) { 2802 case MSG_IDENTIFY_CLIENTPID: 2803 case MSG_IDENTIFY_CWD: 2804 case MSG_IDENTIFY_ENVIRON: 2805 case MSG_IDENTIFY_FEATURES: 2806 case MSG_IDENTIFY_FLAGS: 2807 case MSG_IDENTIFY_LONGFLAGS: 2808 case MSG_IDENTIFY_STDIN: 2809 case MSG_IDENTIFY_STDOUT: 2810 case MSG_IDENTIFY_TERM: 2811 case MSG_IDENTIFY_TERMINFO: 2812 case MSG_IDENTIFY_TTYNAME: 2813 case MSG_IDENTIFY_DONE: 2814 server_client_dispatch_identify(c, imsg); 2815 break; 2816 case MSG_COMMAND: 2817 server_client_dispatch_command(c, imsg); 2818 break; 2819 case MSG_RESIZE: 2820 if (datalen != 0) 2821 fatalx("bad MSG_RESIZE size"); 2822 2823 if (c->flags & CLIENT_CONTROL) 2824 break; 2825 server_client_update_latest(c); 2826 tty_resize(&c->tty); 2827 tty_repeat_requests(&c->tty); 2828 recalculate_sizes(); 2829 if (c->overlay_resize == NULL) 2830 server_client_clear_overlay(c); 2831 else 2832 c->overlay_resize(c, c->overlay_data); 2833 server_redraw_client(c); 2834 if (c->session != NULL) 2835 notify_client("client-resized", c); 2836 break; 2837 case MSG_EXITING: 2838 if (datalen != 0) 2839 fatalx("bad MSG_EXITING size"); 2840 server_client_set_session(c, NULL); 2841 recalculate_sizes(); 2842 tty_close(&c->tty); 2843 proc_send(c->peer, MSG_EXITED, -1, NULL, 0); 2844 break; 2845 case MSG_WAKEUP: 2846 case MSG_UNLOCK: 2847 if (datalen != 0) 2848 fatalx("bad MSG_WAKEUP size"); 2849 2850 if (!(c->flags & CLIENT_SUSPENDED)) 2851 break; 2852 c->flags &= ~CLIENT_SUSPENDED; 2853 2854 if (c->fd == -1 || c->session == NULL) /* exited already */ 2855 break; 2856 s = c->session; 2857 2858 if (gettimeofday(&c->activity_time, NULL) != 0) 2859 fatal("gettimeofday failed"); 2860 2861 tty_start_tty(&c->tty); 2862 server_redraw_client(c); 2863 recalculate_sizes(); 2864 2865 if (s != NULL) 2866 session_update_activity(s, &c->activity_time); 2867 break; 2868 case MSG_SHELL: 2869 if (datalen != 0) 2870 fatalx("bad MSG_SHELL size"); 2871 2872 server_client_dispatch_shell(c); 2873 break; 2874 case MSG_WRITE_READY: 2875 file_write_ready(&c->files, imsg); 2876 break; 2877 case MSG_READ: 2878 file_read_data(&c->files, imsg); 2879 break; 2880 case MSG_READ_DONE: 2881 file_read_done(&c->files, imsg); 2882 break; 2883 } 2884 } 2885 2886 /* Callback when command is not allowed. */ 2887 static enum cmd_retval 2888 server_client_read_only(struct cmdq_item *item, __unused void *data) 2889 { 2890 cmdq_error(item, "client is read-only"); 2891 return (CMD_RETURN_ERROR); 2892 } 2893 2894 /* Callback when command is done. */ 2895 static enum cmd_retval 2896 server_client_command_done(struct cmdq_item *item, __unused void *data) 2897 { 2898 struct client *c = cmdq_get_client(item); 2899 2900 if (~c->flags & CLIENT_ATTACHED) 2901 c->flags |= CLIENT_EXIT; 2902 else if (~c->flags & CLIENT_EXIT) { 2903 if (c->flags & CLIENT_CONTROL) 2904 control_ready(c); 2905 tty_send_requests(&c->tty); 2906 } 2907 return (CMD_RETURN_NORMAL); 2908 } 2909 2910 /* Handle command message. */ 2911 static void 2912 server_client_dispatch_command(struct client *c, struct imsg *imsg) 2913 { 2914 struct msg_command data; 2915 char *buf; 2916 size_t len; 2917 int argc; 2918 char **argv, *cause; 2919 struct cmd_parse_result *pr; 2920 struct args_value *values; 2921 struct cmdq_item *new_item; 2922 2923 if (c->flags & CLIENT_EXIT) 2924 return; 2925 2926 if (imsg->hdr.len - IMSG_HEADER_SIZE < sizeof data) 2927 fatalx("bad MSG_COMMAND size"); 2928 memcpy(&data, imsg->data, sizeof data); 2929 2930 buf = (char *)imsg->data + sizeof data; 2931 len = imsg->hdr.len - IMSG_HEADER_SIZE - sizeof data; 2932 if (len > 0 && buf[len - 1] != '\0') 2933 fatalx("bad MSG_COMMAND string"); 2934 2935 argc = data.argc; 2936 if (cmd_unpack_argv(buf, len, argc, &argv) != 0) { 2937 cause = xstrdup("command too long"); 2938 goto error; 2939 } 2940 2941 if (argc == 0) { 2942 argc = 1; 2943 argv = xcalloc(1, sizeof *argv); 2944 *argv = xstrdup("new-session"); 2945 } 2946 2947 values = args_from_vector(argc, argv); 2948 pr = cmd_parse_from_arguments(values, argc, NULL); 2949 switch (pr->status) { 2950 case CMD_PARSE_ERROR: 2951 cause = pr->error; 2952 goto error; 2953 case CMD_PARSE_SUCCESS: 2954 break; 2955 } 2956 args_free_values(values, argc); 2957 free(values); 2958 cmd_free_argv(argc, argv); 2959 2960 if ((c->flags & CLIENT_READONLY) && 2961 !cmd_list_all_have(pr->cmdlist, CMD_READONLY)) 2962 new_item = cmdq_get_callback(server_client_read_only, NULL); 2963 else 2964 new_item = cmdq_get_command(pr->cmdlist, NULL); 2965 cmdq_append(c, new_item); 2966 cmdq_append(c, cmdq_get_callback(server_client_command_done, NULL)); 2967 2968 cmd_list_free(pr->cmdlist); 2969 return; 2970 2971 error: 2972 cmd_free_argv(argc, argv); 2973 2974 cmdq_append(c, cmdq_get_error(cause)); 2975 free(cause); 2976 2977 c->flags |= CLIENT_EXIT; 2978 } 2979 2980 /* Handle identify message. */ 2981 static void 2982 server_client_dispatch_identify(struct client *c, struct imsg *imsg) 2983 { 2984 const char *data, *home; 2985 size_t datalen; 2986 int flags, feat; 2987 uint64_t longflags; 2988 char *name; 2989 2990 if (c->flags & CLIENT_IDENTIFIED) 2991 fatalx("out-of-order identify message"); 2992 2993 data = imsg->data; 2994 datalen = imsg->hdr.len - IMSG_HEADER_SIZE; 2995 2996 switch (imsg->hdr.type) { 2997 case MSG_IDENTIFY_FEATURES: 2998 if (datalen != sizeof feat) 2999 fatalx("bad MSG_IDENTIFY_FEATURES size"); 3000 memcpy(&feat, data, sizeof feat); 3001 c->term_features |= feat; 3002 log_debug("client %p IDENTIFY_FEATURES %s", c, 3003 tty_get_features(feat)); 3004 break; 3005 case MSG_IDENTIFY_FLAGS: 3006 if (datalen != sizeof flags) 3007 fatalx("bad MSG_IDENTIFY_FLAGS size"); 3008 memcpy(&flags, data, sizeof flags); 3009 c->flags |= flags; 3010 log_debug("client %p IDENTIFY_FLAGS %#x", c, flags); 3011 break; 3012 case MSG_IDENTIFY_LONGFLAGS: 3013 if (datalen != sizeof longflags) 3014 fatalx("bad MSG_IDENTIFY_LONGFLAGS size"); 3015 memcpy(&longflags, data, sizeof longflags); 3016 c->flags |= longflags; 3017 log_debug("client %p IDENTIFY_LONGFLAGS %#llx", c, 3018 (unsigned long long)longflags); 3019 break; 3020 case MSG_IDENTIFY_TERM: 3021 if (datalen == 0 || data[datalen - 1] != '\0') 3022 fatalx("bad MSG_IDENTIFY_TERM string"); 3023 if (*data == '\0') 3024 c->term_name = xstrdup("unknown"); 3025 else 3026 c->term_name = xstrdup(data); 3027 log_debug("client %p IDENTIFY_TERM %s", c, data); 3028 break; 3029 case MSG_IDENTIFY_TERMINFO: 3030 if (datalen == 0 || data[datalen - 1] != '\0') 3031 fatalx("bad MSG_IDENTIFY_TERMINFO string"); 3032 c->term_caps = xreallocarray(c->term_caps, c->term_ncaps + 1, 3033 sizeof *c->term_caps); 3034 c->term_caps[c->term_ncaps++] = xstrdup(data); 3035 log_debug("client %p IDENTIFY_TERMINFO %s", c, data); 3036 break; 3037 case MSG_IDENTIFY_TTYNAME: 3038 if (datalen == 0 || data[datalen - 1] != '\0') 3039 fatalx("bad MSG_IDENTIFY_TTYNAME string"); 3040 c->ttyname = xstrdup(data); 3041 log_debug("client %p IDENTIFY_TTYNAME %s", c, data); 3042 break; 3043 case MSG_IDENTIFY_CWD: 3044 if (datalen == 0 || data[datalen - 1] != '\0') 3045 fatalx("bad MSG_IDENTIFY_CWD string"); 3046 if (access(data, X_OK) == 0) 3047 c->cwd = xstrdup(data); 3048 else if ((home = find_home()) != NULL) 3049 c->cwd = xstrdup(home); 3050 else 3051 c->cwd = xstrdup("/"); 3052 log_debug("client %p IDENTIFY_CWD %s", c, data); 3053 break; 3054 case MSG_IDENTIFY_STDIN: 3055 if (datalen != 0) 3056 fatalx("bad MSG_IDENTIFY_STDIN size"); 3057 c->fd = imsg_get_fd(imsg); 3058 log_debug("client %p IDENTIFY_STDIN %d", c, c->fd); 3059 break; 3060 case MSG_IDENTIFY_STDOUT: 3061 if (datalen != 0) 3062 fatalx("bad MSG_IDENTIFY_STDOUT size"); 3063 c->out_fd = imsg_get_fd(imsg); 3064 log_debug("client %p IDENTIFY_STDOUT %d", c, c->out_fd); 3065 break; 3066 case MSG_IDENTIFY_ENVIRON: 3067 if (datalen == 0 || data[datalen - 1] != '\0') 3068 fatalx("bad MSG_IDENTIFY_ENVIRON string"); 3069 if (strchr(data, '=') != NULL) 3070 environ_put(c->environ, data, 0); 3071 log_debug("client %p IDENTIFY_ENVIRON %s", c, data); 3072 break; 3073 case MSG_IDENTIFY_CLIENTPID: 3074 if (datalen != sizeof c->pid) 3075 fatalx("bad MSG_IDENTIFY_CLIENTPID size"); 3076 memcpy(&c->pid, data, sizeof c->pid); 3077 log_debug("client %p IDENTIFY_CLIENTPID %ld", c, (long)c->pid); 3078 break; 3079 default: 3080 break; 3081 } 3082 3083 if (imsg->hdr.type != MSG_IDENTIFY_DONE) 3084 return; 3085 c->flags |= CLIENT_IDENTIFIED; 3086 3087 if (*c->ttyname != '\0') 3088 name = xstrdup(c->ttyname); 3089 else 3090 xasprintf(&name, "client-%ld", (long)c->pid); 3091 c->name = name; 3092 log_debug("client %p name is %s", c, c->name); 3093 3094 #ifdef __CYGWIN__ 3095 c->fd = open(c->ttyname, O_RDWR|O_NOCTTY); 3096 #endif 3097 3098 if (c->flags & CLIENT_CONTROL) 3099 control_start(c); 3100 else if (c->fd != -1) { 3101 if (tty_init(&c->tty, c) != 0) { 3102 close(c->fd); 3103 c->fd = -1; 3104 } else { 3105 tty_resize(&c->tty); 3106 c->flags |= CLIENT_TERMINAL; 3107 } 3108 close(c->out_fd); 3109 c->out_fd = -1; 3110 } 3111 3112 /* 3113 * If this is the first client, load configuration files. Any later 3114 * clients are allowed to continue with their command even if the 3115 * config has not been loaded - they might have been run from inside it 3116 */ 3117 if ((~c->flags & CLIENT_EXIT) && 3118 !cfg_finished && 3119 c == TAILQ_FIRST(&clients)) 3120 start_cfg(); 3121 } 3122 3123 /* Handle shell message. */ 3124 static void 3125 server_client_dispatch_shell(struct client *c) 3126 { 3127 const char *shell; 3128 3129 shell = options_get_string(global_s_options, "default-shell"); 3130 if (!checkshell(shell)) 3131 shell = _PATH_BSHELL; 3132 proc_send(c->peer, MSG_SHELL, -1, shell, strlen(shell) + 1); 3133 3134 proc_kill_peer(c->peer); 3135 } 3136 3137 /* Get client working directory. */ 3138 const char * 3139 server_client_get_cwd(struct client *c, struct session *s) 3140 { 3141 const char *home; 3142 3143 if (!cfg_finished && cfg_client != NULL) 3144 return (cfg_client->cwd); 3145 if (c != NULL && c->session == NULL && c->cwd != NULL) 3146 return (c->cwd); 3147 if (s != NULL && s->cwd != NULL) 3148 return (s->cwd); 3149 if (c != NULL && (s = c->session) != NULL && s->cwd != NULL) 3150 return (s->cwd); 3151 if ((home = find_home()) != NULL) 3152 return (home); 3153 return ("/"); 3154 } 3155 3156 /* Get control client flags. */ 3157 static uint64_t 3158 server_client_control_flags(struct client *c, const char *next) 3159 { 3160 if (strcmp(next, "pause-after") == 0) { 3161 c->pause_age = 0; 3162 return (CLIENT_CONTROL_PAUSEAFTER); 3163 } 3164 if (sscanf(next, "pause-after=%u", &c->pause_age) == 1) { 3165 c->pause_age *= 1000; 3166 return (CLIENT_CONTROL_PAUSEAFTER); 3167 } 3168 if (strcmp(next, "no-output") == 0) 3169 return (CLIENT_CONTROL_NOOUTPUT); 3170 if (strcmp(next, "wait-exit") == 0) 3171 return (CLIENT_CONTROL_WAITEXIT); 3172 return (0); 3173 } 3174 3175 /* Set client flags. */ 3176 void 3177 server_client_set_flags(struct client *c, const char *flags) 3178 { 3179 char *s, *copy, *next; 3180 uint64_t flag; 3181 int not; 3182 3183 s = copy = xstrdup(flags); 3184 while ((next = strsep(&s, ",")) != NULL) { 3185 not = (*next == '!'); 3186 if (not) 3187 next++; 3188 3189 if (c->flags & CLIENT_CONTROL) 3190 flag = server_client_control_flags(c, next); 3191 else 3192 flag = 0; 3193 if (strcmp(next, "read-only") == 0) 3194 flag = CLIENT_READONLY; 3195 else if (strcmp(next, "ignore-size") == 0) 3196 flag = CLIENT_IGNORESIZE; 3197 else if (strcmp(next, "active-pane") == 0) 3198 flag = CLIENT_ACTIVEPANE; 3199 if (flag == 0) 3200 continue; 3201 3202 log_debug("client %s set flag %s", c->name, next); 3203 if (not) { 3204 if (c->flags & CLIENT_READONLY) 3205 flag &= ~CLIENT_READONLY; 3206 c->flags &= ~flag; 3207 } else 3208 c->flags |= flag; 3209 if (flag == CLIENT_CONTROL_NOOUTPUT) 3210 control_reset_offsets(c); 3211 } 3212 free(copy); 3213 proc_send(c->peer, MSG_FLAGS, -1, &c->flags, sizeof c->flags); 3214 } 3215 3216 /* Get client flags. This is only flags useful to show to users. */ 3217 const char * 3218 server_client_get_flags(struct client *c) 3219 { 3220 static char s[256]; 3221 char tmp[32]; 3222 3223 *s = '\0'; 3224 if (c->flags & CLIENT_ATTACHED) 3225 strlcat(s, "attached,", sizeof s); 3226 if (c->flags & CLIENT_FOCUSED) 3227 strlcat(s, "focused,", sizeof s); 3228 if (c->flags & CLIENT_CONTROL) 3229 strlcat(s, "control-mode,", sizeof s); 3230 if (c->flags & CLIENT_IGNORESIZE) 3231 strlcat(s, "ignore-size,", sizeof s); 3232 if (c->flags & CLIENT_CONTROL_NOOUTPUT) 3233 strlcat(s, "no-output,", sizeof s); 3234 if (c->flags & CLIENT_CONTROL_WAITEXIT) 3235 strlcat(s, "wait-exit,", sizeof s); 3236 if (c->flags & CLIENT_CONTROL_PAUSEAFTER) { 3237 xsnprintf(tmp, sizeof tmp, "pause-after=%u,", 3238 c->pause_age / 1000); 3239 strlcat(s, tmp, sizeof s); 3240 } 3241 if (c->flags & CLIENT_READONLY) 3242 strlcat(s, "read-only,", sizeof s); 3243 if (c->flags & CLIENT_ACTIVEPANE) 3244 strlcat(s, "active-pane,", sizeof s); 3245 if (c->flags & CLIENT_SUSPENDED) 3246 strlcat(s, "suspended,", sizeof s); 3247 if (c->flags & CLIENT_UTF8) 3248 strlcat(s, "UTF-8,", sizeof s); 3249 if (*s != '\0') 3250 s[strlen(s) - 1] = '\0'; 3251 return (s); 3252 } 3253 3254 /* Get client window. */ 3255 struct client_window * 3256 server_client_get_client_window(struct client *c, u_int id) 3257 { 3258 struct client_window cw = { .window = id }; 3259 3260 return (RB_FIND(client_windows, &c->windows, &cw)); 3261 } 3262 3263 /* Add client window. */ 3264 struct client_window * 3265 server_client_add_client_window(struct client *c, u_int id) 3266 { 3267 struct client_window *cw; 3268 3269 cw = server_client_get_client_window(c, id); 3270 if (cw == NULL) { 3271 cw = xcalloc(1, sizeof *cw); 3272 cw->window = id; 3273 RB_INSERT(client_windows, &c->windows, cw); 3274 } 3275 return (cw); 3276 } 3277 3278 /* Get client active pane. */ 3279 struct window_pane * 3280 server_client_get_pane(struct client *c) 3281 { 3282 struct session *s = c->session; 3283 struct client_window *cw; 3284 3285 if (s == NULL) 3286 return (NULL); 3287 3288 if (~c->flags & CLIENT_ACTIVEPANE) 3289 return (s->curw->window->active); 3290 cw = server_client_get_client_window(c, s->curw->window->id); 3291 if (cw == NULL) 3292 return (s->curw->window->active); 3293 return (cw->pane); 3294 } 3295 3296 /* Set client active pane. */ 3297 void 3298 server_client_set_pane(struct client *c, struct window_pane *wp) 3299 { 3300 struct session *s = c->session; 3301 struct client_window *cw; 3302 3303 if (s == NULL) 3304 return; 3305 3306 cw = server_client_add_client_window(c, s->curw->window->id); 3307 cw->pane = wp; 3308 log_debug("%s pane now %%%u", c->name, wp->id); 3309 } 3310 3311 /* Remove pane from client lists. */ 3312 void 3313 server_client_remove_pane(struct window_pane *wp) 3314 { 3315 struct client *c; 3316 struct window *w = wp->window; 3317 struct client_window *cw; 3318 3319 TAILQ_FOREACH(c, &clients, entry) { 3320 cw = server_client_get_client_window(c, w->id); 3321 if (cw != NULL && cw->pane == wp) { 3322 RB_REMOVE(client_windows, &c->windows, cw); 3323 free(cw); 3324 } 3325 } 3326 } 3327 3328 /* Print to a client. */ 3329 void 3330 server_client_print(struct client *c, int parse, struct evbuffer *evb) 3331 { 3332 void *data = EVBUFFER_DATA(evb); 3333 size_t size = EVBUFFER_LENGTH(evb); 3334 struct window_pane *wp; 3335 struct window_mode_entry *wme; 3336 char *sanitized, *msg, *line; 3337 3338 if (!parse) { 3339 utf8_stravisx(&msg, data, size, 3340 VIS_OCTAL|VIS_CSTYLE|VIS_NOSLASH); 3341 log_debug("%s: %s", __func__, msg); 3342 } else { 3343 msg = (char *)EVBUFFER_DATA(evb); 3344 if (msg[size - 1] != '\0') 3345 evbuffer_add(evb, "", 1); 3346 } 3347 3348 if (c == NULL) 3349 goto out; 3350 3351 if (c->session == NULL || (c->flags & CLIENT_CONTROL)) { 3352 if (~c->flags & CLIENT_UTF8) { 3353 sanitized = utf8_sanitize(msg); 3354 if (c->flags & CLIENT_CONTROL) 3355 control_write(c, "%s", sanitized); 3356 else 3357 file_print(c, "%s\n", sanitized); 3358 free(sanitized); 3359 } else { 3360 if (c->flags & CLIENT_CONTROL) 3361 control_write(c, "%s", msg); 3362 else 3363 file_print(c, "%s\n", msg); 3364 } 3365 goto out; 3366 } 3367 3368 wp = server_client_get_pane(c); 3369 wme = TAILQ_FIRST(&wp->modes); 3370 if (wme == NULL || wme->mode != &window_view_mode) 3371 window_pane_set_mode(wp, NULL, &window_view_mode, NULL, NULL); 3372 if (parse) { 3373 do { 3374 line = evbuffer_readln(evb, NULL, EVBUFFER_EOL_LF); 3375 if (line != NULL) { 3376 window_copy_add(wp, 1, "%s", line); 3377 free(line); 3378 } 3379 } while (line != NULL); 3380 3381 size = EVBUFFER_LENGTH(evb); 3382 if (size != 0) { 3383 line = (char *)EVBUFFER_DATA(evb); 3384 window_copy_add(wp, 1, "%.*s", (int)size, line); 3385 } 3386 } else 3387 window_copy_add(wp, 0, "%s", msg); 3388 3389 out: 3390 if (!parse) 3391 free(msg); 3392 } 3393