[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: local keymap patch for key-binding
From: |
David Kastrup |
Subject: |
Re: local keymap patch for key-binding |
Date: |
Sun, 10 Sep 2006 15:25:51 +0200 |
User-agent: |
Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (gnu/linux) |
Chong Yidong <address@hidden> writes:
> David Kastrup <address@hidden> writes:
>
>> It does too little. Check out what read-key-sequence (defined in
>> keyboard.c) does with regard to mouse events (EVENT_HAS_PARAMETERS).
>> The problem is that read-key-sequence does such a load of other stuff
>> that it is hard to extract the material and transfer it to
>> key-binding.
>>
>> The problem is that keymaps may be provided by text properties and
>> overlays, and by keymap properties on strings that display as the
>> display or before-string or after-string properties of text properties
>> or overlays.
>
> I just verified that my patch truly works for keymaps on display
> strings, text properties, and overlays. For example, with
>
> (with-output-to-temp-buffer "Testo"
> (set-buffer "Testo")
> (erase-buffer)
> (let* ((map (make-sparse-keymap))
> (str (propertize "foostring" 'keymap map 'mouse-face 'highlight))
> ovr)
> (define-key map [mouse-1] 'delete-window)
> (insert "1234567890")
> (setq ovr (make-overlay 2 3))
> (overlay-put ovr 'keymap map)
> (overlay-put ovr 'mouse-face 'highlight)
> (put-text-property 5 6 'display str)
> (put-text-property 8 9 'keymap map)
> (put-text-property 8 9 'mouse-face 'highlight)))
>
> C-h k followed by mouse-1 on the overlay, display string, or text
> propertized region all report the correct action for the given local
> keymap.
Uh, C-h k has extra code doing this sort of lookup. It does not rely
on key-binding. So you should not test this with C-h k unless you
have previously dumbed it down with
(defun string-key-binding (&rest ignore) nil)
after help.el has been loaded.
> The reason is that the mouse event passed to `key-binding' contains
> all the information you need to reconstruct the binding directly
> (including whether or not the object we are looking at is a buffer
> position or a string.)
>
> So it seems like there's no problem.
Amazing. Do you have an idea why the stuff in read-key-sequence
concerning mouse related maps appears so much more complicated? Or is
it just me? Some complication, of course, is due to read-key-sequence
having to _assemble_ a key sequence instead of merely looking it up.
But still...
Concretely, we have the following in keyboard.c concerning mouse
events, and I'll add my own comments with // in between.
if (EVENT_HAS_PARAMETERS (key))
{
Lisp_Object kind;
Lisp_Object string;
kind = EVENT_HEAD_KIND (EVENT_HEAD (key));
if (EQ (kind, Qmouse_click))
{
Lisp_Object window, posn;
window = POSN_WINDOW (EVENT_START (key));
posn = POSN_POSN (EVENT_START (key));
// Fake prefixes probably not relevant for keybinding-lookup
if (CONSP (posn)
|| (!NILP (fake_prefixed_keys)
&& !NILP (Fmemq (key, fake_prefixed_keys))))
{
// elided
}
/* Key sequences beginning with mouse clicks are
read using the keymaps in the buffer clicked on,
not the current buffer. If we're at the
beginning of a key sequence, switch buffers. */
// Do you change the buffer accordingly in your patch?
if (last_real_key_start == 0
&& WINDOWP (window)
&& BUFFERP (XWINDOW (window)->buffer)
&& XBUFFER (XWINDOW (window)->buffer) != current_buffer)
{
XVECTOR (raw_keybuf)->contents[raw_keybuf_count++] = key;
keybuf[t] = key;
mock_input = t + 1;
/* Arrange to go back to the original buffer once we're
done reading the key sequence. Note that we can't
use save_excursion_{save,restore} here, because they
save point as well as the current buffer; we don't
want to save point, because redisplay may change it,
to accommodate a Fset_window_start or something. We
don't want to do this at the top of the function,
because we may get input from a subprocess which
wants to change the selected window and stuff (say,
emacsclient). */
record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
Fkill_emacs (Qnil);
set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
orig_local_map = get_local_map (PT, current_buffer,
Qlocal_map);
orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
goto replay_sequence;
// This starts the whole lookup sequence with new values for local-map
// and, well, I don't quite understand what Qkeymap is.
}
/* For a mouse click, get the local text-property keymap
of the place clicked on, rather than point. */
if (last_real_key_start == 0
&& CONSP (XCDR (key))
&& ! localized_local_map)
{
Lisp_Object map_here, start, pos;
localized_local_map = 1;
start = EVENT_START (key);
if (CONSP (start) && POSN_INBUFFER_P (start))
{
pos = POSN_BUFFER_POSN (start);
if (INTEGERP (pos)
&& XINT (pos) >= BEG && XINT (pos) <= Z)
{
map_here = get_local_map (XINT (pos),
current_buffer, Qlocal_map);
if (!EQ (map_here, orig_local_map))
{
orig_local_map = map_here;
keybuf[t] = key;
mock_input = t + 1;
goto replay_sequence;
}
map_here = get_local_map (XINT (pos),
current_buffer, Qkeymap);
if (!EQ (map_here, orig_keymap))
{
orig_keymap = map_here;
keybuf[t] = key;
mock_input = t + 1;
goto replay_sequence;
}
}
}
}
// Another class of events: but they mostly don't require looking in
// other maps
/* Expand mode-line and scroll-bar events into two events:
use posn as a fake prefix key. */
if (SYMBOLP (posn)
&& (NILP (fake_prefixed_keys)
|| NILP (Fmemq (key, fake_prefixed_keys))))
{
if (t + 1 >= bufsize)
error ("Key sequence too long");
keybuf[t] = posn;
keybuf[t + 1] = key;
mock_input = t + 2;
/* Record that a fake prefix key has been generated
for KEY. Don't modify the event; this would
prevent proper action when the event is pushed
back into unread-command-events. */
fake_prefixed_keys = Fcons (key, fake_prefixed_keys);
// Except in the following case:
/* If on a mode line string with a local keymap,
reconsider the key sequence with that keymap. */
if (string = POSN_STRING (EVENT_START (key)),
(CONSP (string) && STRINGP (XCAR (string))))
{
Lisp_Object pos, map, map2;
pos = XCDR (string);
string = XCAR (string);
if (XINT (pos) >= 0
&& XINT (pos) < SCHARS (string))
{
map = Fget_text_property (pos, Qlocal_map, string);
if (!NILP (map))
orig_local_map = map;
map2 = Fget_text_property (pos, Qkeymap, string);
if (!NILP (map2))
orig_keymap = map2;
if (!NILP (map) || !NILP (map2))
goto replay_sequence;
}
}
goto replay_key;
}
else if (NILP (from_string)
&& (string = POSN_STRING (EVENT_START (key)),
(CONSP (string) && STRINGP (XCAR (string)))))
{
/* 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, map, map2;
pos = XCDR (string);
string = XCAR (string);
if (XINT (pos) >= 0
&& XINT (pos) < SCHARS (string))
{
map = Fget_text_property (pos, Qlocal_map, string);
if (!NILP (map))
orig_local_map = map;
map2 = Fget_text_property (pos, Qkeymap, string);
if (!NILP (map2))
orig_keymap = map2;
if (!NILP (map) || !NILP (map2))
{
from_string = string;
goto replay_sequence;
}
}
}
}
// Menu bar: seemingly does not require other maps.
else if (CONSP (XCDR (key))
&& CONSP (EVENT_START (key))
&& CONSP (XCDR (EVENT_START (key))))
{
Lisp_Object posn;
posn = POSN_POSN (EVENT_START (key));
/* Handle menu-bar events:
insert the dummy prefix event `menu-bar'. */
if (EQ (posn, Qmenu_bar) || EQ (posn, Qtool_bar))
{
if (t + 1 >= bufsize)
error ("Key sequence too long");
keybuf[t] = posn;
keybuf[t+1] = key;
/* Zap the position in key, so we know that we've
expanded it, and don't try to do so again. */
POSN_SET_POSN (EVENT_START (key),
Fcons (posn, Qnil));
mock_input = t + 2;
goto replay_sequence;
}
else if (CONSP (posn))
{
/* We're looking at the second event of a
sequence which we expanded before. Set
last_real_key_start appropriately. */
if (last_real_key_start == t && t > 0)
last_real_key_start = t - 1;
}
}
}
If it seems to you that your patch gets the same cases (and with the
same order of priorities), that would be great!
Another thing: I had proposed an additional optional "LOCATION"
argument for key-binding.
--
David Kastrup, Kriemhildstr. 15, 44793 Bochum
- local keymap patch for key-binding, Chong Yidong, 2006/09/09
- Re: local keymap patch for key-binding, David Kastrup, 2006/09/09
- Re: local keymap patch for key-binding, Chong Yidong, 2006/09/09
- Re: local keymap patch for key-binding, Chong Yidong, 2006/09/10
- Re: local keymap patch for key-binding,
David Kastrup <=
- Re: local keymap patch for key-binding, Chong Yidong, 2006/09/10
- Re: local keymap patch for key-binding, David Kastrup, 2006/09/11
- Re: local keymap patch for key-binding, David Kastrup, 2006/09/11
- Re: local keymap patch for key-binding, Kim F. Storm, 2006/09/11
- Re: local keymap patch for key-binding, David Kastrup, 2006/09/11
- Re: local keymap patch for key-binding, David Kastrup, 2006/09/11
- Re: local keymap patch for key-binding, Kim F. Storm, 2006/09/11
- Re: local keymap patch for key-binding, David Kastrup, 2006/09/11
- Re: local keymap patch for key-binding, Chong Yidong, 2006/09/11
- Re: local keymap patch for key-binding, Richard Stallman, 2006/09/11