<div dir="ltr"><div dir="ltr"><div>Hello Luciano,</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>
I think global shortcuts should be handled first, like it is now; if you
 give the opportunity to morphs to handle it first I wouldn’t be able to
 override some of the shortcuts I’m using and I would have to change 
even more code all over the place to make my shortcuts work.

</div></blockquote></div><div><br></div><div>I agree with you, and this is one of the concerns I denoted with Ken's proposed solution. However this wouldn't be an issue with the method I first proposed since the global shortcuts are always  checked 
first, as long as the morph doesn't tell you to not check it.</div><div><br></div><div>You could also have not overridable shortcuts by just placing them outside the closure of the shouldOverride ifFalse call.<br></div><div><br></div><div>This means that if you have a shortcut that collides with a global one in your code you can either disable all global shortcuts when your morph has keyboard focus by implementing a should override method that returns true or, if you only want to intercept a single one, you can check in that method if the keyboard event is for that specific one and return true or false accordingly.</div><div><br></div><div>This solution where we ask the morph whether it wants to override the keyboard input or not is not intended as a final well modeled solution but rather a stopgap measure to allow morphs to easily override global keyboard events without having to refactor half the system.</div><div><br></div><div>However I'm not sure how we would be able to handle global shortcuts first while giving morphs the opportunity to override them, without first asking them what they want to do.<br></div><div><br></div><div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto"></div><div dir="auto">Also, if the handling is done 
in the event classes then nothing was solved. I agree with Juan that we 
have the option to handle global shortcuts either in the hand or in the 
world. Both options make it easy to change the behaviour, either by 
introducing a new hand or a new world.</div></blockquote>

</div><div><br></div><div>I do agree that the global shortcuts should be handled by the world. That is, the keyboard event sentTo method should invoke a world method that checks if itself is a global shortcut (if the morph didn't ask to override it first). This would basically be done by replacing the code inside the shouldOverride if False with this new world method call.<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>
 never needed the full screen thing in Cuis because my X11 window 
manager (dwm) does that. In fact, I patched it to do this the way I like
 it with win-esc and it works with any window (not only Cuis). I guess 
some window managers don’t have a shortcut for full screen? Or are not 
configurable with the shortcut you prefer and not easy to patch?

</div></blockquote><div><br></div><div>I'm pretty sure this full screen fix came up because this doesn't hold true for the windows version. Sadly not everyone can run a Unix OS exclusively.</div><div><br></div><div>Can you maybe elaborate a bit in the model you propose should be implemented?</div><div><br></div><div>Cheers!</div><div><b>Mauro Rizzi</b><br></div><div><br></div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">El lun, 21 dic 2020 a las 1:46, Luciano Notarfrancesco (<<a href="mailto:luchiano@gmail.com">luchiano@gmail.com</a>>) escribió:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto">I think global shortcuts should be handled first, like it is now; if you give the opportunity to morphs to handle it first I wouldn’t be able to override some of the shortcuts I’m using and I would have to change even more code all over the place to make my shortcuts work.</div><div dir="auto"><br></div><div dir="auto">Also, if the handling is done in the event classes then nothing was solved. I agree with Juan that we have the option to handle global shortcuts either in the hand or in the world. Both options make it easy to change the behaviour, either by introducing a new hand or a new world.</div><div dir="auto"><br></div><div dir="auto">I never needed the full screen thing in Cuis because my X11 window manager (dwm) does that. In fact, I patched it to do this the way I like it with win-esc and it works with any window (not only Cuis). I guess some window managers don’t have a shortcut for full screen? Or are not configurable with the shortcut you prefer and not easy to patch?</div><div dir="auto"><br></div><div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, 21 Dec 2020 at 9:22 AM, Mauro Rizzi <<a href="mailto:mrizzi@fi.uba.ar" target="_blank">mrizzi@fi.uba.ar</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Hello Ken<br></div><div><br></div><div>You're right, I didn't think about the wasHandled: method before and it's a better solution than the one I proposed (assuming the methods isFindClassShortcut and isCloseWindowShortcut and Franco's isFullScreenShortcut would be moved into handleKeyEvent and the processKey* ones would have their return removed).</div><div><br></div><div>It would look something like:</div><div><br></div><div>
vvv============vvv<br>
KeyBoardEvent>><br>
<br>
sentTo: aMorph localPosition: positionInAMorph<br>
<br>
        "Dispatch the receiver into anObject"<span><br>
</span></div><div><span><br></span></div><div><span>
   type == #keystroke ifTrue: [<br>
         aMorph <br></span></div><div><span>                 processKeystroke: self<br>
                 localPosition: positionInAMorph ].<br>
   type == #keyDown ifTrue: [<br>
         aMorph<br>
                processKeyDown: self<br>
                localPosition: positionInAMorph ].<br>
   type == #keyUp ifTrue: [<br>
         aMorph<br>
                processKeyUp: self<br>
                localPosition: positionInAMorph ].<br>
<br></span>
    (self wasHandled)<br>
         ifTrue: [^aMorph] "done"<br>
         ifFalse: [<globaldefaultKeyHandler> handleKeyEvent: self]<br>
<br>
<br>
^^^============^^^

</div><div>  "Inside globaldefaultKeyHandler, of course if someone thinks this object shouldn't exist you could just put it's content on the ifFalse closure. Also technically the ifFalse is unnecessary, but it does provide a lot of clarity."<br></div><div>handleKeyEvent: aKeyboardEvent<br></div><div>
<br>
        aKeyboardEvent isFindClassShortcut<br>
                ifTrue: [ ^ BrowserWindow findClass].<br>
        
aKeyboardEvent 

isCloseWindowShortcut<br>
                ifTrue: [ ^ 
aKeyboardEvent

closeCurrentWindowOf: aMorph <br></div><div>




        aKeyboardEvent 



isFullScreenShortcut<br>                  
    


    


        

ifTrue: [ ^ Display toggleFullScreen ]

</div><div>
<br>
^^^============^^^ <br></div><div><br></div><div>We would have to refactor the current senders of wasHandled: to take into account this change.</div><div><br></div><div>Thinking on the readability of this method and it might be a bit hard to follow the wasHandled method call for someone who is first discovering it, since they potentially might not understand how keyboardEvent knows the event was handled.<br></div><div><br></div><div>I do approve of the idea of having global keystrokes be in a separate object than the standard keyboardEvent, I think it would give clarity to the chain of responsibility if it goes into the morph and then into a global keystroke handler object.</div><div><br></div><div>Thinking about it from an usability standpoint using franco's full screen shorcut (alt + enter) we would have to (with both of the proposed implementations) make the isFullScreenShortcut check on the keyboardEvent inside the target morph to avoid processing the input at the morph level and marking it as handled.</div><div><br></div><div>What I mean with this is that all morphs would be responsible of knowing what inputs they should ignore because the keystrokes that we want to capture for system events would also be considered valid inside the morph and would be executed.</div><div><br></div><div>For example if you press shift enter while writing in a method editor the innerTextPane will happily process the input, put the newline into the pane and mark the event as handled, following that the keyboardEvent will say "ah, well that is done with then, moving on" and the findClass dialogue won't pop up, to avoid this you'd have to check whether the current keystroke is one of the system ones inside the morph's execution chain.</div><div><br></div><div>While I do like your implementation significantly more I think the one I recommended earlier gets around this issue. Since it becomes something optional, your morph can decide if it wants to override certain keystrokes or not but if you don't implement the method shouldOverride (Note: this is a bad name for this method) then you go back to the current behaviour.</div><div><br></div><div>Basically one option gives the morph the choice to tell you if it wants to override or not. The other one gives the morph the responsibility of telling you whether you should override or not.<br></div><div>
<div><br></div><div>And I still feel keyboardEvent should have a hierarchy of the 3 types of keyboard events rather than having a type instance variable.</div><div><br></div><div>I just want to clarify I quite enjoy writing walls of text and this is intended as constructive brainstorming. I'm sorry if it comes out as anything but.  <br></div>

</div><div> </div><div><br></div><div>Cheers!</div></div><div dir="ltr"><div><b>Mauro Rizzi</b><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">El dom, 20 dic 2020 a las 20:54, <<a href="mailto:ken.dickey@whidbey.com" target="_blank">ken.dickey@whidbey.com</a>> escribió:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 2020-12-20 21:25, Mauro Rizzi wrote:<br>
<br>
..<br>
> shouldOverride := aMorph shouldOverride: self<br>
<br>
I am suggesting that if the Morph processes the keystroke, it _has_ <br>
overriden and _does NOT need_ a #shouldOverride method.<br>
<br>
So<br>
vvv============vvv<br>
KeyBoardEvent>><br>
<br>
sentTo: aMorph localPosition: positionInAMorph<br>
<br>
        "Dispatch the receiver into anObject"<br>
<br>
   type == #keystroke ifTrue: [<br>
        self isFindClassShortcut<br>
                ifTrue: [ ^ BrowserWindow findClass].<br>
        self isCloseWindowShortcut<br>
                ifTrue: [ ^ self closeCurrentWindowOf: aMorph ].<br>
        ^ aMorph processKeystroke: self<br>
                 localPosition: positionInAMorph ].<br>
   type == #keyDown ifTrue: [<br>
                ^ aMorph<br>
                        processKeyDown: self<br>
                        localPosition: positionInAMorph ].<br>
   type == #keyUp ifTrue: [<br>
                ^ aMorph<br>
                        processKeyUp: self<br>
                        localPosition: positionInAMorph ].<br>
<br>
    (self wasHandled)<br>
         ifTrue: [^aMorph] "done"<br>
         ifFalse: [<globaldefaultKeyHandler> handleKeyEvent: self]<br>
<br>
<br>
^^^============^^^<br>
<br>
Note: I am not an expert here.  Just a guess..<br>
<br>
Prototype is best.<br>
-KenD<br>
</blockquote></div>
</blockquote></div></div>
</blockquote></div></div>