Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
 - refactor processEventsFromQueue:, split obtention of events in nextEventFrom:
 - add pendingEventQueue and queuePendingEvent:
 - make nextEventFrom: give priority to pending events
 - make MouseClickState queue pending mouseUp for next cycle
  • Loading branch information
guillep committed Mar 27, 2020
1 parent 63c83df commit 887a9a9
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 41 deletions.
8 changes: 4 additions & 4 deletions src/Morphic-Base/Form.extension.st
Expand Up @@ -12,13 +12,13 @@ Form >> asMorph [
]

{ #category : #'*Morphic-Base' }
Form >> floodFillTolerance [
^ self class floodFillTolerance
Form class >> floodFillTolerance [
^ FloodFillTolerance ifNil: [FloodFillTolerance := 0.0]
]

{ #category : #'*Morphic-Base' }
Form class >> floodFillTolerance [
^ FloodFillTolerance ifNil: [FloodFillTolerance := 0.0]
Form >> floodFillTolerance [
^ self class floodFillTolerance
]

{ #category : #'*Morphic-Base' }
Expand Down
11 changes: 8 additions & 3 deletions src/Morphic-Base/MouseClickState.class.st
Expand Up @@ -120,12 +120,17 @@ MouseClickState >> handleEvent: evt from: aHand [
self click.
aHand resetClickState.
^true].
"Otherwise transfer to #firstClickUp"
firstClickUp := evt copy.

"Change the state to #firstClickUp.
Then queue the mouseUp event for later processing.
We will handle a click now."
clickState := #firstClickUp.
firstClickUp := evt copy.
"If timedOut or the client's not interested in dbl clicks get outta here"
aHand handleEvent: firstClickUp.
aHand queuePendingEvent: firstClickUp.

self click.

^false].
isDrag ifTrue:["drag start"
self doubleClickTimeout. "***"
Expand Down
114 changes: 80 additions & 34 deletions src/Morphic-Core/HandMorph.class.st
Expand Up @@ -27,7 +27,8 @@ Class {
'lastKeyScanCode',
'combinedChar',
'captureBlock',
'recentModifiers'
'recentModifiers',
'pendingEventQueue'
],
#classVars : [
'DoubleClickTime',
Expand Down Expand Up @@ -904,6 +905,49 @@ HandMorph >> newMouseFocus: aMorph event: event [
^self newMouseFocus: aMorph
]

{ #category : #'private events' }
HandMorph >> nextEventFrom: anEventBufferQueue [
"Returns the next morphic event to handle.
Three cases may arise:
- If possible, a valid morphic event is returned
- If no more events are available, nil is returned
- If we find an invalid event in the queue, we consume it and return the #invalid symbol
The first morphic events available are those in the pending queue.
An event handling cycle should generate and manage a single event.
In the case a cycle needs to generate several events (see MouseClickState), only one event is handled.
Remaining events are queued for later processing.
"
| eventBuffer morphicEvent type pendingMorphicEvent |

pendingMorphicEvent := self pendingEventQueue nextOrNil.
pendingMorphicEvent ifNotNil: [ ^ pendingMorphicEvent ].

anEventBufferQueue ifNil: [ ^ nil ].
eventBuffer := anEventBufferQueue nextEvent.
eventBuffer ifNil: [ ^ nil ].

morphicEvent := nil. "for unknown event types"
type := eventBuffer first.
type = EventTypeMouse ifTrue: [ self world beCursorOwner.
recentModifiers := eventBuffer sixth.
morphicEvent := self generateMouseEvent: eventBuffer
].
type = EventTypeKeyboard ifTrue: [
recentModifiers := eventBuffer fifth.
morphicEvent := self generateKeyboardEvent: eventBuffer
].
type = EventTypeDragDropFiles ifTrue: [
morphicEvent := self generateDropFilesEvent: eventBuffer ].
type = EventTypeWindow ifTrue: [
morphicEvent := self generateWindowEvent: eventBuffer ].

"If the event did not match any of the categories above, it is an invalid event"
( type ~= EventTypeDragDropFiles and: [ morphicEvent isNil ] )
ifTrue: [ ^ #invalid ].
^ morphicEvent
]

{ #category : #accessing }
HandMorph >> noButtonPressed [
"Answer whether any mouse button is not being pressed."
Expand Down Expand Up @@ -979,6 +1023,12 @@ HandMorph >> pasteBuffer: aMorphOrNil [

]

{ #category : #'private events' }
HandMorph >> pendingEventQueue [

^ pendingEventQueue ifNil: [ pendingEventQueue := WaitfreeQueue new ]
]

{ #category : #geometry }
HandMorph >> position [

Expand Down Expand Up @@ -1019,7 +1069,7 @@ HandMorph >> processEvents [
]

{ #category : #'private events' }
HandMorph >> processEventsFromQueue: anEventQueue [
HandMorph >> processEventsFromQueue: anEventBufferQueue [

"Process user input events from the local input devices."

Expand All @@ -1031,38 +1081,34 @@ HandMorph >> processEventsFromQueue: anEventQueue [
self mouseOverHandler processMouseOver: lastMouseEvent ].

hadAny := false.
[ anEventQueue isNotNil and: [ ( evtBuf := anEventQueue nextEvent ) isNotNil ] ]
whileTrue: [ evt := nil. "for unknown event types"
type := evtBuf first.
type = EventTypeMouse
ifTrue: [ self world beCursorOwner.
recentModifiers := evtBuf sixth.
evt := self generateMouseEvent: evtBuf
].
type = EventTypeKeyboard
ifTrue: [ recentModifiers := evtBuf fifth.
evt := self generateKeyboardEvent: evtBuf
].
type = EventTypeDragDropFiles
ifTrue: [ evt := self generateDropFilesEvent: evtBuf ].
type = EventTypeWindow
ifTrue: [ evt := self generateWindowEvent: evtBuf ]. "All other events are ignored"
( type ~= EventTypeDragDropFiles and: [ evt isNil ] )
ifTrue: [ ^ self ].
evt
ifNotNil: [ "Finally, handle it"
self handleEvent: evt.
hadAny := true. "For better user feedback, return immediately after a mouse event has been processed."
( evt isMouse and: [ evt isMouseWheel not ] )
ifTrue: [ ^ self ]
]
]. "note: if we come here we didn't have any mouse events"
mouseClickState notNil
ifTrue:
[ "No mouse events during this cycle. Make sure click states time out accordingly" mouseClickState handleEvent: lastMouseEvent asMouseMove from: self ].
hadAny
ifFalse:
[ "No pending events. Make sure z-order is up to date" self mouseOverHandler processMouseOver: lastMouseEvent ]
[ (evt := self nextEventFrom: anEventBufferQueue) notNil ] whileTrue: [
evt == #invalid ifTrue: [ ^ self ].
evt ifNotNil: [ "Finally, handle it"
self handleEvent: evt.
hadAny := true.
"For better user feedback, return immediately after a mouse event has been processed."
( evt isMouse and: [ evt isMouseWheel not ] )
ifTrue: [ ^ self ]
]
].

"note: if we come here we didn't have any mouse events"
mouseClickState notNil ifTrue: [
"No mouse events during this cycle. Make sure click states time out accordingly"
mouseClickState handleEvent: lastMouseEvent asMouseMove from: self ].
hadAny ifFalse: [
"No pending events. Make sure z-order is up to date"
self mouseOverHandler processMouseOver: lastMouseEvent ]
]

{ #category : #'private events' }
HandMorph >> queuePendingEvent: aMorphicEvent [
"Queue an (extra) event produced during an event handling cycle, to be processed in later cycles.
An event handling cycle should generate and manage a single event.
In the case a cycle needs to generate several events (see MouseClickState), only one event is handled.
Remaining events are queued for later processing.
"
self pendingEventQueue nextPut: aMorphicEvent
]

{ #category : #'focus handling' }
Expand Down

0 comments on commit 887a9a9

Please sign in to comment.