[squeak-dev] Review Request: interactionModes.1.cs

christoph.thiede at student.hpi.uni-potsdam.de christoph.thiede at student.hpi.uni-potsdam.de
Fri Apr 1 14:05:28 UTC 2022


=============== Summary ===============

Change Set:        interactionModes
Date:            1 April 2022
Author:            Christoph Thiede

Explicates the concept of 'interaction modes' to fix handling of #openToolsAttachedToMouseCursor after a dialog or debugger has been completed. Now, all of the following situations work:

    For example, you can evaluate the following via keyboard and then click Ok/Proceed via mouse:
        self inform: 'Hello world!'.
        'Hello world again!' edit.
    Here is another example:
        self halt. self halt.

There were multiple limitiations with the previous approach, which relied on #currentEvent: 1) After running a sub world cycle (e.g., for a dialog window), #currentEvent is outdated and does no longer represent the current 'interaction mode'. 2) #currentEvent is scoped to the active process, but the process instance is invisible to the user and might change during some interactions (e.g., when closing a debugger). New HandMorph>>#currentInteractionMode resolves these limitations by a) relying on #lastEvent rather than #currentEvent and b) providing an execute-around method (#freezeInteractionModeFromEvent:during:) for overriding the interaction mode when changing the process.

Depends on lastEvent.cs for honoring keyboard events in #lastEvent, too.

=============== Diff ===============

HandMorph>>currentInteractionMode {accessing} · ct 4/1/2022 14:43
+ currentInteractionMode
+ 
+     ^ Processor activeProcess environmentAt: {self. #interactionMode} ifAbsent: [
+         self interactionModeForEvent: self lastEvent]

HandMorph>>freezeInteractionModeFromEvent:during: {accessing} · ct 4/1/2022 15:13
+ freezeInteractionModeFromEvent: anEvent during: aBlock
+ 
+     | outer |
+     outer := self valueOfProperty: #frozenInteractionMode.
+     self setProperty: #frozenInteractionMode toValue: (self interactionModeForEvent: anEvent).
+     ^ aBlock ensure: [
+         self setProperty: #frozenInteractionMode toValue: outer]

HandMorph>>interactionModeForEvent: {private events} · ct 4/1/2022 14:44
+ interactionModeForEvent: anEvent
+ 
+     ^ (anEvent isMouse or: [anEvent isDropEvent])
+         ifTrue: [#mouse]
+         ifFalse: [#keyboard]

MorphicDebugger class>>openOn:context:label:contents:fullView: {opening} · ct 4/1/2022 15:01 (changed)
openOn: processToDebug context: context label: title contents: contentsStringOrNil fullView: full 
    
    | debugger uiBlock |
    debugger := self new
        process: processToDebug context: context;
        errorWasInUIProcess: (Project current spawnNewProcessIfThisIsUI: processToDebug).
    
    uiBlock := [
        full
            ifTrue: [debugger openFullNoSuspendLabel: title]
            ifFalse: [debugger openNotifierNoSuspendContents: contentsStringOrNil label: title].
    
        "Try layouting the debugger tool at least once to avoid freeze."
        debugger topView ifNotNil: [:window |
            "There are way too many #fullBounds sends. Layout errors might already have happened."
            window allMorphsDo: [:m | (m hasProperty: #errorOnLayout) ifTrue: [self error: 'Layout error']].
            window world doLayout. "Not safely!"].
        "Try drawing the debugger tool at least once to avoid freeze."
        debugger topView ifNotNil: [:window | window world displayWorld. "Not safely!"].
    ].
        
    "Schedule debugging in a deferred UI message if necessary. Note that only the ui process should execute ui code."
    (Project current uiProcess isActiveProcess not or: [processToDebug isActiveProcess])
        ifFalse: uiBlock
-         ifTrue: [ | event |
-             self flag: #discuss. "mt: We need to preserve the currentEvent for #openToolsAttachedToMouseCursor ..."
-             event := self currentEvent.
-             Project current addDeferredUIMessage: [event becomeActiveDuring: uiBlock]].
+         ifTrue: [ | hand event |
+             "Preserve current interaction mode for #openToolsAttachedToMouseCursor."
+             hand := self currentHand.
+             event := hand lastEvent.
+             Project current addDeferredUIMessage: [
+                 hand freezeInteractionModeFromEvent: event during: uiBlock]].
    
    processToDebug suspend.
    
    "Get here only if active process is not the process-to-debug. So in tests, use a helper process if you want to access this return value."
    ^ debugger

SystemWindow>>openAsTool {*ToolBuilder-Morphic-opening} · ct 4/1/2022 14:55 (changed)
openAsTool
    "Open this window as a tool, that is, honor the preferences such as #reuseWindows and #openToolsAttachedToMouseCursor."
- 
+     
    | meOrSimilarWindow |
    meOrSimilarWindow := self openInWorldExtent: self extent.
-     (Project uiManager openToolsAttachedToMouseCursor "and: [ | event |
-         event := self currentEvent.
-         event isMouse and: [event isMouseUp]]") ifTrue: [
-         meOrSimilarWindow setProperty: #initialDrop toValue: true.
-         meOrSimilarWindow hasDropShadow: false.
-         self currentHand attachMorph: meOrSimilarWindow].
+     (Project uiManager openToolsAttachedToMouseCursor
+         and: [
+             "Rather than relying on #currentEvent or #lastEvent here, dispatch detection of the interaction mode to the current hand. In particular, we must support situations where the interaction mode is carried older from another process or world cycle. For example, you can evaluate the following via keyboard and then click Ok/Proceed via mouse:
+                 self inform: 'Hello world!'.
+                 'Hello world again!' edit.
+             Here is another example:
+                 self halt. self halt.
+             "
+             self currentHand currentInteractionMode = #mouse])
+                 ifTrue: [
+                     meOrSimilarWindow setProperty: #initialDrop toValue: true.
+                     meOrSimilarWindow hasDropShadow: false.
+                     self currentHand attachMorph: meOrSimilarWindow].
    ^ meOrSimilarWindow

["interactionModes.1.cs"]

---
Sent from Squeak Inbox Talk
["interactionModes.1.cs"]
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20220401/0d449e37/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: interactionModes.1.cs
Type: application/octet-stream
Size: 4873 bytes
Desc: not available
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20220401/0d449e37/attachment-0001.obj>


More information about the Squeak-dev mailing list