[comp.windows.x] Unwanted Enter/Leave events during XGrabPointer

garya@stan.com (Gary Aitken) (11/17/88)

Consider the following:
  EnterWindowMask, LeaveWindowMask, ButtonPressMask, and ButtonReleaseMask
    are selected for input on a window.
  The pointer is subsequently grabbed while in the window;
    and the pointer is restricted to the window during the grab;
	and grab events are restricted to ButtonPressMask and ButtonReleaseMask.
  While the pointer is grabbed, the window is moved such that the cursor
    would be outside the window if it were not constrained.

Then each time the window is moved, a LeaveNotify followed by an EnterNotify
are generated for the window.

My reading of the event mask passed to XGrabPointer says the Enter/Leave
events should be discarded; is there something I am missing here?

The following code will illustrate the problem.
To run:
    Start it up.
    After you have the windows displayed, type a carriage return.
    Move Pointer into small box.
    You should see an EnterNotify event.
    Press a button and keep it pressed while the window moves.
    You should see a ButtonPress, followed by a series of
      LeaveNotify/EnterNotify events
    Release the button.
	If the small window is still visible,
      you should see a ButtonRelease event.

---------------------------- Cut Here --------------------------------
  
# include <X11/Xlib.h>
# include <X11/Xutil.h>
 main (argc,argv)
    int   argc ;
    char  **argv ;
 {
    static  char     dspnam[] = "unix:0.0" ;
            Display  *dpy ;
            Window   root,w,w1 ;
            XEvent   ev ;
            char     str[10] ;
            int      i ;

  if (dpy = XOpenDisplay(dspnam)) {
    XSynchronize(dpy,1) ;
    root = XRootWindowOfScreen(XScreenOfDisplay(dpy,0)) ;
    w = XCreateSimpleWindow(dpy,root,0,0,100,12,1,1,0) ;
    w1 = XCreateSimpleWindow(dpy,w,0,0,10,10,1,1,0) ;
    XMapWindow(dpy,w1) ;
    XMapWindow(dpy,w) ;
    gets(str) ;
    XSelectInput(dpy,w1,
      EnterWindowMask|LeaveWindowMask|ButtonPressMask|ButtonReleaseMask) ;
    while (1) {
      XNextEvent(dpy,&ev) ;
      switch (ev.type) {
       case (EnterNotify) :
       case (LeaveNotify) :
        printf("type:%d win:0x:%x\n",ev.type,ev.xcrossing.window) ;
        break ;
       case (ButtonPress) :
       case (ButtonRelease) :
        printf("type:%d win:0x:%x\n",ev.type,ev.xbutton.window) ;
        break ;
      }
      if (ev.type == ButtonPress) {
        XGrabPointer(dpy,w1,False,ButtonPressMask|ButtonReleaseMask,
          GrabModeAsync,GrabModeSync,w1,None,CurrentTime) ;
        i = 1 ;
        while (1) {
          XMoveWindow(dpy,w1,i,0) ;
          XSync(dpy,0) ;
          i += 3 ;
          while (XPending(dpy)) {
            XNextEvent(dpy,&ev) ;
            switch (ev.type) {
             case (EnterNotify) :
             case (LeaveNotify) :
              printf("type:%d win:0x:%x\n",ev.type,ev.xcrossing.window) ;
              break ;
             case (ButtonPress) :
             case (ButtonRelease) :
              printf("type:%d win:0x:%x\n",ev.type,ev.xbutton.window) ;
              break ;
            }
            if (ev.type == ButtonRelease) {
              XUngrabPointer(dpy,CurrentTime) ;
              goto quit ;
            }
          }
        }
      }
    }
 quit : ;
  }
 }

rws@EXPO.LCS.MIT.EDU (Bob Scheifler) (11/17/88)

    My reading of the event mask passed to XGrabPointer says the Enter/Leave
    events should be discarded; is there something I am missing here?

Nope, 'tis a bug, plain and simple.  I know where the bug is, and
basically how to fix it, but it will probably be a little while
before you see a fix.

argv@island.uu.net (Dan Heller) (11/24/88)

In article <8811171510.AA13680@EXPO.LCS.MIT.EDU> rws@EXPO.LCS.MIT.EDU (Bob Scheifler) writes:
>
>    My reading of the event mask passed to XGrabPointer says the Enter/Leave
>    events should be discarded; is there something I am missing here?
>
>Nope, 'tis a bug, plain and simple.  I know where the bug is, and
>basically how to fix it, but it will probably be a little while
>before you see a fix.

But is it a bug?  I depend on this for at least one use.  I have widgets
which need to know whether or not you are inside of the widget's bounding
box.  If you leave it, it needs to dehighlight, XtRemoveTimeOut, etc...
For example, say I have a widget which is an "Open File" command-type
widget.  I am inside the widget, I click on it, and the callback routine
tries to open a file.  At this point, the code is part of the applciation,
_not_ in the user interface.  The application knows nothing of the user
interface layer, but if it fails to open the file, then it needs to 
know what to do next by caling a "generic" routine which asks, "create
the file?"  To do this without relinquishing control back to the top
level, the application calls a routine which creates a dialog box which is
a popup widget that has yes/no widgets and a small MainLoop()-type loop.
It grabs _all_ the events to prevent the user from doing anything else
in the application besides clicking on yes or no.  When the user goes to
click on yes or no, he has left the "Open File" widget which started all
this.  This widget needs to know that the user has left its boundaries
so it can reset itself.

How is this supposed to work if I can't get enter/exit window events?
Obviously, supressing such events is desired, but in cases as I've
described, you need those events.  Perhaps it would be a good idea to
tell the server which window is doing the grabbing and then allow that
window to have enter/exit events... ?

-- 
			--dan

     :-)                :-(               :-|
Have a nice day.   Have a bad day.    Have a day.

rws@EXPO.LCS.MIT.EDU (Bob Scheifler) (11/25/88)

  >    My reading of the event mask passed to XGrabPointer says the Enter/Leave
  >    events should be discarded; is there something I am missing here?

  But is it a bug?

Yes, it is a bug.

  <Long explanation.>

You've apparently missed something.  XGrabPointer has an event mask which
controls dispatch of subsequent pointer-related events to the grab window.
The example provided did an XGrabPointer with owner_events set to False,
meaning *only* this event mask should be obeyed.  Since the mask didn't
have Enter/Leave in it, the application should not have gotten those events.
If, however, you set owner_events to True in the grab, then normal event
dispatch for the client is attempted first, so "underlying" event masks can
apply.

dheller@cory.Berkeley.EDU (Dan Heller) (11/27/88)

In article <8811251525.AA18138@EXPO.LCS.MIT.EDU> rws@EXPO.LCS.MIT.EDU (Bob Scheifler) writes:

>  >    My reading of the event mask passed to XGrabPointer says the Enter/Leave
>  >    events should be discarded; is there something I am missing here?
>  But is it a bug?
>Yes, it is a bug.
>You've apparently missed something.  XGrabPointer has an event mask which

Yes, I missed the main point :-)  Actually, I replied to the wrong article
somehow.  The source of my confusion is the similarity between XGrabPointer
and the XGrabExclusive flag to XtPopup().  The fact that my problem with the
popup dialog box grabbing events and the widget which invoked it never gets
the Leave event contributed to my confusion.

Sorry about that.

However, if anyone has any suggestions about the scenario I'm talking about,
I'd like to hear from you.
Dan Heller	<island!argv@sun.com>