[comp.sys.amiga.tech] Double click detection?

cunniff@hpfcdc.HP.COM (Ross Cunniff) (01/24/89)

I've been fiddling around with detecting double-clicking of the select
button in an application I'm writing.  The method I've come up with follows
(it has been typed in from memory; don't flame me for minor typos...).
It works OK, except that a single click without excessive mouse motion
following takes a noticble amount of time to get processed.  In addition,
the double click loop is hard on the multitasking O/S.  (I just realized
that I could use Intuition timer events; any caveats?)  Does anybody
have a better way of doing this?

A second, only slightly releated question is:  How does one safely close
windows with shared IDCMP ports?  The AutoDocs give a passing mention
to a routine named CloseWindowSafely(), and claim that it is documented
in one of the early issues of AmigaMail.  I don't seem to have that issue.


At any rate, here is the double click loop:

	Wait( 1 << Win->UserPort->mp_SigBit );

	while( Msg = GetMsg( Win->UserPort ) ) {
	    /* Copy Code, Class, etc. fields from Msg; deleted for space */
	    ReplyMsg( Msg );

	    if( (Class == MOUSEBUTTONS) && (Code == SELECTDOWN) ) {
		/* Mouse click; Save current parameters */
		OldS = CurrS;	OldU = CurrU;
		OldX = MouseX;	OldY = MouseY;
		/* Etc... */

		Done = NOT_DONE;
		while( Done == NOT_DONE ) {
		    Msg = GetMsg( Win->UserPort );
		    if( Msg ) {
			/* Copy fields from Msg; deleted for space */
			ReplyMsg( Msg );

			if( (Class == MOUSEBUTTONS) && (Code == SELECTDOWN) ) {
			    if( DoubleClick( OldS, OldU, CurrS, CurrU ) ) {
				/* Aha! a double click */
				Done = DOUBLE_CLICK;
			    }
			    else {
				/* Oops!  Two discrete mouse clicks */
				Done = TWO_EVENTS;
			    }
			}
			else if( Class == MOUSEMOVE ) {
			    if(		(ABS( OldX - MouseX ) > MAX_XDLTA) ||
					(ABS( OldY - MouseY ) > MAX_YDLTA) )
			    {
				/* We moved the mouse too far */
				Done = TWO_EVENTS;
			    }
			}
			else {
			    /* Another event (gadgetclick? RAWKEY?) came in */
			    Done = TWO_EVENTS;
			}
		    }
		    else {
			/* No event pending; see if we've timed out */
			CurrentTime( &CurrS, &CurrU );
			if( DoubleClick( OldS, OldU, CurrS, CurrU ) ) {
			    /* We timed out; go away */
			    Done = TIMEOUT;
			}
		    }
		}	/* end while( Done == NOT_DONE ) */

		/* OK, something happened;  process it */
		switch( Done ) {
		    case DOUBLE_CLICK :
			/* Do double click stuff */
			break;
		    case TWO_EVENTS :
			/* Do stuff for first event */
			/* Do stuff for second event */
			break;
		    case TIMEOUT :
			/* Do stuff for first event */
			break;
		}
	    }	/* end if( select click ) */
	    else {
		/* Do stuff for other events */
	    }
	}	/* end while( Msg ) */



				Ross Cunniff
				...{ucbvax,hplabs}!hpfcrt!cunniff
				cunniff%hpfcrt@hplabs.HP.COM

shimoda@infohh.rmi.de (Markus Schmidt) (01/27/89)

Hi!

Four doubleclicks I use this logic:

while (1) {

      imsg= GetMsg ( ...
      if (imsg->Class=  /* endevent */) 
         break;


      if (imsg->Class==SELECTDOWN)
      {
         static Seconds= 0, 
               Micros= 0;

         if ((Seconds!=0 || Micros!=0) &&
            DoubleClick(Seconds,Micros,
                     imsg->Seconds, imsg->Micros)) {

                  /* Your Stuff ... */

                  Seconds= Micros= 0;
         }
         else {
            Seconds= imsg->Seconds;   Micros= imsg->Micros;
         }
      }

}

Please notice that ReplyMsg is not handled. I just hacked that down
online. 

.-----------------------------------------------------------------.
|  shimoda@rmi.de       `---'   The last remaining adventure      |
|  shimoda@gopnbg.UUCP  |O o|   since there are no more tigers:   |
|                       ==Y==   Doublebuffered async. I/O       _ |
|----------------------- `U' ------------------------------  _ // |
|  Good terminalpackages     begin with A: AmigaCall, A-Ta.. \//  |
`-----------------------------------------------------------------'

atheybey@PTT.LCS.MIT.EDU (01/30/89)

shimoda@infohh.rmi.de (Markus Schmidt) writes:
%Four doubleclicks I use this logic:
%
%while (1) {
%
%      imsg= GetMsg ( ...
%      if (imsg->Class=  /* endevent */) 
%	 break;
%
%
%      if (imsg->Class==SELECTDOWN)
%      {
%	 static Seconds= 0, 
%	       Micros= 0;
%
%	 if ((Seconds!=0 || Micros!=0) &&
%	    DoubleClick(Seconds,Micros,
%		     imsg->Seconds, imsg->Micros)) {
%
%		  /* Your Stuff ... */
%
%		  Seconds= Micros= 0;
%	 }
%	 else {
%	    Seconds= imsg->Seconds;   Micros= imsg->Micros;
%	 }
%      }
%
%}
%
%Please notice that ReplyMsg is not handled. I just hacked that down
%online. 
%
%.-----------------------------------------------------------------.
%|  shimoda@rmi.de       `---'   The last remaining adventure      |
%|  shimoda@gopnbg.UUCP  |O o|   since there are no more tigers:   |

Please correct me if I am wrong, but doesn't this code fragment
contain two Bad Things?  No Guru has yet responded, so I thought I
would take a shot at sticking my foot in my mouth.

It busy-waits.  There is no call to Wait(), or WaitPort() before the
GetMsg().  Even  if you are busy-waiting only while looking for double
clicks, you shouldn't.

GetMsg() will return NULL if no message has yet arrived.  With the
various 'if (imsg-> ... )' tests, you are then indirecting through
address 0, which while not necessarily fatal, is sloppy and will quite
likely break on any system with memory protection (unless it's a VAX :-).
Even if you do call Wait(), you should not depend on GetMsg()
returning something non-NULL.

---------------------------------------------------------------------------
Andrew Heybey, atheybey@ptt.lcs.mit.edu     Room 509, 545 Technology Square
Advanced Network Architecture Group   	 	       Cambridge, MA  02139
MIT Laboratory for Computer Science    			     (617) 253-6011
---------------------------------------------------------------------------

shimoda@infohh.rmi.de (Markus Schmidt) (02/04/89)

)%
)%|  shimoda@rmi.de       `---'   The last remaining adventure      |
)%|  shimoda@gopnbg.UUCP  |O o|   since there are no more tigers:   |
)
)Please correct me if I am wrong, but doesn't this code fragment
)contain two Bad Things?  No Guru has yet responded, so I thought I
)would take a shot at sticking my foot in my mouth.
)
)It busy-waits.  There is no call to Wait(), or WaitPort() before the
)GetMsg().  Even  if you are busy-waiting only while looking for double
)clicks, you shouldn't.
)
)GetMsg() will return NULL if no message has yet arrived.  With the
)various 'if (imsg-> ... )' tests, you are then indirecting through
)address 0, which while not necessarily fatal, is sloppy and will quite
)likely break on any system with memory protection (unless it's a VAX :-).
)Even if you do call Wait(), you should not depend on GetMsg()
)returning something non-NULL.
)
)Andrew Heybey, atheybey@ptt.lcs.mit.edu     Room 509, 545 Technology Square
.-----------------------------------------------------------------.
Of course you are right both times. As I said, it was hacked down
online so forgive me if this caused any trouble. Next time I will
be more reliable.
I just left out anything except the DoubleClick-stuff.

Thank you anyway.

|  shimoda@rmi.de       `---'   The last remaining adventure      |
|  shimoda@gopnbg.UUCP  |O o|   since there are no more tigers:   |
|                       ==Y==   Doublebuffered async. I/O       _ |
|----------------------- `U' ------------------------------  _ // |
|  Good terminalpackages     begin with A: AmigaCall, A-Ta.. \//  |
`-----------------------------------------------------------------'