[comp.windows.x] Motion hints and pointer grabbing

josh@mit-vax.LCS.MIT.EDU (Joshua Marantz) (12/30/88)

I sent this to xbugs and got no reply, and I'm curious to see if anyone else
has had a problem with this.  The bug report follows.

-Joshua Marantz
Viewlogic Systems, Inc.
----------------
			  X Window System Bug Report
			    xbugs@expo.lcs.mit.edu

VERSION:
    R3

CLIENT MACHINE and OPERATING SYSTEM:
    Sun 3/60 running SunOS 3.4.

DISPLAY:
    Sun 3/60, SunOS 3.4, Sun CG4.

WINDOW MANAGER:
    uwm

AREA:
    server

SYNOPSIS:
    MotionNotifyHints do not work when the cursor is grabbed in a ConfineTo
    window.

DESCRIPTION:
 
    R2 servers (running on Sun 3/60/SunOS 3.4/CG4 and uVAXII/VMS/GPX) do
    this correctly.  The code creates an InputOnly limiting window, and
    does an XGrabPointer with the ConfineTo window set to the limiting
    window.  The event mask (MotionNotify | PointerMotionMask) is
    selected.  The server responds to the first mouse movement with a
    MotionNotify event.  XQueryPointer routine is then called to reset
    the hint mechanism.  In R3, the server will not send another
    MotionNotify event until a button is pressed or the mouse leaves
    the window.  In R2, the server will send a new MotionNotify event
    each time the mouse is moved after an intervening XQueryPointer,
    as expected.

REPEAT BY:
    I have modified xev.c to demonstrate the problem.  The context diffs
    follow, but all I did was to call XQueryEvent each time a MotionNotify
    event was received, and to toggle grabbing (confining) the pointer each
    time the mouse button is pressed.

*** /usr/local/X11/clients/xev/xev.c	Sun Oct  9 15:43:32 1988
--- xev.c	Mon Dec 12 19:44:41 1988
***************
*** 95,108 ****
  {
      char *displayname = NULL;
      char *geom = NULL;
!     int i;
      XSizeHints hints;
      int borderwidth = 2;
!     Window w, subw;
!     XSetWindowAttributes attr;
!     unsigned long mask = 0L;
!     int done;
! 
      ProgramName = argv[0];
      for (i = 1; i < argc; i++) {
  	char *arg = argv[i];
--- 95,108 ----
  {
      char *displayname = NULL;
      char *geom = NULL;
!     int i, root_x, root_y, query_x, query_y;
      XSizeHints hints;
      int borderwidth = 2;
!     Window w, subw, query_root, query_child, limit_window;
!     XSetWindowAttributes attr, limit_attr;
!     unsigned long mask = 0L, query_mask;
!     int done, limited = 0;
!     
      ProgramName = argv[0];
      for (i = 1; i < argc; i++) {
  	char *arg = argv[i];
***************
*** 205,210 ****
--- 205,238 ----
  	    do_KeyRelease (&event);
  	    break;
  	  case ButtonPress:
+ 
+             /* If the cursor is confined to the window, let it rome free! */
+             if (limited) {
+                 XUngrabPointer (dpy, CurrentTime);
+                 XDestroyWindow (dpy, limit_window);
+                 limited = 0;
+             }
+ 
+             /* If the cursor was free, confine it to the window */
+             else {
+                 limited = 1;
+                 limit_window = XCreateWindow (dpy, w,
+                                               0, 0, hints.width, hints.height,
+                                               0, 0,
+                                               InputOnly,
+                                               (Visual *) CopyFromParent,
+                                               0, &limit_attr);
+ 
+                 XMapWindow (dpy, limit_window);
+                 XGrabPointer (dpy, w,
+                               True,
+                               ButtonPressMask | PointerMotionMask,
+                               GrabModeAsync,	    /* pointer mode */
+                               GrabModeAsync,	    /* kbd mode */
+                               limit_window,         /* confine-to window */
+                               None,
+                               CurrentTime);
+             }
  	    prologue (&event, "ButtonPress");
  	    do_ButtonPress (&event);
  	    break;
***************
*** 214,219 ****
--- 242,249 ----
  	    break;
  	  case MotionNotify:
  	    prologue (&event, "MotionNotify");
+             XQueryPointer (dpy, w, &query_root, &query_child,
+                            &root_x, &root_y, &query_x, &query_y, &query_mask);
  	    do_MotionNotify (&event);
  	    break;
  	  case EnterNotify:

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

Yes, there is a server bug here, having to do with your switching
from having Hint set in the normal mask to not having Hint set in
the grab mask.  If both were equal it would work OK.  Since you
want hints, you should continue to ask for them in the grab, and
all will be well:

                XGrabPointer (dpy, w,
                              True,
!                             ButtonPressMask | PointerMotionMask
!				| PointerMotionHintMask,
                              GrabModeAsync,	    /* pointer mode */
                              GrabModeAsync,	    /* kbd mode */
                              limit_window,         /* confine-to window */
                              None,
                              CurrentTime);