[comp.windows.x] rubberbanding with Xlib

satyen@xwis.Sun.COM (satyendra Dhingra) (08/29/89)

Does anyone have a good way of doing rubberbanding with Xlib, by good
I mean where rubberband box keeps up with the cursor. The normal way of 
doing rubberbanding 

erasebox(flush buffer)-redrawbox(flush buffer)-erasebox.. 

requires a roundtrip for each request (batching requests makes it even 
worse) and the cursor is always ahead of the box being drawn. Has anyone
worked a solution where rubberbanding box always tracks thr cursor very
closely.

thanks,
satyendra
satyen@sun.com

erik@srava.sra.JUNET (Erik M. van der Poel) (08/29/89)

	Does anyone have a good way of doing rubberbanding with Xlib, by
	good I mean where rubberband box keeps up with the cursor.


I have found that you can keep up with the cursor quite well if you
first erase the box, then call XTrackMouse (supplied below), and finally
draw the box again. XTrackMouse first calls XSync to make sure the
server has processed all of your requests and has sent all events. Then
all mouse events (except for the last one) are skipped to obtain the
most up-to-date one.


XTrackMouse(event)
	register XMotionEvent	*event;
{
	register Display	*display;
	register Window		window;

	if (event->type != MotionNotify) {
		return;
	}

	display = event->display;
	window = event->window;

	XSync(display, 0);

	while (XCheckTypedWindowEvent(display, window, MotionNotify, event)) {
	}
}


Note that XTrackMouse only works for rubberbanding in a window (as
opposed to rubberbanding all over the display like window managers do).
However, this can be changed easily by using XCheckTypedEvent instead of
XCheckTypedWindowEvent.


As far as I know, Xlib does not contain a convenience function like this,
although it might be nice if it did (nudge nudge :-).

-- 
Erik M. van der Poel                  erik@sra.junet             (Japan)
SRA, 1-1-1 Hirakawa-cho, Chiyoda-ku   erik%sra.junet@uunet.uu.net  (USA)
Tokyo 102 Japan. TEL +81-3-234-2692   erik%sra.junet@mcvax.uucp (Europe)

tbecker@incas.UUCP (3295) (08/29/89)

satyen@xwis.Sun.COM (satyendra Dhingra) writes:

>Does anyone have a good way of doing rubberbanding with Xlib, by good
>I mean where rubberband box keeps up with the cursor. The normal way of 
>doing rubberbanding 

>erasebox(flush buffer)-redrawbox(flush buffer)-erasebox.. 

>requires a roundtrip for each request (batching requests makes it even 
>worse) and the cursor is always ahead of the box being drawn. Has anyone
>worked a solution where rubberbanding box always tracks thr cursor very
>closely.

I have written several applications with Xlib, using X11R3 on a Sun3/60,
each application used rubberbanding as you described it. However, in none
of them, the cursor was much ahead of the bounding box, though I have used
exactly the same mecahnism as you described above.

Maybe this has to do with the way you determine when to move the box.
Moving the pointer might generate a great number of PointerMotion events.
If you use each of them to update your rubberband, too much action is
necessary to follow the pointer.

Instead, set the PointerMotionHintMask and consider only PointerMotionEvents
with the is_hint member set to NotifyHint. Then use XQueryPointer to get the
current pointer location and update your rubberband.

This way you make sure the bounding box follows the pointer tightly.

>thanks,
>satyendra
>satyen@sun.com

Hope this helps ...

Thomas Becker

-------------------------------------------------------------------------------
Thomas Becker-----------University of Kaiserslautern---------------West Germany
---------------P.O. 3049------------------------D-6750 Kaiserslautern----------
---------------------e-mail: incas!tbecker@uklirb.uucp-------------------------
--------------------------phone: +49 631 205 3295------------------------------
-------------------------------------------------------------------------------

laffra@HLERUL5I.BITNET (08/29/89)

In response to:

     Does anyone have a good way of doing rubberbanding with Xlib, by good
     I mean where rubberband box keeps up with the cursor. The normal way of
     doing rubberbanding

     erasebox(flush buffer)-redrawbox(flush buffer)-erasebox..

     requires a roundtrip for each request (batching requests makes it even
     worse) and the cursor is always ahead of the box being drawn. Has anyone
     worked a solution where rubberbanding box always tracks thr cursor very
     closely.

There is a way:
You have to make sure that you do not redraw your box with every motion event.
What I generally do (and it works very nicely) is the following:

   XNextEvent(&event);
   switch( type_of(&event) ) {
   case MotionNotify :
             if (event_queue_is_empty_now()) {
                        erase_box(...); draw(box(...);
             else
                        ignore();
   }

The 'event_queue_is_empty_now()' function calls XPending() (XLib function).
In this way you only redraw the box when the mouse pointer is not moving
anymore. This reduce the delay of redrawing and the box will follow the
cursor better.

If your picture is very complicated you might want to test the queue for
new motion event even while you are drawing the picture. The you do not
finish the picture but erase the sofar drawn parts.

Chris Laffra
laffra@HLERUL5I.BITNET
h

marbru@auto-trol.UUCP (Martin Brunecky) (08/31/89)

> Implement rubberbanding ....

I'v seen some advices so far. What I do is as follows (and it DID
generate good results on VS2000 running FT of DECWINDOWS long time
ago. However, you will NEVER track the pointer EXACTLY, there is
always a delay due to the roundtrip. We solve this by using NONE
cursor (which is unfortunatelly missing in the standard cursors, you have
to create one by hand using XCreatePixmapCursor... with a "blank"
pixmap 1x1 pixel).

1) we set pointer motions hint in the window event mask so that we
   don't get swamped with hundreds of motion events. Or in Xt,
   specify compress_motion in core part to TRUE.

2) when we get a motion event, we call XQueryPointer. It costs a round-trip,
   but we get the true LAST pointer position.

3) we compare position to the previous one = no move, skip it

4) we try to do the undraw-draw in one protocol request (using Xor)
   if possible - i.e. using XDrawSegments. Till about 50 (?) segments
   you get good results. Above that, blt from pixmap may be better.


###############################################################################
Martin Brunecky, Auto-trol Technology Corporation,
12500 North Washington Street, Denver, CO-80241-2404
(303) 252-2499                                        ncar!ico!auto-trol!marbru
###############################################################################