diff options
| author | Chong Yidong | 2012-07-14 23:40:12 +0800 |
|---|---|---|
| committer | Chong Yidong | 2012-07-14 23:40:12 +0800 |
| commit | 63408057e7b8f8f9e04fa689117c75b498406daf (patch) | |
| tree | abcfef7f0c68d7591dd5b5043844018c23c9cd16 | |
| parent | 28ca98ac5218a3a14ae57f425ac226fc8fc0f6e4 (diff) | |
| download | emacs-63408057e7b8f8f9e04fa689117c75b498406daf.tar.gz emacs-63408057e7b8f8f9e04fa689117c75b498406daf.zip | |
* xt-mouse.el: Implement extended mouse coordinates.
(xterm-mouse-translate): Move code into xterm-mouse-translate-1.
(xterm-mouse-translate-extended, xterm-mouse-translate-1)
(xterm-mouse--read-event-sequence-1000)
(xterm-mouse--read-event-sequence-1006): New functions. For old
mouse protocol, handle M-mouse-X events correctly.
(xterm-mouse-event): New arg specifying mouse protocol.
(turn-on-xterm-mouse-tracking-on-terminal)
(turn-off-xterm-mouse-tracking-on-terminal): Send DEC 1006
sequence to toggle extended coordinates on newer XTerms. This
appears to be harmless on terminals which do not support this.
Fixes: debbugs:10642
| -rw-r--r-- | lisp/ChangeLog | 14 | ||||
| -rw-r--r-- | lisp/xt-mouse.el | 179 |
2 files changed, 139 insertions, 54 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 8fee2598235..7bb09181b96 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,17 @@ | |||
| 1 | 2012-07-14 Chong Yidong <cyd@gnu.org> | ||
| 2 | |||
| 3 | * xt-mouse.el: Implement extended mouse coordinates (Bug#10642). | ||
| 4 | (xterm-mouse-translate): Move code into xterm-mouse-translate-1. | ||
| 5 | (xterm-mouse-translate-extended, xterm-mouse-translate-1) | ||
| 6 | (xterm-mouse--read-event-sequence-1000) | ||
| 7 | (xterm-mouse--read-event-sequence-1006): New functions. For old | ||
| 8 | mouse protocol, handle M-mouse-X events correctly. | ||
| 9 | (xterm-mouse-event): New arg specifying mouse protocol. | ||
| 10 | (turn-on-xterm-mouse-tracking-on-terminal) | ||
| 11 | (turn-off-xterm-mouse-tracking-on-terminal): Send DEC 1006 | ||
| 12 | sequence to toggle extended coordinates on newer XTerms. This | ||
| 13 | appears to be harmless on terminals which do not support this. | ||
| 14 | |||
| 1 | 2012-07-14 Leo Liu <sdl.web@gmail.com> | 15 | 2012-07-14 Leo Liu <sdl.web@gmail.com> |
| 2 | 16 | ||
| 3 | Add fringe bitmap indicators for flymake. (Bug#11253) | 17 | Add fringe bitmap indicators for flymake. (Bug#11253) |
diff --git a/lisp/xt-mouse.el b/lisp/xt-mouse.el index 06d82870f8c..3c2a3c57c78 100644 --- a/lisp/xt-mouse.el +++ b/lisp/xt-mouse.el | |||
| @@ -47,33 +47,49 @@ | |||
| 47 | ;; Mouse events symbols must have an 'event-kind property with | 47 | ;; Mouse events symbols must have an 'event-kind property with |
| 48 | ;; the value 'mouse-click. | 48 | ;; the value 'mouse-click. |
| 49 | (dolist (event-type '(mouse-1 mouse-2 mouse-3 | 49 | (dolist (event-type '(mouse-1 mouse-2 mouse-3 |
| 50 | M-down-mouse-1 M-down-mouse-2 M-down-mouse-3)) | 50 | M-down-mouse-1 M-down-mouse-2 M-down-mouse-3)) |
| 51 | (put event-type 'event-kind 'mouse-click)) | 51 | (put event-type 'event-kind 'mouse-click)) |
| 52 | 52 | ||
| 53 | (defun xterm-mouse-translate (_event) | 53 | (defun xterm-mouse-translate (_event) |
| 54 | "Read a click and release event from XTerm." | 54 | "Read a click and release event from XTerm." |
| 55 | (xterm-mouse-translate-1)) | ||
| 56 | |||
| 57 | (defun xterm-mouse-translate-extended (_event) | ||
| 58 | "Read a click and release event from XTerm. | ||
| 59 | Similar to `xterm-mouse-translate', but using the \"1006\" | ||
| 60 | extension, which supports coordinates >= 231 (see | ||
| 61 | http://invisible-island.net/xterm/ctlseqs/ctlseqs.html)." | ||
| 62 | (xterm-mouse-translate-1 1006)) | ||
| 63 | |||
| 64 | (defun xterm-mouse-translate-1 (&optional extension) | ||
| 55 | (save-excursion | 65 | (save-excursion |
| 56 | (save-window-excursion | 66 | (save-window-excursion |
| 57 | (deactivate-mark) | 67 | (deactivate-mark) |
| 58 | (let* ((xterm-mouse-last) | 68 | (let* ((xterm-mouse-last nil) |
| 59 | (down (xterm-mouse-event)) | 69 | (down (xterm-mouse-event extension)) |
| 60 | (down-command (nth 0 down)) | 70 | (down-command (nth 0 down)) |
| 61 | (down-data (nth 1 down)) | 71 | (down-data (nth 1 down)) |
| 62 | (down-where (nth 1 down-data)) | 72 | (down-where (nth 1 down-data)) |
| 63 | (down-binding (key-binding (if (symbolp down-where) | 73 | (down-binding (key-binding (if (symbolp down-where) |
| 64 | (vector down-where down-command) | 74 | (vector down-where down-command) |
| 65 | (vector down-command)))) | 75 | (vector down-command)))) |
| 66 | (is-click (string-match "^mouse" (symbol-name (car down))))) | 76 | (is-click (string-match "^mouse" (symbol-name (car down))))) |
| 67 | 77 | ||
| 78 | ;; Retrieve the expected preface for the up-event. | ||
| 68 | (unless is-click | 79 | (unless is-click |
| 69 | (unless (and (eq (read-char) ?\e) | 80 | (unless (cond ((null extension) |
| 70 | (eq (read-char) ?\[) | 81 | (and (eq (read-char) ?\e) |
| 71 | (eq (read-char) ?M)) | 82 | (eq (read-char) ?\[) |
| 83 | (eq (read-char) ?M))) | ||
| 84 | ((eq extension 1006) | ||
| 85 | (and (eq (read-char) ?\e) | ||
| 86 | (eq (read-char) ?\[) | ||
| 87 | (eq (read-char) ?<)))) | ||
| 72 | (error "Unexpected escape sequence from XTerm"))) | 88 | (error "Unexpected escape sequence from XTerm"))) |
| 73 | 89 | ||
| 74 | (let* ((click (if is-click down (xterm-mouse-event))) | 90 | ;; Process the up-event. |
| 75 | ;; (click-command (nth 0 click)) | 91 | (let* ((click (if is-click down (xterm-mouse-event extension))) |
| 76 | (click-data (nth 1 click)) | 92 | (click-data (nth 1 click)) |
| 77 | (click-where (nth 1 click-data))) | 93 | (click-where (nth 1 click-data))) |
| 78 | (if (memq down-binding '(nil ignore)) | 94 | (if (memq down-binding '(nil ignore)) |
| 79 | (if (and (symbolp click-where) | 95 | (if (and (symbolp click-where) |
| @@ -81,17 +97,18 @@ | |||
| 81 | (vector (list click-where click-data) click) | 97 | (vector (list click-where click-data) click) |
| 82 | (vector click)) | 98 | (vector click)) |
| 83 | (setq unread-command-events | 99 | (setq unread-command-events |
| 84 | (if (eq down-where click-where) | 100 | (append (if (eq down-where click-where) |
| 85 | (list click) | 101 | (list click) |
| 86 | (list | 102 | (list |
| 87 | ;; Cheat `mouse-drag-region' with move event. | 103 | ;; Cheat `mouse-drag-region' with move event. |
| 88 | (list 'mouse-movement click-data) | 104 | (list 'mouse-movement click-data) |
| 89 | ;; Generate a drag event. | 105 | ;; Generate a drag event. |
| 90 | (if (symbolp down-where) | 106 | (if (symbolp down-where) |
| 91 | 0 | 107 | 0 |
| 92 | (list (intern (format "drag-mouse-%d" | 108 | (list (intern (format "drag-mouse-%d" |
| 93 | (+ 1 xterm-mouse-last))) | 109 | (1+ xterm-mouse-last))) |
| 94 | down-data click-data))))) | 110 | down-data click-data)))) |
| 111 | unread-command-events)) | ||
| 95 | (if xterm-mouse-debug-buffer | 112 | (if xterm-mouse-debug-buffer |
| 96 | (print unread-command-events xterm-mouse-debug-buffer)) | 113 | (print unread-command-events xterm-mouse-debug-buffer)) |
| 97 | (if (and (symbolp down-where) | 114 | (if (and (symbolp down-where) |
| @@ -118,7 +135,7 @@ | |||
| 118 | (terminal-parameter nil 'xterm-mouse-y)))) | 135 | (terminal-parameter nil 'xterm-mouse-y)))) |
| 119 | pos) | 136 | pos) |
| 120 | 137 | ||
| 121 | ;; read xterm sequences above ascii 127 (#x7f) | 138 | ;; Read XTerm sequences above ASCII 127 (#x7f) |
| 122 | (defun xterm-mouse-event-read () | 139 | (defun xterm-mouse-event-read () |
| 123 | ;; We get the characters decoded by the keyboard coding system. Try | 140 | ;; We get the characters decoded by the keyboard coding system. Try |
| 124 | ;; to recover the raw character. | 141 | ;; to recover the raw character. |
| @@ -147,11 +164,82 @@ | |||
| 147 | (fdiff (- f (* 1.0 maxwrap dbig)))) | 164 | (fdiff (- f (* 1.0 maxwrap dbig)))) |
| 148 | (+ (truncate fdiff) (* maxwrap dbig)))))) | 165 | (+ (truncate fdiff) (* maxwrap dbig)))))) |
| 149 | 166 | ||
| 150 | (defun xterm-mouse-event () | 167 | ;; Normal terminal mouse click reporting: expect three bytes, of the |
| 151 | "Convert XTerm mouse event to Emacs mouse event." | 168 | ;; form <BUTTON+32> <X+32> <Y+32>. Return a list (EVENT-TYPE X Y). |
| 152 | (let* ((type (- (xterm-mouse-event-read) #o40)) | 169 | (defun xterm-mouse--read-event-sequence-1000 () |
| 153 | (x (- (xterm-mouse-event-read) #o40 1)) | 170 | (list (let ((code (- (xterm-mouse-event-read) 32))) |
| 154 | (y (- (xterm-mouse-event-read) #o40 1)) | 171 | (intern |
| 172 | ;; For buttons > 3, the release-event looks differently | ||
| 173 | ;; (see xc/programs/xterm/button.c, function EditorButton), | ||
| 174 | ;; and come in a release-event only, no down-event. | ||
| 175 | (cond ((>= code 64) | ||
| 176 | (format "mouse-%d" (- code 60))) | ||
| 177 | ((memq code '(8 9 10)) | ||
| 178 | (setq xterm-mouse-last code) | ||
| 179 | (format "M-down-mouse-%d" (- code 7))) | ||
| 180 | ((= code 11) | ||
| 181 | (format "M-mouse-%d" (- xterm-mouse-last 7))) | ||
| 182 | ((= code 3) | ||
| 183 | ;; For buttons > 5 xterm only reports a | ||
| 184 | ;; button-release event. Avoid error by mapping | ||
| 185 | ;; them all to mouse-1. | ||
| 186 | (format "mouse-%d" (+ 1 (or xterm-mouse-last 0)))) | ||
| 187 | (t | ||
| 188 | (setq xterm-mouse-last code) | ||
| 189 | (format "down-mouse-%d" (+ 1 code)))))) | ||
| 190 | ;; x and y coordinates | ||
| 191 | (- (xterm-mouse-event-read) 33) | ||
| 192 | (- (xterm-mouse-event-read) 33))) | ||
| 193 | |||
| 194 | ;; XTerm's 1006-mode terminal mouse click reporting has the form | ||
| 195 | ;; <BUTTON> ; <X> ; <Y> <M or m>, where the button and ordinates are | ||
| 196 | ;; in encoded (decimal) form. Return a list (EVENT-TYPE X Y). | ||
| 197 | (defun xterm-mouse--read-event-sequence-1006 () | ||
| 198 | (let (button-bytes x-bytes y-bytes c) | ||
| 199 | (while (not (eq (setq c (xterm-mouse-event-read)) ?\;)) | ||
| 200 | (push c button-bytes)) | ||
| 201 | (while (not (eq (setq c (xterm-mouse-event-read)) ?\;)) | ||
| 202 | (push c x-bytes)) | ||
| 203 | (while (not (memq (setq c (xterm-mouse-event-read)) '(?m ?M))) | ||
| 204 | (push c y-bytes)) | ||
| 205 | (list (let* ((code (string-to-number | ||
| 206 | (apply 'string (nreverse button-bytes)))) | ||
| 207 | (wheel (>= code 64)) | ||
| 208 | (down (and (not wheel) | ||
| 209 | (eq c ?M)))) | ||
| 210 | (intern (format "%s%smouse-%d" | ||
| 211 | (cond (wheel "") | ||
| 212 | ((< code 4) "") | ||
| 213 | ((< code 8) "S-") | ||
| 214 | ((< code 12) "M-") | ||
| 215 | ((< code 16) "M-S-") | ||
| 216 | ((< code 20) "C-") | ||
| 217 | ((< code 24) "C-S-") | ||
| 218 | ((< code 28) "C-M-") | ||
| 219 | ((< code 32) "C-M-S-") | ||
| 220 | (t | ||
| 221 | (error "Unexpected escape sequence from XTerm"))) | ||
| 222 | (if down "down-" "") | ||
| 223 | (if wheel | ||
| 224 | (- code 60) | ||
| 225 | (1+ (setq xterm-mouse-last (mod code 4))))))) | ||
| 226 | (1- (string-to-number (apply 'string (nreverse x-bytes)))) | ||
| 227 | (1- (string-to-number (apply 'string (nreverse y-bytes))))))) | ||
| 228 | |||
| 229 | (defun xterm-mouse-event (&optional extension) | ||
| 230 | "Convert XTerm mouse event to Emacs mouse event. | ||
| 231 | EXTENSION, if non-nil, means to use an extension to the usual | ||
| 232 | terminal mouse protocol; we currently support the value 1006, | ||
| 233 | which is the \"1006\" extension implemented in Xterm >= 277." | ||
| 234 | (let* ((click (cond ((null extension) | ||
| 235 | (xterm-mouse--read-event-sequence-1000)) | ||
| 236 | ((eq extension 1006) | ||
| 237 | (xterm-mouse--read-event-sequence-1006)) | ||
| 238 | (t | ||
| 239 | (error "Unsupported XTerm mouse protocol")))) | ||
| 240 | (type (nth 0 click)) | ||
| 241 | (x (nth 1 click)) | ||
| 242 | (y (nth 2 click)) | ||
| 155 | ;; Emulate timestamp information. This is accurate enough | 243 | ;; Emulate timestamp information. This is accurate enough |
| 156 | ;; for default value of mouse-1-click-follows-link (450msec). | 244 | ;; for default value of mouse-1-click-follows-link (450msec). |
| 157 | (timestamp (xterm-mouse-truncate-wrap | 245 | (timestamp (xterm-mouse-truncate-wrap |
| @@ -159,36 +247,15 @@ | |||
| 159 | (- (float-time) | 247 | (- (float-time) |
| 160 | (or xt-mouse-epoch | 248 | (or xt-mouse-epoch |
| 161 | (setq xt-mouse-epoch (float-time))))))) | 249 | (setq xt-mouse-epoch (float-time))))))) |
| 162 | (mouse (intern | ||
| 163 | ;; For buttons > 3, the release-event looks | ||
| 164 | ;; differently (see xc/programs/xterm/button.c, | ||
| 165 | ;; function EditorButton), and there seems to come in | ||
| 166 | ;; a release-event only, no down-event. | ||
| 167 | (cond ((>= type 64) | ||
| 168 | (format "mouse-%d" (- type 60))) | ||
| 169 | ((memq type '(8 9 10)) | ||
| 170 | (setq xterm-mouse-last type) | ||
| 171 | (format "M-down-mouse-%d" (- type 7))) | ||
| 172 | ((= type 11) | ||
| 173 | (format "mouse-%d" (- xterm-mouse-last 7))) | ||
| 174 | ((= type 3) | ||
| 175 | ;; For buttons > 5 xterm only reports a | ||
| 176 | ;; button-release event. Avoid error by mapping | ||
| 177 | ;; them all to mouse-1. | ||
| 178 | (format "mouse-%d" (+ 1 (or xterm-mouse-last 0)))) | ||
| 179 | (t | ||
| 180 | (setq xterm-mouse-last type) | ||
| 181 | (format "down-mouse-%d" (+ 1 type)))))) | ||
| 182 | (w (window-at x y)) | 250 | (w (window-at x y)) |
| 183 | (ltrb (window-edges w)) | 251 | (ltrb (window-edges w)) |
| 184 | (left (nth 0 ltrb)) | 252 | (left (nth 0 ltrb)) |
| 185 | (top (nth 1 ltrb))) | 253 | (top (nth 1 ltrb))) |
| 186 | |||
| 187 | (set-terminal-parameter nil 'xterm-mouse-x x) | 254 | (set-terminal-parameter nil 'xterm-mouse-x x) |
| 188 | (set-terminal-parameter nil 'xterm-mouse-y y) | 255 | (set-terminal-parameter nil 'xterm-mouse-y y) |
| 189 | (setq | 256 | (setq |
| 190 | last-input-event | 257 | last-input-event |
| 191 | (list mouse | 258 | (list type |
| 192 | (let ((event (if w | 259 | (let ((event (if w |
| 193 | (posn-at-x-y (- x left) (- y top) w t) | 260 | (posn-at-x-y (- x left) (- y top) w t) |
| 194 | (append (list nil 'menu-bar) | 261 | (append (list nil 'menu-bar) |
| @@ -248,11 +315,14 @@ down the SHIFT key while pressing the mouse button." | |||
| 248 | ;; FIXME: is there more elegant way to detect the initial terminal? | 315 | ;; FIXME: is there more elegant way to detect the initial terminal? |
| 249 | (not (string= (terminal-name terminal) "initial_terminal"))) | 316 | (not (string= (terminal-name terminal) "initial_terminal"))) |
| 250 | (unless (terminal-parameter terminal 'xterm-mouse-mode) | 317 | (unless (terminal-parameter terminal 'xterm-mouse-mode) |
| 251 | ;; Simulate selecting a terminal by selecting one of its frames ;-( | 318 | ;; Simulate selecting a terminal by selecting one of its frames |
| 252 | (with-selected-frame (car (frames-on-display-list terminal)) | 319 | (with-selected-frame (car (frames-on-display-list terminal)) |
| 253 | (define-key input-decode-map "\e[M" 'xterm-mouse-translate)) | 320 | (define-key input-decode-map "\e[M" 'xterm-mouse-translate) |
| 321 | (define-key input-decode-map "\e[<" 'xterm-mouse-translate-extended)) | ||
| 254 | (set-terminal-parameter terminal 'xterm-mouse-mode t)) | 322 | (set-terminal-parameter terminal 'xterm-mouse-mode t)) |
| 255 | (send-string-to-terminal "\e[?1000h" terminal))) | 323 | (send-string-to-terminal "\e[?1000h" terminal) |
| 324 | ;; Request extended mouse support, if available (xterm >= 277). | ||
| 325 | (send-string-to-terminal "\e[?1006h" terminal))) | ||
| 256 | 326 | ||
| 257 | (defun turn-off-xterm-mouse-tracking-on-terminal (terminal) | 327 | (defun turn-off-xterm-mouse-tracking-on-terminal (terminal) |
| 258 | "Disable xterm mouse tracking on TERMINAL." | 328 | "Disable xterm mouse tracking on TERMINAL." |
| @@ -268,7 +338,8 @@ down the SHIFT key while pressing the mouse button." | |||
| 268 | ;; command too many times (or to catch an unintended key sequence), than | 338 | ;; command too many times (or to catch an unintended key sequence), than |
| 269 | ;; to send it too few times (or to fail to let xterm-mouse events | 339 | ;; to send it too few times (or to fail to let xterm-mouse events |
| 270 | ;; pass by untranslated). | 340 | ;; pass by untranslated). |
| 271 | (send-string-to-terminal "\e[?1000l" terminal))) | 341 | (send-string-to-terminal "\e[?1000l" terminal) |
| 342 | (send-string-to-terminal "\e[?1006l" terminal))) | ||
| 272 | 343 | ||
| 273 | (provide 'xt-mouse) | 344 | (provide 'xt-mouse) |
| 274 | 345 | ||