mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-04 14:40:54 -08:00
Respect keymaps in buffer text for clicks on displayed strings
When clicking on a string displayed by a display property, also look at the text properties of the underlying buffer text for keymaps, not just the displayed string. The displayed string takes precedence over the buffer text, but it doesn't replace it. Also, we should use the buffer's local map even for clicks on the mode line. (Otherwise, what's the point of the <mode-line> event?) * src/keymap.c (Fcurrent_active_maps): Consider displayed string, then buffer text, then fall back to local map. (Bug#79505) * test/src/keymap-tests.el (keymap-test-keymaps-for-non-buffer-positions): Add more tests.
This commit is contained in:
parent
59da5020da
commit
bea16dfe69
2 changed files with 39 additions and 29 deletions
47
src/keymap.c
47
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))
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue