]> code.delx.au - gnu-emacs/blobdiff - lisp/xt-mouse.el
Close bug#3992.
[gnu-emacs] / lisp / xt-mouse.el
index bf4eeab2259ec7561c88b0a73e5c5d046a418b5b..f802103fbd7a872db95e4d3d1c07636c47310913 100644 (file)
@@ -1,17 +1,17 @@
 ;;; xt-mouse.el --- support the mouse when emacs run in an xterm
 
 ;; Copyright (C) 1994, 2000, 2001, 2002, 2003,
 ;;; xt-mouse.el --- support the mouse when emacs run in an xterm
 
 ;; Copyright (C) 1994, 2000, 2001, 2002, 2003,
-;;   2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+;;   2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: mouse, terminals
 
 ;; This file is part of GNU Emacs.
 
 
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: mouse, terminals
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -19,9 +19,7 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
 
 ;;; Commentary:
 
@@ -45,8 +43,6 @@
 
 (defvar xterm-mouse-debug-buffer nil)
 
 
 (defvar xterm-mouse-debug-buffer nil)
 
-(define-key function-key-map "\e[M" 'xterm-mouse-translate)
-
 (defvar xterm-mouse-last)
 
 ;; Mouse events symbols must have an 'event-kind property with
 (defvar xterm-mouse-last)
 
 ;; Mouse events symbols must have an 'event-kind property with
@@ -77,7 +73,7 @@
            (error "Unexpected escape sequence from XTerm")))
 
        (let* ((click (if is-click down (xterm-mouse-event)))
            (error "Unexpected escape sequence from XTerm")))
 
        (let* ((click (if is-click down (xterm-mouse-event)))
-              (click-command (nth 0 click))
+              ;; (click-command (nth 0 click))
               (click-data (nth 1 click))
               (click-where (nth 1 click-data)))
          (if (memq down-binding '(nil ignore))
               (click-data (nth 1 click))
               (click-where (nth 1 click-data)))
          (if (memq down-binding '(nil ignore))
                (vector (list down-where down-data) down)
              (vector down))))))))
 
                (vector (list down-where down-data) down)
              (vector down))))))))
 
-(defvar xterm-mouse-x 0
-  "Position of last xterm mouse event relative to the frame.")
-
-(defvar xterm-mouse-y 0
-  "Position of last xterm mouse event relative to the frame.")
+;; These two variables have been converted to terminal parameters.
+;;
+;;(defvar xterm-mouse-x 0
+;;  "Position of last xterm mouse event relative to the frame.")
+;;
+;;(defvar xterm-mouse-y 0
+;;  "Position of last xterm mouse event relative to the frame.")
 
 (defvar xt-mouse-epoch nil)
 
 
 (defvar xt-mouse-epoch nil)
 
 
 (defun xterm-mouse-position-function (pos)
   "Bound to `mouse-position-function' in XTerm mouse mode."
 
 (defun xterm-mouse-position-function (pos)
   "Bound to `mouse-position-function' in XTerm mouse mode."
-  (setcdr pos (cons xterm-mouse-x xterm-mouse-y))
+  (when (terminal-parameter nil 'xterm-mouse-x)
+    (setcdr pos (cons (terminal-parameter nil 'xterm-mouse-x)
+                     (terminal-parameter nil 'xterm-mouse-y))))
   pos)
 
 ;; read xterm sequences above ascii 127 (#x7f)
 (defun xterm-mouse-event-read ()
   (let ((c (read-char)))
   pos)
 
 ;; read xterm sequences above ascii 127 (#x7f)
 (defun xterm-mouse-event-read ()
   (let ((c (read-char)))
-    (if (< c 0)
-        (+ c #x8000000 128)
+    (if (> c #x3FFF80)
+        (+ 128 (- c #x3FFF80))
       c)))
 
 (defun xterm-mouse-truncate-wrap (f)
       c)))
 
 (defun xterm-mouse-truncate-wrap (f)
                       ((= type 11)
                        (format "mouse-%d" (- xterm-mouse-last 7)))
                       ((= type 3)
                       ((= type 11)
                        (format "mouse-%d" (- xterm-mouse-last 7)))
                       ((= type 3)
-                       (format "mouse-%d" (+ 1 xterm-mouse-last)))
+                       ;; For buttons > 5 xterm only reports a
+                       ;; button-release event.  Avoid error by mapping
+                       ;; them all to mouse-1.
+                       (format "mouse-%d" (+ 1 (or xterm-mouse-last 0))))
                       (t
                        (setq xterm-mouse-last type)
                        (format "down-mouse-%d" (+ 1 type))))))
                       (t
                        (setq xterm-mouse-last type)
                        (format "down-mouse-%d" (+ 1 type))))))
          (left (nth 0 ltrb))
          (top (nth 1 ltrb)))
 
          (left (nth 0 ltrb))
          (top (nth 1 ltrb)))
 
-    (setq xterm-mouse-x x
-         xterm-mouse-y y)
+    (set-terminal-parameter nil 'xterm-mouse-x x)
+    (set-terminal-parameter nil 'xterm-mouse-y y)
     (setq
      last-input-event
      (list mouse
     (setq
      last-input-event
      (list mouse
 ;;;###autoload
 (define-minor-mode xterm-mouse-mode
   "Toggle XTerm mouse mode.
 ;;;###autoload
 (define-minor-mode xterm-mouse-mode
   "Toggle XTerm mouse mode.
-With prefix arg, turn XTerm mouse mode on iff arg is positive.
+With prefix arg, turn XTerm mouse mode on if arg is positive, otherwise turn
+it off.
 
 Turn it on to use Emacs mouse commands, and off to use xterm mouse commands.
 This works in terminal emulators compatible with xterm.  It only
 
 Turn it on to use Emacs mouse commands, and off to use xterm mouse commands.
 This works in terminal emulators compatible with xterm.  It only
@@ -199,9 +203,21 @@ single clicks are supported.  When turned on, the normal xterm
 mouse functionality for such clicks is still available by holding
 down the SHIFT key while pressing the mouse button."
   :global t :group 'mouse
 mouse functionality for such clicks is still available by holding
 down the SHIFT key while pressing the mouse button."
   :global t :group 'mouse
+  (let ((do-hook (if xterm-mouse-mode 'add-hook 'remove-hook)))
+    (funcall do-hook 'terminal-init-xterm-hook
+             'turn-on-xterm-mouse-tracking-on-terminal)
+    (funcall do-hook 'delete-terminal-functions
+             'turn-off-xterm-mouse-tracking-on-terminal)
+    (funcall do-hook 'suspend-tty-functions
+             'turn-off-xterm-mouse-tracking-on-terminal)
+    (funcall do-hook 'resume-tty-functions
+             'turn-on-xterm-mouse-tracking-on-terminal)
+    (funcall do-hook 'suspend-hook 'turn-off-xterm-mouse-tracking)
+    (funcall do-hook 'suspend-resume-hook 'turn-on-xterm-mouse-tracking)
+    (funcall do-hook 'kill-emacs-hook 'turn-off-xterm-mouse-tracking))
   (if xterm-mouse-mode
       ;; Turn it on
   (if xterm-mouse-mode
       ;; Turn it on
-      (unless window-system
+      (progn
        (setq mouse-position-function #'xterm-mouse-position-function)
        (turn-on-xterm-mouse-tracking))
     ;; Turn it off
        (setq mouse-position-function #'xterm-mouse-position-function)
        (turn-on-xterm-mouse-tracking))
     ;; Turn it off
@@ -210,18 +226,42 @@ down the SHIFT key while pressing the mouse button."
 
 (defun turn-on-xterm-mouse-tracking ()
   "Enable Emacs mouse tracking in xterm."
 
 (defun turn-on-xterm-mouse-tracking ()
   "Enable Emacs mouse tracking in xterm."
-  (if xterm-mouse-mode
-      (send-string-to-terminal "\e[?1000h")))
+  (dolist (terminal (terminal-list))
+    (turn-on-xterm-mouse-tracking-on-terminal terminal)))
 
 (defun turn-off-xterm-mouse-tracking (&optional force)
   "Disable Emacs mouse tracking in xterm."
 
 (defun turn-off-xterm-mouse-tracking (&optional force)
   "Disable Emacs mouse tracking in xterm."
-  (if (or force xterm-mouse-mode)
-      (send-string-to-terminal "\e[?1000l")))
-
-;; Restore normal mouse behaviour outside Emacs.
-(add-hook 'suspend-hook 'turn-off-xterm-mouse-tracking)
-(add-hook 'suspend-resume-hook 'turn-on-xterm-mouse-tracking)
-(add-hook 'kill-emacs-hook 'turn-off-xterm-mouse-tracking)
+  (dolist (terminal (terminal-list))
+    (turn-off-xterm-mouse-tracking-on-terminal terminal)))
+
+(defun turn-on-xterm-mouse-tracking-on-terminal (&optional terminal)
+  "Enable xterm mouse tracking on TERMINAL."
+  (when (and xterm-mouse-mode (eq t (terminal-live-p terminal))
+            ;; Avoid the initial terminal which is not a termcap device.
+            ;; FIXME: is there more elegant way to detect the initial terminal?
+            (not (string= (terminal-name terminal) "initial_terminal")))
+    (unless (terminal-parameter terminal 'xterm-mouse-mode)
+      ;; Simulate selecting a terminal by selecting one of its frames ;-(
+      (with-selected-frame (car (frames-on-display-list terminal))
+        (define-key input-decode-map "\e[M" 'xterm-mouse-translate))
+      (set-terminal-parameter terminal 'xterm-mouse-mode t))
+    (send-string-to-terminal "\e[?1000h" terminal)))
+
+(defun turn-off-xterm-mouse-tracking-on-terminal (terminal)
+  "Disable xterm mouse tracking on TERMINAL."
+  ;; Only send the disable command to those terminals to which we've already
+  ;; sent the enable command.
+  (when (and (terminal-parameter terminal 'xterm-mouse-mode)
+             (eq t (terminal-live-p terminal))
+            ;; Avoid the initial terminal which is not a termcap device.
+            ;; FIXME: is there more elegant way to detect the initial terminal?
+            (not (string= (terminal-name terminal) "initial_terminal")))
+    ;; We could remove the key-binding and unset the `xterm-mouse-mode'
+    ;; terminal parameter, but it seems less harmful to send this escape
+    ;; command too many times (or to catch an unintended key sequence), than
+    ;; to send it too few times (or to fail to let xterm-mouse events
+    ;; pass by untranslated).
+    (send-string-to-terminal "\e[?1000l" terminal)))
 
 (provide 'xt-mouse)
 
 
 (provide 'xt-mouse)