[comp.windows.open-look] Double Clicks in XView

zoo@aps1.spa.umn.edu (david d [zoo] zuhn) (11/27/90)

Howdy.  I'm trying to write an application that needs to be able to
distinguish between single clicks and double clicks of a mouse button.
I am using XView 2, and this processing will be in the event procedure
of a canvas.

Does anyone have sample code for this?  Thanks.

david d [zoo] zuhn		Univ. of Minnesota Dept. of Astronomy
zoo@aps1.spa.umn.edu		      Automated Plate Scanner Project

kasso@aha.Eng.Sun.COM (Chris Kasso) (12/06/90)

In article <ZOO.90Nov26201641@grumpy.spa.umn.edu> zoo@aps1.spa.umn.edu writes:
>Howdy.  I'm trying to write an application that needs to be able to
>distinguish between single clicks and double clicks of a mouse button.
>I am using XView 2, and this processing will be in the event procedure
>of a canvas.
>
>Does anyone have sample code for this?  Thanks.
>
>david d [zoo] zuhn		Univ. of Minnesota Dept. of Astronomy
>zoo@aps1.spa.umn.edu		      Automated Plate Scanner Project

You probably want to use an interval timer to distinguish between double
and single clicks of the mouse.  Here's some code that should do
what you want:

#include <stdio.h>
#include <xview/xview.h>
#include <xview/canvas.h>
#include <xview/notify.h>

short	buttonState;

main(argc,argv)
    int		 argc;
    char	*argv[];
{
    void	 EventProc();	
    Xv_server	 server;
    Frame	 frame;
    Canvas	 canvas;

    server = xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL);

    frame = xv_create(NULL, FRAME,
			 XV_LABEL,	"XView Example",
			 XV_X,		200,
			 XV_Y, 		200,
			 XV_WIDTH,	200,
			 XV_HEIGHT,	200,
			 NULL);

    canvas = xv_create(frame, CANVAS,
			 XV_WIDTH,	WIN_EXTEND_TO_EDGE,
			 XV_HEIGHT,	WIN_EXTEND_TO_EDGE,
			 NULL);

    xv_set(canvas_paint_window(canvas), 
			WIN_EVENT_PROC, EventProc,
			WIN_CONSUME_EVENTS,
					WIN_MOUSE_BUTTONS,
					WIN_RESIZE,
					WIN_REPAINT,
					NULL,
			NULL);
    
    buttonState = 0; 

    window_fit(frame);
    xv_main_loop(frame);
}

void
EventProc(window, event)
    Xv_Window	 window;
    Event	*event;
{
    switch (event_action(event)) {
      case ACTION_SELECT:
	  if (event_is_down(event)) {
	      struct itimerval	timer;
	      void 		ButtonTimer();

	      if (!buttonState) {
		  timer.it_value.tv_sec = 0;
		  timer.it_value.tv_usec = 200000;
		  timer.it_interval.tv_sec = 0;
		  timer.it_interval.tv_usec = 0;
		  notify_set_itimer_func(window, ButtonTimer, ITIMER_REAL,
					 &timer, NULL);
		  buttonState = 1;
	      } else {
    		  /*
     		   * Second button press happened before the timeout, this must
		   * be a double click.
     		   */
    		  notify_set_itimer_func(window, NOTIFY_FUNC_NULL, ITIMER_REAL,
					 NULL, NULL);
                  fprintf (stderr, "Double-Click on ACTION_SELECT\n");
		  buttonState = 0;
	      }
	  }
          break;
      case ACTION_ADJUST:
	  if (event_is_down(event))
              fprintf (stderr, "ACTION_ADJUST (down)\n");
	  else
              fprintf (stderr, "ACTION_ADJUST (up)\n");
          break;
      case ACTION_MENU:
	  if (event_is_down(event))
              fprintf (stderr, "ACTION_MENU (down)\n");
	  else
              fprintf (stderr, "ACTION_MENU (up)\n");
          break;
      case WIN_REPAINT:
          fprintf (stderr, "WIN_REPAINT\n");
          break;
      case WIN_RESIZE:
          fprintf (stderr, "WIN_RESIZE\n");
          break;
    }
}

void
ButtonTimer(client, which)
    Notify_client	client;
    int			which;
{
    /*
     * Timeout happened before the second button press.  This is a 
     * single click.
     */
    notify_set_itimer_func(client, NOTIFY_FUNC_NULL, ITIMER_REAL, NULL, NULL);
    fprintf (stderr, "Single-Click on ACTION_SELECT\n");
    buttonState = 0;
}

--
Chris Kasso					Internet: kasso@Eng.Sun.COM
Windows and Graphics Software			uucp: {...}!sun!kasso
Sun Microsystems, Inc.

jcb@frisbee.Eng.Sun.COM (Jim Becker) (12/07/90)

In comp.windows.open-look Chris Kasso writes:

    In article <ZOO.90Nov26201641@grumpy.spa.umn.edu> zoo@aps1.spa.umn.edu writes:
    >Howdy.  I'm trying to write an application that needs to be able to
    >distinguish between single clicks and double clicks of a mouse button.
    >I am using XView 2, and this processing will be in the event procedure
    >of a canvas.
    >
    >Does anyone have sample code for this?  Thanks.
    >
    >david d [zoo] zuhn		Univ. of Minnesota Dept. of Astronomy
    >zoo@aps1.spa.umn.edu		      Automated Plate Scanner Project

    You probably want to use an interval timer to distinguish between double
    and single clicks of the mouse.  Here's some code that should do
    what you want:


An easier  method  is  simply  to  retain  the  `time'  field  in  the
XButtonEvent  associated  with  the last ACTION_SELECT event. Then the
`time' field associated with the next XButtonEvent  in  the  following
ACTION_SELECT  can  be  tested  in  terms  of  the double click timing
threshhold.

Here's some snippets of code:

/*
 * 	this does the check for multiclick and returns boolean
 */
static	int
txt_is_multiclick( textsw, tline, tindex )
Textob		*textsw;
int		tline, tindex;
{
	XButtonEvent	*bevent		= &textsw->xevent->xbutton;
	Time		curtime		= bevent->time;
	short		is_multiclick	= FALSE;

	if( tline  == textsw->last_tline && 
	    tindex == textsw->last_tindex ) 
		if( (curtime - textsw->last_time) <= textsw->click_timeout )
			is_multiclick	= TRUE;

	return is_multiclick;
}

static	int
text_notify_dispatch( textsw_pub, event, arg, type)
Textsw		textsw_pub;
Event		*event;
Notify_arg	arg;
Notify_event_type type;
{
	...
	XEvent			*aevent		= event->ie_xevent;
	XButtonEvent		*bevent		= aevent->xbutton;

	...

	textsw->click_timeout	= HARDCODED_MILLISECONDS;	/* init once */
	textsw->xevent		= aevent;


	...
	if( txt_is_multiclick( textsw, line, index ) ) {

		/* inside the threshhold */
	}
	else {
		/* outside the threshold */
	}		
	

	textsw->last_time	= bevent->time;
}



-Jim

--
--    
	 Jim Becker / jcb%frisbee@sun.com  / Sun Microsystems