Dear Joshua Gargus
Hi. I have been trying to learn squeak. Recently I have been reading the code in MouseClickState event handling. The original version of this has your initials on it and was written/added in Sept 2001. The routine that calls it for action is HandMorph>>handleEvent; and that was written six months earlier.
MouseClickState>>handleEvent:from: is nonrecursive except at one point where it is processing the first mouseup. There it calls handleEvent: with a copy of the mouseup event after firing the click selector.
I've check with a diagnostic and this is definitely a recursive call. The same mouseup comes thru a second time (the click state has changed. And the recursive event glides thru without causing anymore changes.) The recursive call releases it back to handleEvent with the true flag. It is processed to completion.
When handleEvent exits the remaining unrecursed event is released back to handleEvent with the original false flag. Furthur processing is not done and handleEvent releases back to its original caller.
I do not believe this is what was actually intended. But I do not understand what the actual intention was either.
Changing the code so that instead of
self click. aHand handleEvent: copiedEvt . ^false
we have just:
self click. ^true
would seem to do the trick as far as the post processing results are concerned.
So if there is a difference then it would have to be in what happens before clickstate is checked a second time.
From the rest of the method, it would be the most
logical way to have coded it. So obvious that the fact that it was not is curious.
Was there something click was supposed to change such as mouse focus that would make the recurssion useful?
If click does not change mouse focus then you have the same old listeners to mouse up being fired twice. Which would explain a few things.
So I am trying to track down the history and the folklore on ClickState to see what I'm missing.
Any help would be appreciated.
Here is the diagnostics in text:
'From Squeak3.8alpha of ''17 July 2004'' [latest update: #5976] on 1 August 2004 at 12:18:18 pm'! "Change Set: ClickStateDiagnostics-wiz Date: 1 August 2004 Author: Jerome Peace (wiz) wiz 8/1/2004 12:17
ClickStateDiagnostic tools to explore what Clickstate is doing. This changeset limits itself to the looking routines.
I've set up a subclass of MouseClickState to and a history iVar and a PastHistory cVar. The former stores all the events ClickState is called with; the latter the past ClickStates instances. MouseClickState did not have to be patched. HandMorph is patched to attach the hooks. Also HandMorph class now has accessors to EventStats.
This is very useful for seeing just what actually passed thru clickstate. It does not show the actions of clickstate though they can mostly be arrived at by inference.
I use the method name #preserve to have an instance save itself in its Past History. The method has been added to Object as a nop to avoid objections from nil and other non approriate classes.
The subclass and preserve technique is a pattern that could be used to observe other instances.
Third attempt. wiz 7/29/2004 10:29 Added a size limit to PastHistory. No sense causing out of space crashes.
Second attempt at ClickTestTools.
This is a first pass at tools to examine in MouseClickState.
I made a nosy subclass of MouseClickState which copys the events as they are sent to a history collection.
The states objects themselves are preserved in a classVar ordered collection with the idea of them being explored and reset e.g. (WizClickStage resetPastHistory explore) .
HandMorph class was modified to give access to the eventStats that handleEvent stores. (HandMorph eventStatsReset explore).
HandMorph was modified to use and preserve my clickstate subclass. "!
MouseClickState subclass: #WizClickState instanceVariableNames: 'history' classVariableNames: 'PastHistory' poolDictionaries: '' category: 'Morphic-Kernel'!
!WizClickState commentStamp: '<historical>' prior: 0! I am a nosy click state subclass. I collect a history of events passed to my super.
"WizClickState resetPastHistory explore."
Structure: history OrderedCollection or nil -- collects event sent to clickstate PastHistory OrderedCollection or nil -- collects clickstates as they are reset.
Use me as a microscope to check what MouseClickState will do.!
!Object methodsFor: '*ClickTest' stamp: 'wiz 7/29/2004 02:22'! preserve "Subclass WizClickState redifines. Just ignore here." ^ self! !
!HandMorph methodsFor: 'double click support' stamp: 'wiz 7/29/2004 01:15'! resetClickState "Reset the double-click detection state to normal (i.e., not waiting for a double-click). " mouseClickState preserve. mouseClickState := nil! !
!HandMorph methodsFor: 'double click support' stamp: 'wiz 7/29/2004 00:58'! waitForClicksOrDrag: aMorph event: evt selectors: clickAndDragSelectors threshold: threshold "Wait for mouse button and movement events, informing aMorph about events interesting to it via callbacks. This message is typically sent to the Hand by aMorph when it first receives a mouse-down event. The callback methods, named in clickAndDragSelectors and passed a copy of evt, are: 1 (click) sent when the mouse button goes up within doubleClickTime. 2 (doubleClick) sent when the mouse goes up, down, and up again all within DoubleClickTime. 3 (doubleClickTimeout) sent when the mouse does not have a doubleClick within DoubleClickTime. 4 (startDrag) sent when the mouse moves more than threshold pixels from evt's position within DoubleClickTime. Note that mouseMove: and mouseUp: events are not sent to aMorph until it becomes the mouse focus, which is typically done by aMorph in its click:, doubleClick:, or drag: methods. " mouseClickState := WizClickState new client: aMorph click: clickAndDragSelectors first dblClick: clickAndDragSelectors second dblClickTime: DoubleClickTime dblClickTimeout: clickAndDragSelectors third drag: clickAndDragSelectors fourth threshold: threshold event: evt! !
!HandMorph class methodsFor: 'accessing' stamp: 'wiz 7/28/2004 00:08'! eventStats ^ EventStats! !
!HandMorph class methodsFor: 'accessing' stamp: 'wiz 8/1/2004 11:54'! eventStatsReset | oldStats | "HandMorph eventStatsReset explore" oldStats _ EventStats. EventStats _ nil . ^oldStats! !
!WizClickState methodsFor: 'access' stamp: 'wiz 7/29/2004 00:43'! history ^ history ! !
!WizClickState methodsFor: 'access' stamp: 'wiz 7/29/2004 01:09'! pastHistory ^ PastHistory! !
!WizClickState methodsFor: 'access' stamp: 'wiz 7/29/2004 10:05'! preserve (PastHistory ifNil: [PastHistory := OrderedCollection new]) size < 100 ifTrue: [PastHistory add: self] .! !
!WizClickState methodsFor: 'access' stamp: 'wiz 7/29/2004 02:41'! resetPastHistory self class resetPastHistory! !
!WizClickState methodsFor: 'event handling' stamp: 'wiz 7/29/2004 00:46'! handleEvent: evt from: aHand (history ifNil: [history := OrderedCollection new]) add: evt. ^ super handleEvent: evt from: aHand ! !
!WizClickState class methodsFor: 'accessing' stamp: 'wiz 7/29/2004 02:39'! pastHistory ^ PastHistory! !
!WizClickState class methodsFor: 'accessing' stamp: 'wiz 7/29/2004 02:44'! resetPastHistory "WizClickState resetPastHistory explore." | oldPastHistory | oldPastHistory := PastHistory. PastHistory := nil. ^ oldPastHistory! !
Attached is the changeset with the diagnostic routines for examining ClickStates and the events that flow thru them.
Yours in service, --Jerome Peace
__________________________________ Do you Yahoo!? New and Improved Yahoo! Mail - Send 10MB messages! http://promotions.yahoo.com/new_mail
squeak-dev@lists.squeakfoundation.org