Subject: Re: bug#6372: 24.0.50; C-mouse-1 activates region

From: Eli Zaretskii <[email-masked]>
Date: Sat, 21 Jul 2012 14:42:06 +0300

> From: Chong Yidong <[email-masked]>
> Cc: Drew Adams <[email-masked]>,  [email-masked]
> Date: Mon, 09 Jul 2012 12:37:05 +0800
> 
> Eli Zaretskii <[email-masked]> writes:
> 
> > Indeed.  After the recipe, "C-h l" shows this:
> >
> >   <C-down-mouse-1> <drag-mouse-1> C-h l
> >
> > What do you see on GNU/Linux?  Which toolkit(s) did you try it with?
> >
> > FWIW, in the MSDOS build the problem doesn't happen, and view-lossage
> > shows just this:
> >
> >   <C-down-mouse-1> C-h l
> >
> > Any clue where could drag-mouse-1 come from?  I guess we don't discard
> > some events that we should.
> 
> On GNU/Linux (both GTK build and Lucid build) I see
> 
>   <C-down-mouse-1> C-h l

Thanks.

I'm sorry, but it will take someone who knows more than I do about
MS-Windows messages and their processing to fix this one.  I describe
my findings below in the hope that someone will pick up where I left
off.

We track mouse events during pop-up menu by sending the
WM_EMACS_TRACKPOPUPMENU message to the Emacs message pump.  This
message is handled by w32_wnd_proc around line 3770 of w32fns.c.
There, we call TrackPopupMenu, a Windows API that displays the menu
and returns the user selection of menu items.  After TrackPopupMenu
returns, we remove any mouse events still in the message queue, by
calling PeekMessage with appropriate arguments, and return the user
selection to our caller, which is w32_menu_show.  The user selection
returned is zero when the user closes the menu without selecting any
item, by clicking outside the menu.  w32_menu_show then removes any
mouse events in the Emacs event queue by calling discard_mouse_events.

What happens in this case, and is the reason for the bug, is that
somehow the mouse click event that pops down the menu is not delivered
to Emacs until _after_ w32_menu_show returns.  That click is not
removed by PeekMessage mentioned above, and is not discarded by
discard_mouse_events.  It is read by w32_wnd_proc only after all of
the above processing is complete, and any memory of the menu that was
popped down is gone.  So Emacs processes that mouse click as a normal
event, oblivious to the fact that it actually happened as part of the
menu.

What I don't understand here is why that mouse click is not delivered
when we call PeekMessage, so that it could be discarded.  It's as if
Windows withholds that message from being put into the Emacs message
queue.  Why is that, and what can we do to be able to peek at that
click message as part of menu processing and discard it, is beyond me.