<div id="__MailbirdStyleContent" style="font-size: 10pt;font-family: Arial;color: #000000;text-align: left" dir="ltr">
                                        Hi Christoph --<div><br></div><div>I don't like the name "interaction mode" ... it's way to broad and abstract ... you open up an entirely new namespace for interaction when we should actually focus on making the current user-input event handling more robust and easier to use. You propose a can of worms. <span style="font-size: 10pt">You just put a complex facade in front of #lastEvent/#currentEvent. We have problems with both anyway. So, let's not make that more complicated at the moment.</span></div><div><br></div><div>-1</div><div><br></div><div>Best,</div><div>Marcel</div><div class="mb_sig"></div>
                                        <blockquote class="history_container" type="cite" style="border-left-style: solid;border-width: 1px;margin-top: 20px;margin-left: 0px;padding-left: 10px;min-width: 500px">
                        <p style="color: #AAAAAA; margin-top: 10px;">Am 01.04.2022 16:05:47 schrieb christoph.thiede@student.hpi.uni-potsdam.de <christoph.thiede@student.hpi.uni-potsdam.de>:</p><div style="font-family:Arial,Helvetica,sans-serif">
<b>=============== Summary ===============</b><br>
<br>
Change Set:        interactionModes<br>
Date:            1 April 2022<br>
Author:            Christoph Thiede<br>
<br>
Explicates the concept of 'interaction modes' to fix handling of <span style="color: #000080">#openToolsAttachedToMouseCursor</span> after a dialog or debugger has been completed. Now, all of the following situations work:<br>
<br>
    For example, you can evaluate the following via keyboard and then click Ok/Proceed via mouse:<br>
        <span style="color: #800000">self</span><span style="color: #000000"> </span><span style="color: #000080">inform:</span><span style="color: #000000"> </span><span style="color: #800080">'Hello world!'</span><span style="color: #000000">.</span><span style="color: #FF0000"><br>
        </span><span style="color: #800080">'Hello world again!'</span><span style="color: #000000"> </span><span style="color: #000080">edit</span><span style="color: #000000">.</span><br>
    Here is another example:<br>
        <span style="color: #800000">self</span><span style="color: #000000"> </span><span style="color: #000080">halt</span><span style="color: #000000">.</span><span style="color: #000000"> </span><span style="color: #800000">self</span><span style="color: #000000"> </span><span style="color: #000080">halt</span><span style="color: #000000">.</span><br>
<br>
There were multiple limitiations with the previous approach, which relied on <span style="color: #000080">#currentEvent</span>: 1) After running a sub world cycle (e.g., for a dialog window), <span style="color: #000080">#currentEvent</span> is outdated and does no longer represent the current 'interaction mode'. 2) <span style="color: #000080">#currentEvent</span> 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 <span style="color: #000000">HandMorph</span><span style="color: #000080">>></span><span style="color: #000080">#currentInteractionMode</span> resolves these limitations by a) relying on <span style="color: #000080">#lastEvent</span> rather than <span style="color: #000080">#currentEvent</span> and b) providing an execute-around method (<span style="color: #000080">#freezeInteractionModeFromEvent:during:</span>) for overriding the interaction mode when changing the process.<br>
<br>
Depends on lastEvent.cs for honoring keyboard events in <span style="color: #000080">#lastEvent</span>, too.<br>
<br>
<b>=============== Diff ===============</b><br>
<br>
<b>HandMorph>>currentInteractionMode {accessing} · ct 4/1/2022 14:43</b><br>
<span style="color: #FF0000">+ currentInteractionMode<br>
+ <br>
+     ^ Processor activeProcess environmentAt: {self. #interactionMode} ifAbsent: [<br>
+         self interactionModeForEvent: self lastEvent]</span><br>
<br>
<b>HandMorph>>freezeInteractionModeFromEvent:during: {accessing} · ct 4/1/2022 15:13</b><br>
<span style="color: #FF0000">+ freezeInteractionModeFromEvent: anEvent during: aBlock<br>
+ <br>
+     | outer |<br>
+     outer := self valueOfProperty: #frozenInteractionMode.<br>
+     self setProperty: #frozenInteractionMode toValue: (self interactionModeForEvent: anEvent).<br>
+     ^ aBlock ensure: [<br>
+         self setProperty: #frozenInteractionMode toValue: outer]</span><br>
<br>
<b>HandMorph>>interactionModeForEvent: {private events} · ct 4/1/2022 14:44</b><br>
<span style="color: #FF0000">+ interactionModeForEvent: anEvent<br>
+ <br>
+     ^ (anEvent isMouse or: [anEvent isDropEvent])<br>
+         ifTrue: [#mouse]<br>
+         ifFalse: [#keyboard]</span><br>
<br>
<b>MorphicDebugger class>>openOn:context:label:contents:fullView: {opening} · ct 4/1/2022 15:01 (changed)</b><br>
openOn: processToDebug context: context label: title contents: contentsStringOrNil fullView: full <br>
    <br>
    | debugger uiBlock |<br>
    debugger := self new<br>
        process: processToDebug context: context;<br>
        errorWasInUIProcess: (Project current spawnNewProcessIfThisIsUI: processToDebug).<br>
    <br>
    uiBlock := [<br>
        full<br>
            ifTrue: [debugger openFullNoSuspendLabel: title]<br>
            ifFalse: [debugger openNotifierNoSuspendContents: contentsStringOrNil label: title].<br>
    <br>
        "Try layouting the debugger tool at least once to avoid freeze."<br>
        debugger topView ifNotNil: [:window |<br>
            "There are way too many #fullBounds sends. Layout errors might already have happened."<br>
            window allMorphsDo: [:m | (m hasProperty: #errorOnLayout) ifTrue: [self error: 'Layout error']].<br>
            window world doLayout. "Not safely!"].<br>
        "Try drawing the debugger tool at least once to avoid freeze."<br>
        debugger topView ifNotNil: [:window | window world displayWorld. "Not safely!"].<br>
    ].<br>
        <br>
    "Schedule debugging in a deferred UI message if necessary. Note that only the ui process should execute ui code."<br>
    (Project current uiProcess isActiveProcess not or: [processToDebug isActiveProcess])<br>
        ifFalse: uiBlock<br>
<s><span style="color: #0000FF">-         ifTrue: [ | event |<br>
-             self flag: #discuss. "mt: We need to preserve the currentEvent for #openToolsAttachedToMouseCursor ..."<br>
-             event := self currentEvent.<br>
-             Project current addDeferredUIMessage: [event becomeActiveDuring: uiBlock]].<br>
</span></s><span style="color: #FF0000">+         ifTrue: [ | hand event |<br>
+             "Preserve current interaction mode for #openToolsAttachedToMouseCursor."<br>
+             hand := self currentHand.<br>
+             event := hand lastEvent.<br>
+             Project current addDeferredUIMessage: [<br>
+                 hand freezeInteractionModeFromEvent: event during: uiBlock]].<br>
</span>    <br>
    processToDebug suspend.<br>
    <br>
    "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."<br>
    ^ debugger<br>
<br>
<b>SystemWindow>>openAsTool {*ToolBuilder-Morphic-opening} · ct 4/1/2022 14:55 (changed)</b><br>
openAsTool<br>
    "Open this window as a tool, that is, honor the preferences such as #reuseWindows and #openToolsAttachedToMouseCursor."<br>
<s><span style="color: #0000FF">- <br>
</span></s><span style="color: #FF0000">+     <br>
</span>    | meOrSimilarWindow |<br>
    meOrSimilarWindow := self openInWorldExtent: self extent.<br>
<s><span style="color: #0000FF">-     (Project uiManager openToolsAttachedToMouseCursor "and: [ | event |<br>
-         event := self currentEvent.<br>
-         event isMouse and: [event isMouseUp]]") ifTrue: [<br>
-         meOrSimilarWindow setProperty: #initialDrop toValue: true.<br>
-         meOrSimilarWindow hasDropShadow: false.<br>
-         self currentHand attachMorph: meOrSimilarWindow].<br>
</span></s><span style="color: #FF0000">+     (Project uiManager openToolsAttachedToMouseCursor<br>
+         and: [<br>
+             "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:<br>
+                 self inform: 'Hello world!'.<br>
+                 'Hello world again!' edit.<br>
+             Here is another example:<br>
+                 self halt. self halt.<br>
+             "<br>
+             self currentHand currentInteractionMode = #mouse])<br>
+                 ifTrue: [<br>
+                     meOrSimilarWindow setProperty: #initialDrop toValue: true.<br>
+                     meOrSimilarWindow hasDropShadow: false.<br>
+                     self currentHand attachMorph: meOrSimilarWindow].<br>
</span>    ^ meOrSimilarWindow<br>
<br>
["interactionModes.1.cs"]<br>
<br>
<span style="color: #808080">---<br>
</span><span style="color: #808080"><i>Sent from </i></span><span style="color: #808080"><i><a href="https://github.com/hpi-swa-lab/squeak-inbox-talk"><u><span style="color: #808080">Squeak Inbox Talk</span></u></a></i></span><br>
["interactionModes.1.cs"]
</div></blockquote></div>