aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChong Yidong2012-07-14 23:40:12 +0800
committerChong Yidong2012-07-14 23:40:12 +0800
commit63408057e7b8f8f9e04fa689117c75b498406daf (patch)
treeabcfef7f0c68d7591dd5b5043844018c23c9cd16
parent28ca98ac5218a3a14ae57f425ac226fc8fc0f6e4 (diff)
downloademacs-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/ChangeLog14
-rw-r--r--lisp/xt-mouse.el179
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 @@
12012-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
12012-07-14 Leo Liu <sdl.web@gmail.com> 152012-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.
59Similar to `xterm-mouse-translate', but using the \"1006\"
60extension, which supports coordinates >= 231 (see
61http://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.
231EXTENSION, if non-nil, means to use an extension to the usual
232terminal mouse protocol; we currently support the value 1006,
233which 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