diff --git a/src/keymap.c b/src/keymap.c index 295b209f06b..a01dee1476b 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -1721,33 +1721,12 @@ means to return the active maps for that window's buffer. */) /* For a mouse click, get the local text-property keymap of the place clicked on, rather than point. */ - if (POSN_INBUFFER_P (position)) - { - Lisp_Object pos = POSN_BUFFER_POSN (position); - if (FIXNUMP (pos) - && XFIXNUM (pos) >= BEG && XFIXNUM (pos) <= Z) - { - local_map = get_local_map (XFIXNUM (pos), - current_buffer, Qlocal_map); - - keymap = get_local_map (XFIXNUM (pos), - current_buffer, Qkeymap); - } - } - - Lisp_Object pos_area = POSN_POSN (position); - if (EQ (pos_area, Qmode_line) || EQ (pos_area, Qheader_line)) - { - /* For clicks on mode line or header line, ignore the maps - we found at POSITION, because properties at point are - not relevant in that case. */ - local_map = Qnil; - keymap = Qnil; - } + local_map = Qnil; + keymap = Qnil; /* If on a mode line string with a local keymap, or for a click on a string, i.e. overlay string or a string - displayed via the `display' property, consider only the + displayed via the `display' property, first consider the `local-map' and `keymap' properties of that string. */ if (CONSP (string) && STRINGP (XCAR (string))) @@ -1763,6 +1742,26 @@ means to return the active maps for that window's buffer. */) } } + Lisp_Object buffer_posn = POSN_BUFFER_POSN (position); + /* Then, if the click was in the buffer, get the local + text-property keymap of the place clicked on. */ + + if (FIXNUMP (buffer_posn) + && XFIXNUM (buffer_posn) >= BEG && XFIXNUM (buffer_posn) <= Z) + { + /* The properties in POSN_STRING take precedence, if set. */ + if (NILP (local_map)) + local_map = get_local_map (XFIXNUM (buffer_posn), + current_buffer, Qlocal_map); + + if (NILP (keymap)) + keymap = get_local_map (XFIXNUM (buffer_posn), + current_buffer, Qkeymap); + } + + /* Finally, fall back on the buffer's local map. */ + if (NILP (local_map)) + local_map = BVAR (current_buffer, keymap); } if (!NILP (local_map)) diff --git a/test/src/keymap-tests.el b/test/src/keymap-tests.el index 950c741a6dd..0d203f6fcb0 100644 --- a/test/src/keymap-tests.el +++ b/test/src/keymap-tests.el @@ -509,25 +509,36 @@ g .. h foo ;; From the parent this time/ (should (equal (keymap-lookup map "u") #'undo)))) +(defun keymap-test--get-maps (posn) + (let ((maps (current-active-maps nil posn))) + ;; The local map should always be present. + (should (memq (current-local-map) maps)) + maps)) + (defun keymap-test--maps-for-posn (area string) - (current-active-maps - nil + (keymap-test--get-maps ;; FIXME: This test would be better if this was a real position ;; created by a real click. - `(,(selected-window) ,area (1 . 1) 0 (,string . 0) nil (1 . 1) nil (1 . 1) (1 . 1)))) + (let (;; If AREA is passed, the click isn't in the buffer; otherwise + ;; it's at position 1. + (pos (if area nil 1))) + `(,(selected-window) ,area (1 . 1) 0 (,string . 0) + ,pos (1 . 1) nil (1 . 1) (1 . 1))))) (ert-deftest keymap-test-keymaps-for-non-buffer-positions () "`current-active-maps' with non-buffer positions. (bug#76620)" (with-temp-buffer (pop-to-buffer (current-buffer)) (let ((keymap (make-sparse-keymap "keymap-at-point"))) + (use-local-map (make-sparse-keymap "buffer-local-map")) (insert (propertize "string" 'keymap keymap)) (goto-char (point-min)) - (should (memq keymap (current-active-maps))) + (should (memq keymap (keymap-test--get-maps nil))) (should-not (memq keymap (keymap-test--maps-for-posn 'mode-line nil))) (should-not (memq keymap (keymap-test--maps-for-posn 'mode-line "s"))) - (should-not (memq keymap (keymap-test--maps-for-posn nil "s"))) + (should (memq keymap (keymap-test--maps-for-posn nil "s"))) (should (memq keymap (keymap-test--maps-for-posn nil nil))) + (should (memq keymap (keymap-test--get-maps "a"))) (let* ((mode-line-keymap (make-sparse-keymap "keymap-in-mode-line")) (s (propertize "string" 'keymap mode-line-keymap))) ;; Respect `keymap' in the string clicked on.