From: patrick%ess2.span@FEDEX.MSFC.NASA.GOV (Patrick E. Meyer (205)544-2265)
Newsgroups: comp.windows.x.motif
Subject: Help!: Double Click and Rubberbanding
Date: 19 Aug 92 15:19:06 GMT

I have two of what I believe should be simple questions.

1) The easiest first:  The Selection Box widget has a XmNdefaultCallback which
   is activated via double clicking MB1 on your selection. I would like to add a
   double click callback to a Drawing Area widget.  What are my options:
      a. Do I add a translation -, if so what <Btn1Dn>,<Btn1up>,<Btn1Dn>,
         <Btn1Up>?
      b. Do I create a callback that checks the time between clicks using
         the XmNinputCallback -
         I would like to use the mwm's defined double click rate.

2) Using the Rubberbanding technique in Young p. 259, I am making a utility
   that allow you to create cross hairs the span the four sides of a given
   window. In other words, drawing lines from 0 to width through mouse y and
   0 to height through mouse x.

   My problem is recieving mouse grabbed events when crossing children of the
   selected window.

   Example: I have a form with drawing area's, paned windows, and text lists
   for children.  When the grabbed sprite leaves the text list and enters
   the drawing area, I no longer recieve motion notifies.

   I have tried XSelectInput on the parent form to no avail.  Does my crosshair
   routine have to know its children and request their motion notifies when
   they don't allow propagation (sp?). Maybe this is not even the problem.

Any help is greatly appreciated.

Patrick Meyer
Please email to ... patrick%ess2.span@Fedex.Msfc.Nasa.Gov

/*******************************************************
*
* Library routine to create a cross hair grab for window 
*/
#include <X11/Xlib.h>
#include <X11/StringDefs.h>
#include <X11/Intrinsic.h> 
#include <X11/cursorfont.h>
#include <Xm/Xm.h>
#include <Xm/ScrollBar.h>

typedef struct {
    Boolean vertical;
    Boolean horizontal;
    Position vert_x;
    Position vert_y;
    Position hori_x;
    Position hori_y;
    GC  gc;
} cross_hair_data;

void XessStartCrosshairs();
void XessEndCrosshairs();
void XessTrackCrosshairs();


void XessCreateCrosshairs(Widget w, Boolean vertical, Boolean horizontal) {

  static cross_hair_data data;
  Arg       args[2];
  unsigned long gc_valuemask;
  XGCValues values;

  /* Set which lines will be drawn */
  data.vertical = vertical;
  data.horizontal = horizontal;

  /* Add call backs to draw cross hairs */
  XtAddEventHandler(w, ButtonPressMask,   FALSE, XessStartCrosshairs, &data);
  XtAddEventHandler(w, Button3MotionMask, FALSE, XessTrackCrosshairs, &data);
  XtAddEventHandler(w, ButtonReleaseMask, FALSE, XessEndCrosshairs,   &data);

  XSelectInput(XtDisplay(w), XRootWindowOfScreen(XtScreen(w)),
                      Button3MotionMask);

  /* Force mouse to stay in users window */
  XGrabButton(XtDisplay(w), Button3, ShiftMask, XtWindow(w), TRUE, 
              ButtonPressMask | Button3MotionMask | ButtonReleaseMask,
              GrabModeAsync, GrabModeAsync,
              XtWindow(w), 
              XCreateFontCursor(XtDisplay(w), XC_crosshair));

  XtSetArg(args[0], XtNforeground, &values.foreground);
  XtSetArg(args[1], XtNbackground, &values.background);
  XtGetValues(w, args,2);


  values.foreground = values.foreground ^ values.background;
  values.line_style = LineSolid;
  values.function   = GXxor;
  values.subwindow_mode = IncludeInferiors;
  data.gc = XtGetGC(w, GCForeground | GCBackground | GCSubwindowMode |
               GCFunction | GCLineStyle, &values);
}

void XessStartCrosshairs(Widget w, cross_hair_data *data, XEvent *event) {
  Arg args[2];

  if (event->xbutton.button == Button3) {
     data->vert_x = event->xbutton.x;
     data->hori_y = event->xbutton.y;

     XtSetArg(args[0], XmNheight, &data->vert_y);
     XtSetArg(args[1], XmNwidth, &data->hori_x);
     XtGetValues(w, args, 2);

     if(data->vertical)
        XDrawLine(XtDisplay(w), XtWindow(w), data->gc,
                  data->vert_x, 0, 
                  data->vert_x, data->vert_y);
     if(data->horizontal)
        XDrawLine(XtDisplay(w), XtWindow(w), data->gc,
                  0, data->hori_y,
                  data->hori_x, data->hori_y);
  }
}

void XessTrackCrosshairs(Widget w, cross_hair_data *data, XEvent *event) {
  Arg args[2];


     /*
      * Draw once to clear the previous line.
      */
     if(data->vertical)
        XDrawLine(XtDisplay(w), XtWindow(w), data->gc,
                  data->vert_x, 0, 
                  data->vert_x, data->vert_y);
     if(data->horizontal)
        XDrawLine(XtDisplay(w), XtWindow(w), data->gc,
                  0, data->hori_y,
                  data->hori_x, data->hori_y);
     /*
      * Update the endpoints.
      */
     XtSetArg(args[0], XmNheight, &data->vert_y);
     XtSetArg(args[1], XmNwidth, &data->hori_x);
     XtGetValues(w, args, 2);

     data->vert_x = event->xbutton.x;
     data->hori_y = event->xbutton.y;
     /*
      * Draw the new line.
      */
     if(data->vertical)
        XDrawLine(XtDisplay(w), XtWindow(w), data->gc,
                  data->vert_x, 0, 
                  data->vert_x, data->vert_y);
     if(data->horizontal)
        XDrawLine(XtDisplay(w), XtWindow(w), data->gc,
                  0, data->hori_y,
                  data->hori_x, data->hori_y);
}

void XessEndCrosshairs(Widget w, cross_hair_data *data, XEvent *event) {
  Arg args[2];

 /*
  * Clear the current line and update the endpoint info.
  */
  if (event->xbutton.button == Button3) {
     if(data->vertical)
        XDrawLine(XtDisplay(w), XtWindow(w), data->gc,
                  data->vert_x, 0, 
                  data->vert_x, data->vert_y);
     if(data->horizontal)
        XDrawLine(XtDisplay(w), XtWindow(w), data->gc,
                  0, data->hori_y,
                  data->hori_x, data->hori_y);
  }
}

Thanks again...
Please email to ... patrick%ess2.span@Fedex.Msfc.Nasa.Gov