emacs-xterm-mouse-support.patch 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. https://debbugs.gnu.org/cgi/bugreport.cgi?bug=29552
  2. diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el
  3. index 972f84ee6c..0c40c4ba12 100644
  4. --- a/lisp/menu-bar.el
  5. +++ b/lisp/menu-bar.el
  6. @@ -2460,6 +2460,31 @@ tty-menu--initial-menu-x
  7. This is meant to be used only for debugging TTY menus.")
  8. +(defun tty-menu-bar-open-with-mouse (event)
  9. + "Opens menu-bar menu on a TTY frame.
  10. +
  11. +If EVENT is a mouse-click on the menu-bar of a TTY frame, drop
  12. +down the corresponding menu."
  13. + (interactive "e")
  14. + (let* ((pos (event-start event))
  15. + (frame (posn-window pos))
  16. + (area (posn-area pos))
  17. + (x (car (posn-x-y pos)))
  18. + (menu (menu-bar-menu-at-x-y x 0 frame)))
  19. + ;; Find first column of clicked menu-bar item. There must be a
  20. + ;; smarter way ...
  21. + (while (and (>= x 0)
  22. + (eq menu (menu-bar-menu-at-x-y (1- x) 0 frame)))
  23. + (setq x (1- x)))
  24. + (popup-menu (or
  25. + (lookup-key-ignore-too-long
  26. + global-map (vector 'menu-bar menu))
  27. + (lookup-key-ignore-too-long
  28. + (current-local-map) (vector 'menu-bar menu))
  29. + (cdar (minor-mode-key-binding (vector 'menu-bar menu)))
  30. + (mouse-menu-bar-map))
  31. + (posn-at-x-y x 0 nil t) nil t)))
  32. +
  33. (defun menu-bar-open (&optional frame)
  34. "Start key navigation of the menu bar in FRAME.
  35. @@ -2584,6 +2609,8 @@ tty-menu-navigation-map
  36. (define-key map [C-down-mouse-2] 'tty-menu-ignore)
  37. (define-key map [C-down-mouse-3] 'tty-menu-ignore)
  38. (define-key map [mouse-movement] 'tty-menu-mouse-movement)
  39. + ;; Do not deselect menu, when mouse is hovering over the menu-bar.
  40. + (define-key map [menu-bar mouse-movement] 'tty-menu-mouse-movement)
  41. map)
  42. "Keymap used while processing TTY menus.")
  43. diff --git a/lisp/xt-mouse.el b/lisp/xt-mouse.el
  44. index d704cfa4e8..b1ecbb41d3 100644
  45. --- a/lisp/xt-mouse.el
  46. +++ b/lisp/xt-mouse.el
  47. @@ -67,6 +67,21 @@ xterm-mouse-translate-1
  48. ;; the value 'mouse-click.
  49. (when ev-command (put ev-command 'event-kind 'mouse-click))
  50. + ;; notify display engine to (de)highlight text with mouse-face
  51. + ;; property
  52. + (when ev-data
  53. + (let* ((window (posn-window ev-data))
  54. + (x (+ (car (posn-x-y ev-data))
  55. + (car (window-edges window))))
  56. + (y (+ (cdr (posn-x-y ev-data))
  57. + (cadr (window-edges window)))))
  58. + (and (with-current-buffer (window-buffer window)
  59. + header-line-format)
  60. + (not (eq ev-where 'mode-line))
  61. + (not (eq ev-where 'header-line))
  62. + (setq y (1+ y)))
  63. + (note-mouse-highlight (window-frame window) x y)))
  64. +
  65. (cond
  66. ((null event) nil) ;Unknown/bogus byte sequence!
  67. (is-down
  68. @@ -76,7 +91,10 @@ xterm-mouse-translate-1
  69. ;; to guard against that.
  70. (copy-sequence event))
  71. vec)
  72. - (is-move vec)
  73. + (is-move
  74. + (if track-mouse
  75. + vec
  76. + []))
  77. (t
  78. (let* ((down (terminal-parameter nil 'xterm-mouse-last-down))
  79. (down-data (nth 1 down))
  80. @@ -147,6 +165,14 @@ xterm-mouse-utf-8
  81. :risky t
  82. :group 'xterm)
  83. +(defcustom xterm-mouse-highlight t
  84. + "Non-nil enables display of help-echo properties and
  85. +mouse-face highlighting for text under the mouse."
  86. + :version "27.1"
  87. + :type 'boolean
  88. + :risky t
  89. + :group 'xterm)
  90. +
  91. (defun xterm-mouse--read-coordinate ()
  92. "Read a mouse coordinate from the current terminal.
  93. If `xterm-mouse-utf-8' was non-nil when
  94. @@ -266,8 +292,8 @@ xterm-mouse-event
  95. (left (nth 0 ltrb))
  96. (top (nth 1 ltrb))
  97. (posn (if w
  98. - (posn-at-x-y (- x left) (- y top) w t)
  99. - (append (list nil 'menu-bar)
  100. + (posn-at-x-y (- x left) (- y top) w t)
  101. + (append (list nil 'menu-bar)
  102. (nthcdr 2 (posn-at-x-y x y)))))
  103. (event (list type posn)))
  104. (setcar (nthcdr 3 posn) timestamp)
  105. @@ -322,7 +348,12 @@ xterm-mouse-mode
  106. single clicks are supported. When turned on, the normal xterm
  107. mouse functionality for such clicks is still available by holding
  108. down the SHIFT key while pressing the mouse button."
  109. - :global t :group 'mouse
  110. + :global t
  111. + :group 'mouse
  112. + :keymap (let ((map (make-sparse-keymap)))
  113. + (define-key map [menu-bar mouse-1]
  114. + 'tty-menu-bar-open-with-mouse)
  115. + map)
  116. (funcall (if xterm-mouse-mode 'add-hook 'remove-hook)
  117. 'terminal-init-xterm-hook
  118. 'turn-on-xterm-mouse-tracking-on-terminal)
  119. @@ -350,6 +381,12 @@ xterm-mouse-tracking-enable-sequence
  120. \"\\e[?1002h\" \"Mouse motion mode\": Enables reports for mouse
  121. motion events during dragging operations.
  122. +\"\\e[?1003h\" \"Any event tracking mode\": Enables reports for
  123. + all mouse events. In particular all mouse motion
  124. + events will be reported and not only those during
  125. + dragging operations. This sequence enables
  126. + highlighting of text under the mouse cursor.
  127. +
  128. \"\\e[?1005h\" \"UTF-8 coordinate extension\": Enables an
  129. extension to the basic mouse mode, which uses UTF-8
  130. characters to overcome the 223 row/column limit.
  131. @@ -368,18 +405,18 @@ xterm-mouse-tracking-enable-sequence
  132. (apply #'concat (xterm-mouse--tracking-sequence ?h)))
  133. (defconst xterm-mouse-tracking-enable-sequence
  134. - "\e[?1000h\e[?1002h\e[?1005h\e[?1006h"
  135. + "\e[?1000h\e[?1002h\e[?1005h\e[?1006h\e[?1003h"
  136. "Control sequence to enable xterm mouse tracking.
  137. Enables basic mouse tracking, mouse motion events and finally
  138. extended tracking on terminals that support it. The following
  139. escape sequences are understood by modern xterms:
  140. -\"\\e[?1000h\" \"Basic mouse mode\": Enables reports for mouse
  141. +\"\\e[?1000h\" \"Basic mouse mode\": Disables reports for mouse
  142. clicks. There is a limit to the maximum row/column
  143. position (<= 223), which can be reported in this
  144. basic mode.
  145. -\"\\e[?1002h\" \"Mouse motion mode\": Enables reports for mouse
  146. +\"\\e[?1002h\" \"Mouse motion mode\": Disables reports for mouse
  147. motion events during dragging operations.
  148. \"\\e[?1005h\" \"UTF-8 coordinate extension\": Enables an extension
  149. @@ -388,11 +425,17 @@ xterm-mouse-tracking-enable-sequence
  150. extension may conflict with non UTF-8 applications or
  151. non UTF-8 locales.
  152. -\"\\e[?1006h\" \"SGR coordinate extension\": Enables a newer
  153. +\"\\e[?1006h\" \"SGR coordinate extension\": Disables a newer
  154. alternative extension to the basic mouse mode, which
  155. overcomes the 223 row/column limit without the
  156. drawbacks of the UTF-8 coordinate extension.
  157. +\"\\e[?1003h\" \"Any event tracking mode\": Disables reports for
  158. + all mouse events, in particular mouse motion events
  159. + will allways be reported and not only during dragging
  160. + operations. This sequence disables highlighting of
  161. + text under the mouse cursor.
  162. +
  163. The two extension modes are mutually exclusive, where the last
  164. given escape sequence takes precedence over the former.")
  165. @@ -408,7 +451,7 @@ xterm-mouse-tracking-disable-sequence
  166. (apply #'concat (nreverse (xterm-mouse--tracking-sequence ?l))))
  167. (defconst xterm-mouse-tracking-disable-sequence
  168. - "\e[?1006l\e[?1005l\e[?1002l\e[?1000l"
  169. + "\e[?1003l\e[?1006l\e[?1005l\e[?1002l\e[?1000l"
  170. "Reset the modes set by `xterm-mouse-tracking-enable-sequence'.")
  171. (make-obsolete-variable
  172. @@ -422,7 +465,8 @@ xterm-mouse--tracking-sequence
  173. enable, ?l to disable)."
  174. (mapcar
  175. (lambda (code) (format "\e[?%d%c" code suffix))
  176. - `(1000 1002 ,@(when xterm-mouse-utf-8 '(1005)) 1006)))
  177. + `(1000 1002 ,@(when xterm-mouse-utf-8 '(1005)) 1006 ,@(when
  178. + xterm-mouse-highlight '(1003)))))
  179. (defun turn-on-xterm-mouse-tracking-on-terminal (&optional terminal)
  180. "Enable xterm mouse tracking on TERMINAL."
  181. diff --git a/src/keyboard.c b/src/keyboard.c
  182. index b18dc1abbe..31e4933c14 100644
  183. --- a/src/keyboard.c
  184. +++ b/src/keyboard.c
  185. @@ -652,6 +652,19 @@ add_command_key (Lisp_Object key)
  186. if (this_command_key_count >= ASIZE (this_command_keys))
  187. this_command_keys = larger_vector (this_command_keys, 1, -1);
  188. + /* Only store the first and the last event in a series of mouse-movements. */
  189. + if (EQ (EVENT_HEAD (key), Qmouse_movement) && this_command_key_count >= 2)
  190. + {
  191. + Lisp_Object ev1 = AREF (this_command_keys, this_command_key_count - 2);
  192. + Lisp_Object ev2 = AREF (this_command_keys, this_command_key_count - 1);
  193. + if (EQ (EVENT_HEAD (ev1), Qmouse_movement) &&
  194. + EQ (EVENT_HEAD (ev2), Qmouse_movement))
  195. + {
  196. + ASET (this_command_keys, this_command_key_count - 1, key);
  197. + return;
  198. + }
  199. + }
  200. +
  201. ASET (this_command_keys, this_command_key_count, key);
  202. ++this_command_key_count;
  203. }
  204. diff --git a/src/term.c b/src/term.c
  205. index 06695d1ec6..f10259c08c 100644
  206. --- a/src/term.c
  207. +++ b/src/term.c
  208. @@ -793,8 +793,6 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
  209. cmcheckmagic (tty);
  210. }
  211. -#ifdef HAVE_GPM /* Only used by GPM code. */
  212. -
  213. static void
  214. tty_write_glyphs_with_face (register struct frame *f, register struct glyph *string,
  215. register int len, register int face_id)
  216. @@ -851,7 +849,6 @@ tty_write_glyphs_with_face (register struct frame *f, register struct glyph *str
  217. cmcheckmagic (tty);
  218. }
  219. -#endif
  220. /* An implementation of insert_glyphs for termcap frames. */
  221. @@ -2371,9 +2368,7 @@ frame's terminal). */)
  222. Mouse
  223. ***********************************************************************/
  224. -#ifdef HAVE_GPM
  225. -
  226. -#ifndef HAVE_WINDOW_SYSTEM
  227. +#if defined (HAVE_GPM) && !defined (HAVE_WINDOW_SYSTEM)
  228. void
  229. term_mouse_moveto (int x, int y)
  230. {
  231. @@ -2387,7 +2382,7 @@ term_mouse_moveto (int x, int y)
  232. last_mouse_x = x;
  233. last_mouse_y = y; */
  234. }
  235. -#endif /* HAVE_WINDOW_SYSTEM */
  236. +#endif /* HAVE_GPM && !HAVE_WINDOW_SYSTEM */
  237. /* Implementation of draw_row_with_mouse_face for TTY/GPM. */
  238. void
  239. @@ -2421,6 +2416,7 @@ tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
  240. cursor_to (f, save_y, save_x);
  241. }
  242. +#ifdef HAVE_GPM
  243. static bool
  244. term_mouse_movement (struct frame *frame, Gpm_Event *event)
  245. {
  246. @@ -2798,12 +2794,17 @@ mouse_get_xy (int *x, int *y)
  247. enum scroll_bar_part part_dummy;
  248. Time time_dummy;
  249. - if (FRAME_TERMINAL (sf)->mouse_position_hook)
  250. + if (Fterminal_parameter (Qnil, Qxterm_mouse_mode))
  251. + {
  252. + lmx = Fterminal_parameter (Qnil, Qxterm_mouse_x);
  253. + lmy = Fterminal_parameter (Qnil, Qxterm_mouse_y);
  254. + }
  255. + else if (FRAME_TERMINAL (sf)->mouse_position_hook)
  256. (*FRAME_TERMINAL (sf)->mouse_position_hook) (&sf, -1,
  257. &lisp_dummy, &part_dummy,
  258. - &lmx, &lmy,
  259. - &time_dummy);
  260. - if (!NILP (lmx))
  261. + &lmx, &lmy,
  262. + &time_dummy);
  263. + if (INTEGERP (lmx) && INTEGERP (lmy))
  264. {
  265. *x = XINT (lmx);
  266. *y = XINT (lmy);
  267. @@ -3064,7 +3065,7 @@ read_menu_input (struct frame *sf, int *x, int *y, int min_y, int max_y,
  268. || sf != SELECTED_FRAME ())
  269. return MI_QUIT_MENU;
  270. if (EQ (cmd, Qtty_menu_mouse_movement))
  271. - mouse_get_xy (x, y);
  272. + mouse_get_xy (x, y);
  273. else if (EQ (cmd, Qtty_menu_next_menu))
  274. {
  275. usable_input = 0;
  276. @@ -4541,6 +4542,9 @@ bigger, or it may make it blink, or it may do nothing at all. */);
  277. DEFSYM (Qtty_mode_set_strings, "tty-mode-set-strings");
  278. DEFSYM (Qtty_mode_reset_strings, "tty-mode-reset-strings");
  279. + DEFSYM (Qxterm_mouse_mode, "xterm-mouse-mode");
  280. + DEFSYM (Qxterm_mouse_x, "xterm-mouse-x");
  281. + DEFSYM (Qxterm_mouse_y, "xterm-mouse-y");
  282. #ifndef MSDOS
  283. DEFSYM (Qtty_menu_next_item, "tty-menu-next-item");
  284. diff --git a/src/xdisp.c b/src/xdisp.c
  285. index 016e7044ca..96fba761a6 100644
  286. --- a/src/xdisp.c
  287. +++ b/src/xdisp.c
  288. @@ -29568,9 +29568,7 @@ draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row,
  289. return;
  290. }
  291. #endif
  292. -#if defined (HAVE_GPM) || defined (MSDOS) || defined (WINDOWSNT)
  293. tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw);
  294. -#endif
  295. }
  296. /* Display the active region described by mouse_face_* according to DRAW. */
  297. @@ -31571,6 +31569,31 @@ note_mouse_highlight (struct frame *f, int x, int y)
  298. define_frame_cursor1 (f, cursor, pointer);
  299. }
  300. +DEFUN ("note-mouse-highlight", Fnote_mouse_highlight, Snote_mouse_highlight,
  301. + 3, 3, 0,
  302. + doc: /* Take proper action when the mouse has moved to position
  303. +X, Y on frame F with regards to highlighting portions of display that
  304. +have mouse-face properties. Also de-highlight portions of display
  305. +where the mouse was before, set the mouse pointer shape as appropriate
  306. +for the mouse coordinates, and activate help echo (tooltips). X and Y
  307. +can be negative or out of range. */)
  308. + (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
  309. +{
  310. + CHECK_FRAME(frame);
  311. + CHECK_NUMBER(x);
  312. + CHECK_NUMBER(y);
  313. +
  314. + /* silently do nothing, if frame is not on a terminal */
  315. + if (XFRAME(frame)->output_method != output_termcap &&
  316. + XFRAME(frame)->output_method != output_msdos_raw)
  317. + return Qnil;
  318. +
  319. + note_mouse_highlight(XFRAME(frame), XINT(x), XINT(y));
  320. + fflush_unlocked(FRAME_TTY(XFRAME(frame))->output);
  321. +
  322. + return Qnil;
  323. +}
  324. +
  325. /* EXPORT for RIF:
  326. Clear any mouse-face on window W. This function is part of the
  327. @@ -32253,6 +32276,8 @@ They are still logged to the *Messages* buffer. */);
  328. defsubr (&Stool_bar_height);
  329. defsubr (&Slookup_image_map);
  330. #endif
  331. +
  332. + defsubr (&Snote_mouse_highlight);
  333. defsubr (&Sline_pixel_height);
  334. defsubr (&Sformat_mode_line);
  335. defsubr (&Sinvisible_p);