#REFACTORING by cg
authorClaus Gittinger <cg@exept.de>
Wed, 18 Dec 2019 10:32:30 +0100
changeset 8936 54027288924c
parent 8935 bb3677b7a7bb
child 8937 a9c4ca74ecb0
#REFACTORING by cg class: DisplaySurface added:16 methods FIX: these methods are needed here (to be understood by rootview)
DisplaySurface.st
--- 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