diff options
author | Olaf Rogalsky <olaf.rogalsky@gmail.com> | 2015-03-24 21:04:00 -0400 |
---|---|---|
committer | Stefan Monnier <monnier@iro.umontreal.ca> | 2015-03-24 21:04:00 -0400 |
commit | c2385c6f36d346d6524a4119109f52d4fd975244 (patch) | |
tree | 70d917cbe59b248222db3ec1d30a9ab51b3d9f61 /lisp | |
parent | b28753b55ce83215b15661d16bfbafe3c8964b2a (diff) | |
download | emacs-c2385c6f36d346d6524a4119109f52d4fd975244.tar.gz |
* lisp/xt-mouse.el: Add mouse-tracking support.
Fixes: debbugs:19416
* lisp/xt-mouse.el: Add mouse-tracking support.
(xterm-mouse-translate-1): Handle mouse-movement events.
(xterm-mouse--read-event-sequence-1000)
(xterm-mouse--read-event-sequence-1006): Delete functions.
(xterm-mouse--read-event-sequence): New function that handles both at
the same time. Handle mouse-movements.
(xterm-mouse--read-utf8-char, xterm-mouse--read-number-from-terminal):
New functions.
(xterm-mouse-event): Simplify.
(xterm-mouse-tracking-enable-sequence)
(xterm-mouse-tracking-disable-sequence): Enable mouse tracking.
* lisp/mouse.el (mouse-drag-line): Also ignore `vertical-line' prefix events.
Diffstat (limited to 'lisp')
-rw-r--r-- | lisp/ChangeLog | 16 | ||||
-rw-r--r-- | lisp/mouse.el | 3 | ||||
-rw-r--r-- | lisp/xt-mouse.el | 185 |
3 files changed, 134 insertions, 70 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 3b8fa7d66c7..0d2f59227e9 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,19 @@ +2015-03-25 Olaf Rogalsky <olaf.rogalsky@gmail.com> + + * xt-mouse.el: Add mouse-tracking support (bug#19416). + (xterm-mouse-translate-1): Handle mouse-movement events. + (xterm-mouse--read-event-sequence-1000) + (xterm-mouse--read-event-sequence-1006): Delete functions. + (xterm-mouse--read-event-sequence): New function that handles both at + the same time. Handle mouse-movements. + (xterm-mouse--read-utf8-char, xterm-mouse--read-number-from-terminal): + New functions. + (xterm-mouse-event): Simplify. + (xterm-mouse-tracking-enable-sequence) + (xterm-mouse-tracking-disable-sequence): Enable mouse tracking. + + * mouse.el (mouse-drag-line): Also ignore `vertical-line' prefix events. + 2015-03-24 Michael Albinus <michael.albinus@gmx.de> * net/tramp-sh.el (tramp-do-file-attributes-with-ls) diff --git a/lisp/mouse.el b/lisp/mouse.el index c50913f4636..5f3fa5d7694 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -486,9 +486,10 @@ must be one of the symbols `header', `mode', or `vertical'." `(menu-item "" ,(lambda () (interactive) (funcall exitfun)) :filter ,(lambda (cmd) (if dragged cmd))))) ;; Some of the events will of course end up looked up - ;; with a mode-line or header-line prefix ... + ;; with a mode-line, header-line or vertical-line prefix ... (define-key map [mode-line] map) (define-key map [header-line] map) + (define-key map [vertical-line] map) ;; ... and some maybe even with a right- or bottom-divider ;; prefix. (define-key map [right-divider] map) diff --git a/lisp/xt-mouse.el b/lisp/xt-mouse.el index b87c1a28937..7f1e72260ae 100644 --- a/lisp/xt-mouse.el +++ b/lisp/xt-mouse.el @@ -60,6 +60,7 @@ http://invisible-island.net/xterm/ctlseqs/ctlseqs.html)." (ev-data (nth 1 event)) (ev-where (nth 1 ev-data)) (vec (vector event)) + (is-move (eq 'mouse-movement ev-command)) (is-down (string-match "down-" (symbol-name ev-command)))) ;; Mouse events symbols must have an 'event-kind property with @@ -71,6 +72,7 @@ http://invisible-island.net/xterm/ctlseqs/ctlseqs.html)." (is-down (setf (terminal-parameter nil 'xterm-mouse-last-down) event) vec) + (is-move vec) (t (let* ((down (terminal-parameter nil 'xterm-mouse-last-down)) (down-data (nth 1 down)) @@ -132,65 +134,89 @@ http://invisible-island.net/xterm/ctlseqs/ctlseqs.html)." (fdiff (- f (* 1.0 maxwrap dbig)))) (+ (truncate fdiff) (* maxwrap dbig)))))) -;; Normal terminal mouse click reporting: expect three bytes, of the -;; form <BUTTON+32> <X+32> <Y+32>. Return a list (EVENT-TYPE X Y). -(defun xterm-mouse--read-event-sequence-1000 () - (let* ((code (- (read-event) 32)) - (type - ;; For buttons > 3, the release-event looks differently - ;; (see xc/programs/xterm/button.c, function EditorButton), - ;; and come in a release-event only, no down-event. - (cond ((>= code 64) - (format "mouse-%d" (- code 60))) - ((memq code '(8 9 10)) - (format "M-down-mouse-%d" (- code 7))) - ((memq code '(3 11)) - (let ((down (car (terminal-parameter - nil 'xterm-mouse-last-down)))) - (when (and down (string-match "[0-9]" (symbol-name down))) - (format (if (eq code 3) "mouse-%s" "M-mouse-%s") - (match-string 0 (symbol-name down)))))) - ((memq code '(0 1 2)) - (format "down-mouse-%d" (+ 1 code))))) - (x (- (read-event) 33)) - (y (- (read-event) 33))) - (and type (wholenump x) (wholenump y) - (list (intern type) x y)))) - -;; XTerm's 1006-mode terminal mouse click reporting has the form -;; <BUTTON> ; <X> ; <Y> <M or m>, where the button and ordinates are -;; in encoded (decimal) form. Return a list (EVENT-TYPE X Y). -(defun xterm-mouse--read-event-sequence-1006 () - (let (button-bytes x-bytes y-bytes c) - (while (not (eq (setq c (read-event)) ?\;)) - (push c button-bytes)) - (while (not (eq (setq c (read-event)) ?\;)) - (push c x-bytes)) - (while (not (memq (setq c (read-event)) '(?m ?M))) - (push c y-bytes)) - (list (let* ((code (string-to-number - (apply 'string (nreverse button-bytes)))) - (wheel (>= code 64)) - (down (and (not wheel) - (eq c ?M)))) - (intern (format "%s%smouse-%d" - (cond (wheel "") - ((< code 4) "") - ((< code 8) "S-") - ((< code 12) "M-") - ((< code 16) "M-S-") - ((< code 20) "C-") - ((< code 24) "C-S-") - ((< code 28) "C-M-") - ((< code 32) "C-M-S-") - (t - (error "Unexpected escape sequence from XTerm"))) - (if down "down-" "") - (if wheel - (- code 60) - (1+ (mod code 4)))))) - (1- (string-to-number (apply 'string (nreverse x-bytes)))) - (1- (string-to-number (apply 'string (nreverse y-bytes))))))) +(defun xterm-mouse--read-utf8-char (&optional prompt seconds) + "Read an utf-8 encoded character from the current terminal. +This function reads and returns an utf-8 encoded character of +command input. If the user generates an event which is not a +character (i.e., a mouse click or function key event), read-char +signals an error. + +The returned event may come directly from the user, or from a +keyboard macro. It is not decoded by the keyboard's input coding +system and always treated with an utf-8 input encoding. + +The optional arguments PROMPT and SECONDS work like in +`read-event'." + (let ((tmp (keyboard-coding-system))) + (set-keyboard-coding-system 'utf-8) + (prog1 (read-event prompt t seconds) + (set-keyboard-coding-system tmp)))) + +;; In default mode, each numeric parameter of XTerm's mouse report is +;; a single char, possibly encoded as utf-8. The actual numeric +;; parameter then is obtained by subtracting 32 from the character +;; code. In extendend mode the parameters are returned as decimal +;; string delemited either by semicolons or for the last parameter by +;; one of the characters "m" or "M". If the last character is a "m", +;; then the mouse event was a button release, else it was a button +;; press or a mouse motion. Return value is a cons cell with +;; (NEXT-NUMERIC-PARAMETER . LAST-CHAR) +(defun xterm-mouse--read-number-from-terminal (extension) + (let (c) + (if extension + (let ((n 0)) + (while (progn + (setq c (read-char)) + (<= ?0 c ?9)) + (setq n (+ (* 10 n) c (- ?0)))) + (cons n c)) + (cons (- (setq c (read-utf8-char)) 32) c)))) + +;; XTerm reports mouse events as +;; <EVENT-CODE> <X> <Y> in default mode, and +;; <EVENT-CODE> ";" <X> ";" <Y> <"M" or "m"> in extended mode. +;; The macro read-number-from-terminal takes care of reading +;; the response parameters appropriatly. The EVENT-CODE differs +;; slightly between default and extended mode. +;; Return a list (EVENT-TYPE-SYMBOL X Y). +(defun xterm-mouse--read-event-sequence (&optional extension) + (pcase-let* + ((`(,code . ,_) (xterm-mouse--read-number-from-terminal extension)) + (`(,x . ,_) (xterm-mouse--read-number-from-terminal extension)) + (`(,y . ,c) (xterm-mouse--read-number-from-terminal extension)) + (wheel (/= (logand code 64) 0)) + (move (/= (logand code 32) 0)) + (ctrl (/= (logand code 16) 0)) + (meta (/= (logand code 8) 0)) + (shift (/= (logand code 4) 0)) + (down (and (not wheel) + (not move) + (if extension + (eq c ?M) + (/= (logand code 3) 3)))) + (btn (cond + ((or extension down wheel) + (+ (logand code 3) (if wheel 4 1))) + ;; The default mouse protocol does not report the button + ;; number in release events: extract the button number + ;; from last button-down event. + ((terminal-parameter nil 'xterm-mouse-last-down) + (string-to-number + (substring + (symbol-name + (car (terminal-parameter nil 'xterm-mouse-last-down))) + -1))) + ;; Spurious release event without previous button-down + ;; event: assume, that the last button was button 1. + (t 1))) + (sym (if move 'mouse-movement + (intern (concat (if ctrl "C-" "") + (if meta "M-" "") + (if shift "S-" "") + (if down "down-" "") + "mouse-" + (number-to-string btn)))))) + (list sym (1- x) (1- y)))) (defun xterm-mouse--set-click-count (event click-count) (setcdr (cdr event) (list click-count)) @@ -207,12 +233,10 @@ http://invisible-island.net/xterm/ctlseqs/ctlseqs.html)." EXTENSION, if non-nil, means to use an extension to the usual terminal mouse protocol; we currently support the value 1006, which is the \"1006\" extension implemented in Xterm >= 277." - (let* ((click (cond ((null extension) - (xterm-mouse--read-event-sequence-1000)) - ((eq extension 1006) - (xterm-mouse--read-event-sequence-1006)) - (t - (error "Unsupported XTerm mouse protocol"))))) + (let ((click (cond ((memq extension '(1006 nil)) + (xterm-mouse--read-event-sequence extension)) + (t + (error "Unsupported XTerm mouse protocol"))))) (when click (let* ((type (nth 0 click)) (x (nth 1 click)) @@ -291,13 +315,36 @@ down the SHIFT key while pressing the mouse button." (setq mouse-position-function nil))) (defconst xterm-mouse-tracking-enable-sequence - "\e[?1000h\e[?1006h" + "\e[?1000h\e[?1002h\e[?1005h\e[?1006h" "Control sequence to enable xterm mouse tracking. -Enables basic tracking, then extended tracking on -terminals that support it.") +Enables basic mouse tracking, mouse motion events and finally +extended tracking on terminals that support it. The following +escape sequences are understood by modern xterms: + +\"\\e[?1000h\" `Basic mouse mode´: Enables reports for mouse + clicks. There is a limit to the maximum row/column + position (<= 223), which can be reported in this + basic mode. + +\"\\e[?1002h\" `Mouse motion mode´: Enables reports for mouse + motion events during dragging operations. + +\"\\e[?1005h\" `UTF-8 coordinate extension`: Enables an extension + to the basic mouse mode, which uses UTF-8 + characters to overcome the 223 row/column limit. This + extension may conflict with non UTF-8 applications or + non UTF-8 locales. + +\"\\e[?1006h\" `SGR coordinate extension´: Enables a newer + alternative extension to the basic mouse mode, which + overcomes the 223 row/column limit without the + drawbacks of the UTF-8 coordinate extension. + +The two extension modes are mutually exclusive, where the last +given escape sequence takes precedence over the former.") (defconst xterm-mouse-tracking-disable-sequence - "\e[?1006l\e[?1000l" + "\e[?1006l\e[?1005l\e[?1002l\e[?1000l" "Reset the modes set by `xterm-mouse-tracking-enable-sequence'.") (defun turn-on-xterm-mouse-tracking-on-terminal (&optional terminal) |