Subject: bug#102: keymap property ignored for mouse click on overlay

From: Chong Yidong <[email-masked]>
Date: Tue, 15 Apr 2008 19:50:03 -0400

> (setq foo-map (make-sparse-keymap))
> (define-key foo-map [mouse-2] 'bar)
> 
> (defun foo (beg end)
>   (interactive "r")
>   (let ((overlay (make-overlay beg end)))
>     (overlay-put
>      overlay 'display
>      (propertize "xxxxxxxxx" 'face 'font-lock-constant-face))
>     (overlay-put overlay 'keymap foo-map)))
> 
> (defun bar (event) (interactive "e") (message "BAR"))
> ... 
> I'm guessing that the mouse click on the overlay is noted not as being
> a click on a buffer position that has the overlay but on a buffer
> position that is under the displayed "xxxxxxxxx" but is actually
> outside the text that has the overlay.

First off, could you confirm that this bug, #102, is the same as #71 in
the bug tracker, at

http://debbugs.gnu.org/cgi/bugreport.cgi?bug=71

?  Thanks.

The following patch implements the behavior you are looking for: mouse
clicks on before/after strings and display strings will use the `keymap'
overlay or text property associated with the text position---unless the
string itself defines a `keymap' text property, in which case that
keymap is used instead.

Could you test it out?  Please test as many combinations of
keymaps/overlays/textprops as possible.  Test the output of C-h k also.

*** trunk/src/keyboard.c~	2008-04-15 19:34:26.000000000 -0400
--- trunk/src/keyboard.c	2008-04-15 19:21:34.000000000 -0400
***************
*** 9695,9701 ****
  		  localized_local_map = 1;
  		  start = EVENT_START (key);
  
! 		  if (CONSP (start) && POSN_INBUFFER_P (start))
  		    {
  		      pos = POSN_BUFFER_POSN (start);
  		      if (INTEGERP (pos)
--- 9695,9701 ----
  		  localized_local_map = 1;
  		  start = EVENT_START (key);
  
! 		  if (CONSP (start))
  		    {
  		      pos = POSN_BUFFER_POSN (start);
  		      if (INTEGERP (pos)
*** trunk/src/keymap.c.~1.372.~	2008-04-08 21:55:36.000000000 -0400
--- trunk/src/keymap.c	2008-04-15 14:32:22.000000000 -0400
***************
*** 1682,1705 ****
        if (CONSP (position))
  	{
  	  Lisp_Object string;
  
  	  /* 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;
  
! 	      pos = POSN_BUFFER_POSN (position);
! 	      if (INTEGERP (pos)
! 		  && XINT (pos) >= BEG && XINT (pos) <= Z)
! 		{
! 		  local_map = get_local_map (XINT (pos),
! 					     current_buffer, Qlocal_map);
! 		  
! 		  keymap = get_local_map (XINT (pos),
! 					  current_buffer, Qkeymap);
! 		}
  	    }
  
  	  /* If on a mode line string with a local keymap,
--- 1682,1699 ----
        if (CONSP (position))
  	{
  	  Lisp_Object string;
+ 	  Lisp_Object pos = POSN_BUFFER_POSN (position);
  
  	  /* For a mouse click, get the local text-property keymap
  	     of the place clicked on, rather than point.  */
! 	  if (INTEGERP (pos)
! 	      && XINT (pos) >= BEG && XINT (pos) <= Z)
  	    {
! 	      local_map = get_local_map (XINT (pos),
! 					 current_buffer, Qlocal_map);
  
! 	      keymap = get_local_map (XINT (pos),
! 				      current_buffer, Qkeymap);
  	    }
  
  	  /* If on a mode line string with a local keymap,
***************
*** 1862,1885 ****
        if (CONSP (position))
  	{
  	  Lisp_Object string;
  
  	  /* 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;
  
! 	      pos = POSN_BUFFER_POSN (position);
! 	      if (INTEGERP (pos)
! 		  && XINT (pos) >= BEG && XINT (pos) <= Z)
! 		{
! 		  local_map = get_local_map (XINT (pos),
! 					     current_buffer, Qlocal_map);
! 
! 		  keymap = get_local_map (XINT (pos),
! 					  current_buffer, Qkeymap);
! 		}
  	    }
  
  	  /* If on a mode line string with a local keymap,
--- 1856,1873 ----
        if (CONSP (position))
  	{
  	  Lisp_Object string;
+ 	  Lisp_Object pos = POSN_BUFFER_POSN (position);
  
  	  /* For a mouse click, get the local text-property keymap
  	     of the place clicked on, rather than point.  */
! 	  if (INTEGERP (pos)
! 	      && XINT (pos) >= BEG && XINT (pos) <= Z)
  	    {
! 	      local_map = get_local_map (XINT (pos),
! 					 current_buffer, Qlocal_map);
  
! 	      keymap = get_local_map (XINT (pos),
! 				      current_buffer, Qkeymap);
  	    }
  
  	  /* If on a mode line string with a local keymap,