[comp.windows.x] help with XGrabPointer

diamant@HPFCLP.SDE.HP.COM (John Diamant) (12/23/88)

[ This is a resend of a message posted to comp.windows.x.  I have reason to
  believe our USENET feed was broken, and am thus mailing this directly to
  the xpert mailing list instead.  I apologize if any of you are seeing
  this twice ]

I am having some interaction problems with menus and pointer grabs and am
hoping someone could offer some guidance.

First, the application:  I'm trying to have one application do a pointer
grab under certain circumstances and allow the user to select a window in
any application.  The application wants the window id of the selected window.
In general, I know how to do this and in fact have working code.  However,
I am having interaction problems when I try to make this work with menus.
In particular, the menus are in the HP widget set.

The scenario is as follows.
   The user requests this function.
   The client issues an XGrabPointer
   The user brings the pointer over a menu and depresses button 1
   The independent application with the menu in it has a passive grab on
	button 1 (I'm not sure if it is being executed, but the documentation
	for XGrabButton would indicate not -- since an active grab exists at
	the time).
   My application gets the button press and uses XSendEvent to send it to
	the menu, which now posts the menu pane.
   The user drags the pointer down to a particular menu item and releases
   My application gets the release event and generates another XSendEvent
	to popdown the menu.

This all works fine; however there are some corner cases which do not.
First, if the user happens to select my application (the one that issued the
active grab), then my grab is lost when a menu is posted.  I assume this means
in this case the passive grab got executed (I don't know why) and it attempts
to do an XUngrabPointer followed by an XGrabPointer.  The XUngrabPointer works
only because it is the same application.  This leaves me SOL since I no longer
have any way of redirecting the events to this special mode.  This implies that
the passive grab was always being executed.

If the user presses a button in another application, the
XUngrabPointer and XGrabPointer will both fail and I get complete control of
the menus.  This presents a different problem.  The menus have cascading
submenus and because the active grab in the menu code failed, it is not capable
of behaving normally or posting the submenus.  I could resend all the events
to the application, but this is tricky because I have to recalculate the
window id for each, since the grab gives me back the wrong window ids
(it returns the grab window and child, which in my case is the root window
and the child of the root in which the event occurred).  It
also wouldn't solve the problem in the preceeding paragraph.

What I really want is something that would change the mouse sprite when this
mode is entered, but only grab release events.  Something like a passive
grab on a button release only, but in such a way as to block the passive
grab that already existed on button release for the menus and to not interfere
with any other event handling (button press or motion events).  An active grab
is closer in terms of mouse sprite handling, but it prevents the menu system
from behaving normally, also.

The grab in my application is done as follows:

  status = XGrabPointer(dpy, DefaultRootWindow(dpy), False,
                        ButtonPressMask  | ButtonReleaseMask,
                        GrabModeAsync, GrabModeAsync,
                        DefaultRootWindow(dpy),
                        qmark_cursor, CurrentTime);

and the menu code tries to do the following (inside the passive grab handler):

      if (event->xbutton.type == ButtonPress)
         XUngrabPointer (XtDisplay(menuMgr), CurrentTime);

      /* Set up our own pointer grab */
      XGrabPointer (XtDisplay(menuMgr), XtWindow(assocWidget), TRUE,
                    ButtonPressMask|ButtonReleaseMask|EnterWindowMask|
                    LeaveWindowMask, GrabModeAsync, GrabModeAsync, None,
                    NULL, CurrentTime);


Any advice or help on this would be appreciated.

Thanks,


John Diamant
Software Engineering Systems Division
Hewlett-Packard Co.		ARPA Internet: diamant@hpfclp.sde.hp.com
Fort Collins, CO		UUCP:  {hplabs,hpfcla}!hpfclp!diamant

rws@EXPO.LCS.MIT.EDU (Bob Scheifler) (12/23/88)

    First, if the user happens to select my application (the one that issued
    the active grab), then my grab is lost when a menu is posted.

If you mean the user selects a menu in your application, then given the
menu fragment you show below, it seems to follow that you will lose your grab.

    I assume this means
    in this case the passive grab got executed (I don't know why) and it
    attempts to do an XUngrabPointer followed by an XGrabPointer.

The passive grab should not get executed (if it does there's a server bug),
but the menu code probably can't tell a passive grab got activated, it just
assumes a button press caused a grab, and does an Ungrab, which releases the
grab you had, since it's being executed in your process.

    This leaves me SOL since I no longer
    have any way of redirecting the events to this special mode.

Yup.

    This implies that the passive grab was always being executed.

Nope, I don't think so.

    What I really want is something that would change the mouse sprite when
    this mode is entered, but only grab release events.

I can't think of any way for you to get this behavior.