#REFACTORING by cg
class: DisplaySurface
added:16 methods
FIX: these methods are needed here (to be understood by rootview)
--- a/DisplaySurface.st Wed Dec 18 10:32:14 2019 +0100
+++ b/DisplaySurface.st Wed Dec 18 10:32:30 2019 +0100
@@ -2396,6 +2396,304 @@
"Modified: / 9.1.1999 / 01:58:09 / cg"
! !
+!DisplaySurface methodsFor:'event simulation'!
+
+simulateButtonMotion:buttonMask to:aPoint sendDisplayEvent:sendDisplayEvent
+ "simulate a button motion by determining which sub-view is affected and
+ synthetically generating a buttonPressEvent for whatever view is underneath.
+ Returns the view which precessed the event or nil."
+
+ |ev|
+
+ ev := WindowEvent buttonMotion:buttonMask x:0 y:0 view:self.
+ "/ x/y will be set in simulateUserEvent:at:sendDisplayEvent:
+ ^ self simulateUserEvent:ev at:aPoint sendDisplayEvent:sendDisplayEvent
+!
+
+simulateButtonPress:button at:aPoint
+ "simulate a button press by determining which sub-view is affected and
+ synthetically generating a buttonPressEvent for whatever view is underneath.
+ Returns the view which precessed the event or nil."
+
+ ^ self simulateButtonPress:button at:aPoint sendDisplayEvent:false
+
+ "Created: / 12-07-2011 / 14:36:02 / cg"
+!
+
+simulateButtonPress:button at:aPoint sendDisplayEvent:sendDisplayEvent
+ "simulate a button press by determining which sub-view is affected and
+ synthetically generating a buttonPressEvent for whatever view is underneath.
+ Returns the view which precessed the event or nil."
+
+ |ev|
+
+ ev := WindowEvent buttonPress:button x:0 y:0 view:self.
+ "/ x/y will be set in simulateUserEvent:at:sendDisplayEvent:
+ ^ self simulateUserEvent:ev at:aPoint sendDisplayEvent:sendDisplayEvent
+
+ "Created: / 12-07-2011 / 14:36:02 / cg"
+ "Modified (comment): / 19-07-2019 / 13:57:45 / Claus Gittinger"
+!
+
+simulateButtonRelease:button at:aPoint
+ "simulate a button release by determining which sub-view is affected and
+ synthetically generating a buttonPressEvent for whatever view is underneath.
+ Returns the view which precessed the event or nil."
+
+ ^ self simulateButtonRelease:button at:aPoint sendDisplayEvent:false
+
+ "Created: / 12-07-2011 / 14:54:37 / cg"
+!
+
+simulateButtonRelease:button at:aPoint sendDisplayEvent:sendDisplayEvent
+ "simulate a button release by determining which sub-view is affected and
+ synthetically generating a buttonPressEvent for whatever view is underneath.
+ Returns the view which precessed the event or nil."
+
+ |ev|
+
+ ev := WindowEvent buttonRelease:button x:0 y:0 view:self.
+ "/ x/y will be set in simulateUserEvent:at:sendDisplayEvent:
+ ^ self simulateUserEvent:ev at:aPoint sendDisplayEvent:sendDisplayEvent
+
+ "Created: / 12-07-2011 / 14:54:37 / cg"
+ "Modified (comment): / 19-07-2019 / 13:57:58 / Claus Gittinger"
+!
+
+simulateKey:aKeySymbolOrCharacter at:aPoint sendDisplayEvent:sendDisplayEvent keyPressTime:seconds
+ "simulate text input by generating alternating keyPress/keyRelease events."
+
+ (aKeySymbolOrCharacter isCharacter
+ and:[ aKeySymbolOrCharacter isLetter
+ and:[ aKeySymbolOrCharacter isUppercase
+ ]]) ifTrue:[
+ self simulateKeyPress:#Shift at:aPoint sendDisplayEvent:sendDisplayEvent.
+ self simulateKeyPress:aKeySymbolOrCharacter asLowercase at:aPoint sendDisplayEvent:sendDisplayEvent.
+ Delay waitForSeconds:seconds.
+ self simulateKeyRelease:aKeySymbolOrCharacter asLowercase at:aPoint sendDisplayEvent:sendDisplayEvent.
+ self simulateKeyRelease:#Shift at:aPoint sendDisplayEvent:sendDisplayEvent.
+ ] ifFalse:[
+ self simulateKeyPress:aKeySymbolOrCharacter at:aPoint sendDisplayEvent:sendDisplayEvent.
+ Delay waitForSeconds:seconds.
+ self simulateKeyRelease:aKeySymbolOrCharacter at:aPoint sendDisplayEvent:sendDisplayEvent.
+ ].
+
+ "Created: / 19-07-2019 / 14:40:52 / Claus Gittinger"
+!
+
+simulateKeyPress:keyOrStringOrSymbol at:aPoint
+ "simulate a key press by determining which sub-view is affected and
+ synthetically generating a keyPressEvent for whatever view is underneath.
+ Returns the view which processed the event or nil."
+
+ ^ self simulateKeyPress:keyOrStringOrSymbol at:aPoint sendDisplayEvent:false
+!
+
+simulateKeyPress:keyOrStringOrSymbol at:aPoint sendDisplayEvent:sendDisplayEvent
+ "simulate a key press by determining which sub-view is affected and
+ synthetically generating a keyPressEvent for whatever view is underneath.
+ Returns the view which processed the event or nil."
+
+ |sequence ev lastView|
+
+ (keyOrStringOrSymbol isCharacter or:[keyOrStringOrSymbol isSymbol])
+ ifTrue:[ sequence := Array with:keyOrStringOrSymbol ]
+ ifFalse:[ sequence := keyOrStringOrSymbol ].
+
+ sequence do:[:each |
+ ev := WindowEvent keyPress:each x:0 y:0 view:self.
+ "/ x/y will be set in simulateUserEvent:at:sendDisplayEvent:
+ lastView := self simulateUserEvent:ev at:aPoint sendDisplayEvent:sendDisplayEvent
+ ].
+ ^ lastView
+
+ "Modified (comment): / 19-07-2019 / 13:58:06 / Claus Gittinger"
+!
+
+simulateKeyPressRelease:keyOrStringOrSymbol at:aPoint
+ "simulate a key release by determining which sub-view is affected and
+ synthetically generating a keyPressEvent for whatever view is underneath.
+ Returns the view which processed the event or nil."
+
+ ^ self simulateKeyPressRelease:keyOrStringOrSymbol at:aPoint sendDisplayEvent:false
+!
+
+simulateKeyPressRelease:keyOrStringOrSymbol at:aPoint sendDisplayEvent:sendDisplayEvent
+ "simulate a key release by determining which sub-view is affected and
+ synthetically generating a keyPressEvent for whatever view is underneath.
+ Returns the view which processed the event or nil."
+
+ |sequence ev1 ev2 lastView|
+
+ (keyOrStringOrSymbol isCharacter or:[keyOrStringOrSymbol isSymbol])
+ ifTrue:[ sequence := Array with:keyOrStringOrSymbol ]
+ ifFalse:[ sequence := keyOrStringOrSymbol ].
+
+ sequence do:[:each |
+ ev1 := WindowEvent keyPress:each x:0 y:0 view:self.
+ "/ x/y will be set in simulateUserEvent:at:sendDisplayEvent:
+ lastView := self simulateUserEvent:ev1 at:aPoint sendDisplayEvent:sendDisplayEvent.
+
+ ev2 := WindowEvent keyRelease:each x:0 y:0 view:self.
+ "/ x/y will be set in simulateUserEvent:at:sendDisplayEvent:
+ lastView := self simulateUserEvent:ev2 at:aPoint sendDisplayEvent:sendDisplayEvent.
+ ].
+ ^ lastView
+
+ "Modified (comment): / 19-07-2019 / 13:58:14 / Claus Gittinger"
+!
+
+simulateKeyRelease:keyOrStringOrSymbol at:aPoint
+ "simulate a key release by determining which sub-view is affected and
+ synthetically generating a keyPressEvent for whatever view is underneath.
+ Returns the view which processed the event or nil."
+
+ ^ self simulateKeyRelease:keyOrStringOrSymbol at:aPoint sendDisplayEvent:false
+!
+
+simulateKeyRelease:keyOrStringOrSymbol at:aPoint sendDisplayEvent:sendDisplayEvent
+ "simulate a key release by determining which sub-view is affected and
+ synthetically generating a keyPressEvent for whatever view is underneath.
+ Returns the view which processed the event or nil."
+
+ |sequence ev lastView|
+
+ (keyOrStringOrSymbol isCharacter or:[keyOrStringOrSymbol isSymbol])
+ ifTrue:[ sequence := Array with:keyOrStringOrSymbol ]
+ ifFalse:[ sequence := keyOrStringOrSymbol ].
+
+ sequence do:[:each |
+ ev := WindowEvent keyRelease:each x:0 y:0 view:self.
+ "/ x/y will be set in simulateUserEvent:at:sendDisplayEvent:
+ lastView := self simulateUserEvent:ev at:aPoint sendDisplayEvent:sendDisplayEvent
+ ].
+ ^ lastView
+
+ "Modified (comment): / 19-07-2019 / 13:58:18 / Claus Gittinger"
+!
+
+simulateTextInput:aString at:aPoint sendDisplayEvent:sendDisplayEvent
+ "simulate text input by generating alternating keyPress/keyRelease events."
+
+ self simulateTextInput:aString at:aPoint sendDisplayEvent:sendDisplayEvent keyPressTime:0.05
+!
+
+simulateTextInput:aString at:aPoint sendDisplayEvent:sendDisplayEvent keyPressTime:seconds
+ "simulate text input by generating alternating keyPress/keyRelease events."
+
+ aString do:[:eachCharacter |
+ self simulateKey:eachCharacter at:aPoint sendDisplayEvent:sendDisplayEvent keyPressTime:seconds
+ ].
+
+ "Created: / 19-07-2019 / 14:40:52 / Claus Gittinger"
+!
+
+simulateUserEvent:ev at:aPoint
+ "simulate a button press by determining which sub-view is affected and
+ synthetically generating a buttonPressEvent for whatever view is underneath.
+ Cares for any active grab - i.e. if some other view has grabbed the pointer or keyboard
+ the event is sent to the grabView with pointer coordinate translated as required
+ (typically these are popup views like menus)
+ Returns the view which precessed the event or nil."
+
+ ^ self simulateUserEvent:ev at:aPoint sendDisplayEvent:false
+!
+
+simulateUserEvent:ev at:aPoint sendDisplayEvent:sendDisplayEvent
+ "simulate a button event by determining which sub-view is affected and
+ synthetically generating an event for whatever view is underneath.
+
+ If sendDisplayEvent is true, a real physical event is generated via sendEvent, from the Display (xserver).
+ Otherwise, the event is pushed into the widget's event queue, without a roundtrip through the display.
+
+ Otherwise, care for any active grab - i.e. if some other view has grabbed the pointer or keyboard
+ the event is sent to the grabView with pointer coordinate translated as required
+ (typically these are popup views like menus)
+
+ Returns the view which processed the event or nil.
+ For displayEvent sending, always return the receiver, as we do not know how the grab processing came out at the end"
+
+ |targetView pointXLated sensor evArg|
+
+ sendDisplayEvent ifTrue:[
+ "/ translate to screen coordinates
+ pointXLated := device translatePoint:aPoint from:(self id) to:(device rootWindowId).
+ "/ and send it via the display
+ ev isButtonPressEvent ifTrue:[
+ evArg := #buttonPress
+ ] ifFalse:[ ev isButtonReleaseEvent ifTrue:[
+ evArg := #buttonRelease
+ ] ifFalse:[ ev isKeyPressEvent ifTrue:[
+ evArg := #keyPress
+ ] ifFalse:[ ev isKeyReleaseEvent ifTrue:[
+ evArg := #keyRelease
+ ] ifFalse:[
+ evArg := ev type
+ ]]]].
+ device
+ sendKeyOrButtonEvent:evArg
+ x:pointXLated x y:pointXLated y
+ keyOrButton:(ev isKeyEvent ifTrue:[ev rawKey] ifFalse:[ev button])
+ state:(ev modifierFlags)
+ toViewId:self id.
+ ^ self.
+ ].
+
+ (ev isButtonEvent or:[ev isPointerEnterLeaveEvent]) ifTrue:[
+ "/ if there is a pointer grab, the event has to be sent to that one
+ targetView := device activePointerGrab.
+ "/ Transcript showCR:'direct to %1' with:targetView.
+ ] ifFalse:[
+ (ev isKeyEvent) ifTrue:[
+ "/ if there is a keyboard grab, the event has to be sent to that one
+ targetView := device activeKeyboardGrab.
+ "/ Transcript showCR:'direct to %1' with:targetView.
+ ].
+ ].
+
+ targetView isNil ifTrue:[
+ ((0@0 extent:self extent) containsPoint:aPoint) ifTrue:[
+ self subViews do:[:each |
+ |whichView|
+
+ whichView := each simulateUserEvent:ev
+ at:(device translatePoint:aPoint fromView:self toView:each)
+ sendDisplayEvent:false.
+ whichView notNil ifTrue:[^ whichView].
+ ].
+ targetView := self.
+ ].
+ ].
+
+ targetView notNil ifTrue:[
+ sensor := targetView sensor.
+ targetView == self ifTrue:[
+ pointXLated := aPoint
+ ] ifFalse:[
+ pointXLated := device translatePoint:aPoint fromView:self toView:targetView.
+ ].
+ ev x:(pointXLated x).
+ ev y:(pointXLated y).
+ ev view:targetView.
+
+ ev isButtonPressEvent ifTrue:[
+ sensor buttonPress:ev button x:ev x y:ev y view:targetView.
+ ] ifFalse:[
+ ev isButtonReleaseEvent ifTrue:[
+ sensor buttonRelease:ev button x:(ev x) y:(ev y) view:targetView.
+ ] ifFalse:[
+ sensor pushEvent:ev.
+ ]
+ ].
+ ^ targetView
+ ].
+
+ ^ nil
+
+ "Created: / 12-07-2011 / 14:53:19 / cg"
+ "Modified (format): / 19-07-2019 / 14:08:26 / Claus Gittinger"
+! !
+
!DisplaySurface methodsFor:'initialization & release'!
destroy