1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-02-04 06:31:13 -08:00

Ignore keymaps at point for positions outside the buffer

Correct a few edge cases where we used the keymaps at point when
looking up keymaps for an event position which is outside the
current buffer.  Namely:

- Clicking on a part of the mode line which is after the end of
  mode-line-format produces an event with non-nil posn-area but
  nil posn-string.

- Even if posn-string doesn't have a local keymap, we should
  still ignore the keymaps at point if posn-string is non-nil.

* src/keymap.c (Fcurrent_active_maps): Ignore keymaps at point
for more positions outside the buffer.  (bug#76620)
This commit is contained in:
Spencer Baugh 2025-08-28 14:13:24 -04:00 committed by Stefan Monnier
parent 82f6c16514
commit 0e9cee2bf5
2 changed files with 43 additions and 22 deletions

View file

@ -1735,11 +1735,20 @@ means to return the active maps for that window's buffer. */)
}
}
/* 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 `local-map' and `keymap' properties of
that string. */
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;
}
/* 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
`local-map' and `keymap' properties of that string. */
if (CONSP (string) && STRINGP (XCAR (string)))
{
@ -1749,23 +1758,8 @@ means to return the active maps for that window's buffer. */)
&& XFIXNUM (pos) >= 0
&& XFIXNUM (pos) < SCHARS (string))
{
Lisp_Object map = Fget_text_property (pos, Qlocal_map,
string);
Lisp_Object pos_area = POSN_POSN (position);
/* For clicks on mode line or header line, override
the maps we found at POSITION unconditionally, even
if the corresponding properties of the mode- or
header-line string are nil, because propertries at
point are not relevant in that case. */
if (!NILP (map)
|| EQ (pos_area, Qmode_line)
|| EQ (pos_area, Qheader_line))
local_map = map;
map = Fget_text_property (pos, Qkeymap, string);
if (!NILP (map)
|| EQ (pos_area, Qmode_line)
|| EQ (pos_area, Qheader_line))
keymap = map;
local_map = Fget_text_property (pos, Qlocal_map, string);
keymap = Fget_text_property (pos, Qkeymap, string);
}
}

View file

@ -509,6 +509,33 @@ g .. h foo
;; From the parent this time/
(should (equal (keymap-lookup map "u") #'undo))))
(defun keymap-test--maps-for-posn (area string)
(current-active-maps
nil
;; 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))))
(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")))
(insert (propertize "string" 'keymap keymap))
(goto-char (point-min))
(should (memq keymap (current-active-maps)))
(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 nil)))
(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.
(should-not (memq keymap (keymap-test--maps-for-posn nil s)))
(should-not (memq keymap (keymap-test--maps-for-posn 'mode-line s)))
(should (memq mode-line-keymap (keymap-test--maps-for-posn nil s)))
(should (memq mode-line-keymap (keymap-test--maps-for-posn 'mode-line s)))))))
(provide 'keymap-tests)
;;; keymap-tests.el ends here