'From Squeak3.1alpha of 5 February 2001 [latest update: #3575] on 12 February 2001 at 7:42:22 pm'! "Change Set: FasterClicks Date: 12 February 2001 Author: Marcel Weiher, Bob Arning Acts on clicks immediately instead of waiting for the double-click timeout to expire. Makes the system generally feel much more responsive and fixes an interaction with threading on the MacOS-X VM. A side effect is that receivers of doubleClick events will now get a singleClick first, so they have to deal with this situation. Ad-hoc testing with the TrashcanMorph (one of the very few double-clickable morphs) showed no ill effects. Slight changes by Bob Arning so FreeCell works a little better with the new regime "! !Morph methodsFor: 'event handling' stamp: 'RAA 2/12/2001 15:26'! firstClickTimedOut: evt "Useful for double-click candidates who want to know whether or not the click is a single or double. In this case, ignore the #click: and wait for either this or #doubleClick:" ! ! !MouseClickState methodsFor: 'initialize' stamp: 'RAA 2/12/2001 18:55'! handleEvent: evt from: aHand "Process the given mouse event to detect a click, double-click, or drag. Return true if the event should be processed by the sender, false if it shouldn't. NOTE: This method heavily relies on getting *all* mouse button events." | localEvt timedOut isDrag | timedOut _ (evt timeStamp - firstClickTime) > dblClickTime. localEvt _ evt transformedBy: (clickClient transformedFrom: aHand owner). isDrag _ (localEvt cursorPoint - firstClickDown cursorPoint) r > dragThreshold. clickState == #firstClickDown ifTrue: [ "Careful here - if we had a slow cycle we may have a timedOut mouseUp event" (timedOut and:[localEvt isMouseUp not]) ifTrue:[ "timeout before #mouseUp -> keep waiting for drag if requested" clickState _ #firstClickTimedOut. dragSelector ifNil:[ clickClient firstClickTimedOut: firstClickDown. "***" aHand resetClickState. clickSelector ifNotNil:[clickClient perform: clickSelector with: firstClickDown]]. ^true]. localEvt isMouseUp ifTrue:[ (timedOut or:[dblClickSelector isNil]) ifTrue:[ clickSelector ifNotNil:[clickClient perform: clickSelector with: firstClickDown]. aHand resetClickState. ^true]. "Otherwise transfer to #firstClickUp" firstClickUp _ evt copy. clickState _ #firstClickUp. "If timedOut or the client's not interested in dbl clicks get outta here" clickSelector ifNotNil:[clickClient perform: clickSelector with: firstClickUp]. aHand handleEvent: firstClickUp. ^false]. isDrag ifTrue:["drag start" clickClient firstClickTimedOut: firstClickDown. "***" aHand resetClickState. dragSelector == nil "If no drag selector send #click instead" ifTrue:[clickSelector ifNotNil:[clickClient perform: clickSelector with: firstClickDown]] ifFalse:[clickClient perform: dragSelector with: localEvt]. ^true]. ^false]. clickState == #firstClickTimedOut ifTrue:[ localEvt isMouseUp ifTrue:["neither drag nor double click" clickClient firstClickTimedOut: firstClickDown. "***" aHand resetClickState. clickSelector ifNotNil:[clickClient perform: clickSelector with: firstClickDown]. ^true]. isDrag ifTrue:["drag start" clickClient firstClickTimedOut: firstClickDown. "***" aHand resetClickState. dragSelector ifNotNil:[clickClient perform: dragSelector with: localEvt]. ^true]. ^false]. clickState = #firstClickUp ifTrue:[ (timedOut) ifTrue:[ "timed out after mouseUp - send #click: and mouseUp" clickClient firstClickTimedOut: firstClickDown. "***" aHand resetClickState. ^true]. localEvt isMouseDown ifTrue:["double click" aHand resetClickState. dblClickSelector ifNotNil:[clickClient perform: dblClickSelector with: firstClickDown]. ^false]]. ^true! ! !PlayingCardMorph methodsFor: 'events' stamp: 'RAA 2/12/2001 19:22'! click: evt "since we really want to know about double-clicks before making our move, ignore this and wait until #firstClickTimedOut: arrives"! ! !PlayingCardMorph methodsFor: 'events' stamp: 'RAA 2/12/2001 19:16'! firstClickTimedOut: evt | root popUp | root _ owner rootForGrabOf: self. root == nil ifTrue: ["Display hidden card in front" popUp _ self copy. self board owner owner addMorphFront: popUp. self world displayWorld. (Delay forMilliseconds: 750) wait. popUp delete] ifFalse: [evt hand grabMorph: root]! !