comparison src/terminal.c @ 13448:a62b0bbc8834 v8.0.1598

patch 8.0.1598: cannot select text in a terminal with the mouse commit https://github.com/vim/vim/commit/c48369c3fc507f398abbc933a60f653c6abe6701 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Mar 11 19:30:45 2018 +0100 patch 8.0.1598: cannot select text in a terminal with the mouse Problem: Cannot select text in a terminal with the mouse. Solution: When a job in a terminal is not consuming mouse events, use them for modeless selection. Also stop Insert mode when clicking in a terminal window.
author Christian Brabandt <cb@256bit.org>
date Sun, 11 Mar 2018 19:45:05 +0100
parents 9f06f7aca74c
children 0e7a56b18d61
comparison
equal deleted inserted replaced
13447:17eebaa3188f 13448:a62b0bbc8834
36 * that buffer, attributes come from the scrollback buffer tl_scrollback. 36 * that buffer, attributes come from the scrollback buffer tl_scrollback.
37 * When the buffer is changed it is turned into a normal buffer, the attributes 37 * When the buffer is changed it is turned into a normal buffer, the attributes
38 * in tl_scrollback are no longer used. 38 * in tl_scrollback are no longer used.
39 * 39 *
40 * TODO: 40 * TODO:
41 * - if the job in the terminal does not support the mouse, we can use the
42 * mouse in the Terminal window for copy/paste and scrolling.
43 * - When using 'termguicolors' still use the 16 ANSI colors as-is. Helps for 41 * - When using 'termguicolors' still use the 16 ANSI colors as-is. Helps for
44 * - In the GUI use a terminal emulator for :!cmd. Make the height the same as 42 * - In the GUI use a terminal emulator for :!cmd. Make the height the same as
45 * the window and position it higher up when it gets filled, so it looks like 43 * the window and position it higher up when it gets filled, so it looks like
46 * the text scrolls up. 44 * the text scrolls up.
47 * - implement term_setsize() 45 * - implement term_setsize()
895 893
896 vterm_mouse_move(vterm, mouse_row - W_WINROW(curwin), 894 vterm_mouse_move(vterm, mouse_row - W_WINROW(curwin),
897 mouse_col - curwin->w_wincol, mod); 895 mouse_col - curwin->w_wincol, mod);
898 if (button != 0) 896 if (button != 0)
899 vterm_mouse_button(vterm, button, pressed, mod); 897 vterm_mouse_button(vterm, button, pressed, mod);
898 return TRUE;
899 }
900
901 static int enter_mouse_col = -1;
902 static int enter_mouse_row = -1;
903
904 /*
905 * Handle a mouse click, drag or release.
906 * Return TRUE when a mouse event is sent to the terminal.
907 */
908 static int
909 term_mouse_click(VTerm *vterm, int key)
910 {
911 #if defined(FEAT_CLIPBOARD)
912 /* For modeless selection mouse drag and release events are ignored, unless
913 * they are preceded with a mouse down event */
914 static int ignore_drag_release = TRUE;
915 VTermMouseState mouse_state;
916
917 vterm_state_get_mousestate(vterm_obtain_state(vterm), &mouse_state);
918 if (mouse_state.flags == 0)
919 {
920 /* Terminal is not using the mouse, use modeless selection. */
921 switch (key)
922 {
923 case K_LEFTDRAG:
924 case K_LEFTRELEASE:
925 case K_RIGHTDRAG:
926 case K_RIGHTRELEASE:
927 /* Ignore drag and release events when the button-down wasn't
928 * seen before. */
929 if (ignore_drag_release)
930 {
931 int save_mouse_col, save_mouse_row;
932
933 if (enter_mouse_col < 0)
934 break;
935
936 /* mouse click in the window gave us focus, handle that
937 * click now */
938 save_mouse_col = mouse_col;
939 save_mouse_row = mouse_row;
940 mouse_col = enter_mouse_col;
941 mouse_row = enter_mouse_row;
942 clip_modeless(MOUSE_LEFT, TRUE, FALSE);
943 mouse_col = save_mouse_col;
944 mouse_row = save_mouse_row;
945 }
946 /* FALLTHROUGH */
947 case K_LEFTMOUSE:
948 case K_RIGHTMOUSE:
949 if (key == K_LEFTRELEASE || key == K_RIGHTRELEASE)
950 ignore_drag_release = TRUE;
951 else
952 ignore_drag_release = FALSE;
953 /* Should we call mouse_has() here? */
954 if (clip_star.available)
955 {
956 int button, is_click, is_drag;
957
958 button = get_mouse_button(KEY2TERMCAP1(key),
959 &is_click, &is_drag);
960 if (mouse_model_popup() && button == MOUSE_LEFT
961 && (mod_mask & MOD_MASK_SHIFT))
962 {
963 /* Translate shift-left to right button. */
964 button = MOUSE_RIGHT;
965 mod_mask &= ~MOD_MASK_SHIFT;
966 }
967 clip_modeless(button, is_click, is_drag);
968 }
969 break;
970
971 case K_MIDDLEMOUSE:
972 if (clip_star.available)
973 insert_reg('*', TRUE);
974 break;
975 }
976 enter_mouse_col = -1;
977 return FALSE;
978 }
979 #endif
980 enter_mouse_col = -1;
981
982 switch (key)
983 {
984 case K_LEFTMOUSE:
985 case K_LEFTMOUSE_NM: term_send_mouse(vterm, 1, 1); break;
986 case K_LEFTDRAG: term_send_mouse(vterm, 1, 1); break;
987 case K_LEFTRELEASE:
988 case K_LEFTRELEASE_NM: term_send_mouse(vterm, 1, 0); break;
989 case K_MOUSEMOVE: term_send_mouse(vterm, 0, 0); break;
990 case K_MIDDLEMOUSE: term_send_mouse(vterm, 2, 1); break;
991 case K_MIDDLEDRAG: term_send_mouse(vterm, 2, 1); break;
992 case K_MIDDLERELEASE: term_send_mouse(vterm, 2, 0); break;
993 case K_RIGHTMOUSE: term_send_mouse(vterm, 3, 1); break;
994 case K_RIGHTDRAG: term_send_mouse(vterm, 3, 1); break;
995 case K_RIGHTRELEASE: term_send_mouse(vterm, 3, 0); break;
996 }
900 return TRUE; 997 return TRUE;
901 } 998 }
902 999
903 /* 1000 /*
904 * Convert typed key "c" into bytes to send to the job. 1001 * Convert typed key "c" into bytes to send to the job.
993 case K_MOUSEDOWN: other = term_send_mouse(vterm, 4, 1); break; 1090 case K_MOUSEDOWN: other = term_send_mouse(vterm, 4, 1); break;
994 case K_MOUSELEFT: /* TODO */ return 0; 1091 case K_MOUSELEFT: /* TODO */ return 0;
995 case K_MOUSERIGHT: /* TODO */ return 0; 1092 case K_MOUSERIGHT: /* TODO */ return 0;
996 1093
997 case K_LEFTMOUSE: 1094 case K_LEFTMOUSE:
998 case K_LEFTMOUSE_NM: other = term_send_mouse(vterm, 1, 1); break; 1095 case K_LEFTMOUSE_NM:
999 case K_LEFTDRAG: other = term_send_mouse(vterm, 1, 1); break; 1096 case K_LEFTDRAG:
1000 case K_LEFTRELEASE: 1097 case K_LEFTRELEASE:
1001 case K_LEFTRELEASE_NM: other = term_send_mouse(vterm, 1, 0); break; 1098 case K_LEFTRELEASE_NM:
1002 case K_MOUSEMOVE: other = term_send_mouse(vterm, 0, 0); break; 1099 case K_MOUSEMOVE:
1003 case K_MIDDLEMOUSE: other = term_send_mouse(vterm, 2, 1); break; 1100 case K_MIDDLEMOUSE:
1004 case K_MIDDLEDRAG: other = term_send_mouse(vterm, 2, 1); break; 1101 case K_MIDDLEDRAG:
1005 case K_MIDDLERELEASE: other = term_send_mouse(vterm, 2, 0); break; 1102 case K_MIDDLERELEASE:
1006 case K_RIGHTMOUSE: other = term_send_mouse(vterm, 3, 1); break; 1103 case K_RIGHTMOUSE:
1007 case K_RIGHTDRAG: other = term_send_mouse(vterm, 3, 1); break; 1104 case K_RIGHTDRAG:
1008 case K_RIGHTRELEASE: other = term_send_mouse(vterm, 3, 0); break; 1105 case K_RIGHTRELEASE: if (!term_mouse_click(vterm, c))
1106 return 0;
1107 other = TRUE;
1108 break;
1109
1009 case K_X1MOUSE: /* TODO */ return 0; 1110 case K_X1MOUSE: /* TODO */ return 0;
1010 case K_X1DRAG: /* TODO */ return 0; 1111 case K_X1DRAG: /* TODO */ return 0;
1011 case K_X1RELEASE: /* TODO */ return 0; 1112 case K_X1RELEASE: /* TODO */ return 0;
1012 case K_X2MOUSE: /* TODO */ return 0; 1113 case K_X2MOUSE: /* TODO */ return 0;
1013 case K_X2DRAG: /* TODO */ return 0; 1114 case K_X2DRAG: /* TODO */ return 0;
1471 got_int = FALSE; 1572 got_int = FALSE;
1472 State = save_State; 1573 State = save_State;
1473 return c; 1574 return c;
1474 } 1575 }
1475 1576
1577 static int mouse_was_outside = FALSE;
1578
1476 /* 1579 /*
1477 * Send keys to terminal. 1580 * Send keys to terminal.
1478 * Return FAIL when the key needs to be handled in Normal mode. 1581 * Return FAIL when the key needs to be handled in Normal mode.
1479 * Return OK when the key was dropped or sent to the terminal. 1582 * Return OK when the key was dropped or sent to the terminal.
1480 */ 1583 */
1481 int 1584 int
1482 send_keys_to_term(term_T *term, int c, int typed) 1585 send_keys_to_term(term_T *term, int c, int typed)
1483 { 1586 {
1484 char msg[KEY_BUF_LEN]; 1587 char msg[KEY_BUF_LEN];
1485 size_t len; 1588 size_t len;
1486 static int mouse_was_outside = FALSE;
1487 int dragging_outside = FALSE; 1589 int dragging_outside = FALSE;
1488 1590
1489 /* Catch keys that need to be handled as in Normal mode. */ 1591 /* Catch keys that need to be handled as in Normal mode. */
1490 switch (c) 1592 switch (c)
1491 { 1593 {
1727 #endif 1829 #endif
1728 desired_cursor_color = (char_u *)""; 1830 desired_cursor_color = (char_u *)"";
1729 desired_cursor_shape = -1; 1831 desired_cursor_shape = -1;
1730 desired_cursor_blink = -1; 1832 desired_cursor_blink = -1;
1731 may_output_cursor_props(); 1833 may_output_cursor_props();
1834 }
1835
1836 /*
1837 * Called when entering a window with the mouse. If this is a terminal window
1838 * we may want to change state.
1839 */
1840 void
1841 term_win_entered()
1842 {
1843 term_T *term = curbuf->b_term;
1844
1845 if (term != NULL)
1846 {
1847 if (term_use_loop())
1848 {
1849 reset_VIsual_and_resel();
1850 if (State & INSERT)
1851 stop_insert_mode = TRUE;
1852 }
1853 mouse_was_outside = FALSE;
1854 enter_mouse_col = mouse_col;
1855 enter_mouse_row = mouse_row;
1856 }
1732 } 1857 }
1733 1858
1734 /* 1859 /*
1735 * Returns TRUE if the current window contains a terminal and we are sending 1860 * Returns TRUE if the current window contains a terminal and we are sending
1736 * keys to the job. 1861 * keys to the job.