Tony Garnock-Jones uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-tonyg.1997.mcz
==================== Summary ====================
Name: Morphic-tonyg.1997 Author: tonyg Time: 24 May 2022, 9:56:56.627629 am UUID: ea8cb549-5895-4ad8-8fde-4fcb6ea5594e Ancestors: Morphic-ct.1996
Repair bug that caused unconditional clearing of the #mouseOverForKeyboardFocus preference whenever the host window was de/reactivated.
Symptoms: switching away from Squeak and back (or save-and-quit followed by reopen) while #mouseOverForKeyboardFocus enabled would cause it to become disabled.
Cause: PasteUpMorph>>#windowEvent: was clearing the preference and then restoring it from state in a WindowHostFocusMorph. However, when #windowDeactivated occurred twice in a row (which happens), it would correctly store #mouseOverForKeyboardFocus in the first WindowHostFocusMorph instance, but then would deactivate and replace that instance with a fresh one, which would then receive the incorrect (false) value of #mouseOverForKeyboardFocus. Later, when the window was activated again, the incorrect value would be restored, because the correct value had already been forgotten (as it was contained in the first, rather than the second-and-current, WindowHostFocusMorph instance).
Change: Alter WindowHostFocusMorph>>#active: to not only set the active instvar but to save or restore the #mouseOverForKeyboardFocus preference. This way, any time a WindowHostFocusMorph is activated, the preference is saved, and any time it is deactivated, the preference is restored. This works with the current logic in PasteUpMorph>>#windowEvent:. One drawback is that it repeatedly toggles the preference, depending on how many redundant de/reactivation events the host sends us in a row, but the final value of the preference is at least correct now (I hope!).
=============== Diff against Morphic-ct.1996 ===============
Item was changed: ----- Method: PasteUpMorph>>windowEvent: (in category 'event handling') ----- windowEvent: anEvent
self windowEventHandler ifNotNil: [^self windowEventHandler windowEvent: anEvent]. anEvent type caseOf: { [#windowClose] -> [ Preferences eToyFriendly ifTrue: [ProjectNavigationMorph basicNew quitSqueak] ifFalse: [TheWorldMenu basicNew quitSession]]. [#windowDeactivated] -> [ + "The host window has been deactivated. Until it regains the focus, honor the fact that we will not receive keyboard events again by changing the current keyboard focus morph. windowHostFocusMorph represents the host system which now holds the keyboard focus instead of the previousFocus." - "The host window has been deactivated. Until it regains the focus, honor the fact that we will not receive keyboard events again by changing the current keyboard focus morph. windowHostFocusMorph represents the host system which now holds the keyboard focus instead of the previousFocus. If enabled, disable #mouseOverForKeyboardFocus temporarily because when inactive, we *can't* set the externally controlled keyboard focus." (self valueOfProperty: #windowHostFocusMorph) ifNotNil: [:hostFocus | "There is currently no exact-once guarantee for this event type from the VM. Mark any older host focus morph as inactive, it will be held as the previousFocus of the next host focus morph." hostFocus active: false]. self setProperty: #windowHostFocusMorph toValue: (WindowHostFocusMorph new in: [:hostFocus | hostFocus previousFocus: anEvent hand keyboardFocus. + anEvent hand newKeyboardFocus: hostFocus.]; - anEvent hand newKeyboardFocus: hostFocus. - Preferences mouseOverForKeyboardFocus ifTrue: [ - hostFocus previousMouseOverForKeyboardFocus: true. - Preferences setPreference: #mouseOverForKeyboardFocus toValue: false]]; yourself)]. [#windowActivated] -> [ + "Alright, the spook is over!! We have back control over the keyboard focus, delete the windowHostFocusMorph and restore the previous focus holder." - "Alright, the spook is over!! We have back control over the keyboard focus, delete the windowHostFocusMorph and restore the previous focus holder and the #mouseOverForKeyboardFocus preference." (self removeProperty: #windowHostFocusMorph) ifNotNil: [:hostFocus | hostFocus active: false. (anEvent hand keyboardFocus == hostFocus and: [hostFocus previousFocus notNil]) ifTrue: + [anEvent hand newKeyboardFocus: hostFocus previousFocus]]]. } - [anEvent hand newKeyboardFocus: hostFocus previousFocus]. - hostFocus previousMouseOverForKeyboardFocus ifNotNil: [:value | - Preferences setPreference: #mouseOverForKeyboardFocus toValue: value]]]. } otherwise: []!
Item was changed: ----- Method: WindowHostFocusMorph>>active: (in category 'accessing') ----- active: aBoolean + active := aBoolean.
+ active + ifTrue: [ + "If #mouseOverForKeyboardFocus is enabled, disable it temporarily because when WindowHostFocusMorph 'has the focus', Squeak as a whole *doesn't*, and we *can't* set the externally controlled keyboard focus." + self saveMouseOverForKeyboardFocus] + ifFalse: [ + "Restore the #mouseOverForKeyboardFocus preference that we (maybe) saved when we were activated." + self restoreMouseOverForKeyboardFocus]! - active := aBoolean.!
Item was removed: - ----- Method: WindowHostFocusMorph>>previousMouseOverForKeyboardFocus (in category 'accessing') ----- - previousMouseOverForKeyboardFocus - - ^ previousMouseOverForKeyboardFocus!
Item was removed: - ----- Method: WindowHostFocusMorph>>previousMouseOverForKeyboardFocus: (in category 'accessing') ----- - previousMouseOverForKeyboardFocus: aBoolean - - previousMouseOverForKeyboardFocus := aBoolean.!
Item was added: + ----- Method: WindowHostFocusMorph>>restoreMouseOverForKeyboardFocus (in category 'accessing') ----- + restoreMouseOverForKeyboardFocus + previousMouseOverForKeyboardFocus ifNotNil: [:value | + previousMouseOverForKeyboardFocus := nil. + Preferences setPreference: #mouseOverForKeyboardFocus toValue: value].!
Item was added: + ----- Method: WindowHostFocusMorph>>saveMouseOverForKeyboardFocus (in category 'accessing') ----- + saveMouseOverForKeyboardFocus + Preferences mouseOverForKeyboardFocus ifTrue: [ + previousMouseOverForKeyboardFocus := true. + Preferences setPreference: #mouseOverForKeyboardFocus toValue: false].!
On May 24, 2022, at 1:02 AM, commits@source.squeak.org wrote:
Repair bug that caused unconditional clearing of the #mouseOverForKeyboardFocus preference whenever the host window was de/reactivated.
Deep thank yous from a user of #mouseOverForKeyboardFocus!
Best, Tim J.
OMG, THANK YOU! I suffered by this for how Magma opens multiple images to run its test suite. Whenever the suite would fail, it's a pain to get all the windows closed, I almost sure, because of this bug. I searched high and low for the cause, but was never able to track it down. Great work!
On Tue, May 24, 2022 at 3:03 AM commits@source.squeak.org wrote:
Tony Garnock-Jones uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-tonyg.1997.mcz
==================== Summary ====================
Name: Morphic-tonyg.1997 Author: tonyg Time: 24 May 2022, 9:56:56.627629 am UUID: ea8cb549-5895-4ad8-8fde-4fcb6ea5594e Ancestors: Morphic-ct.1996
Repair bug that caused unconditional clearing of the #mouseOverForKeyboardFocus preference whenever the host window was de/reactivated.
Symptoms: switching away from Squeak and back (or save-and-quit followed by reopen) while #mouseOverForKeyboardFocus enabled would cause it to become disabled.
Cause: PasteUpMorph>>#windowEvent: was clearing the preference and then restoring it from state in a WindowHostFocusMorph. However, when #windowDeactivated occurred twice in a row (which happens), it would correctly store #mouseOverForKeyboardFocus in the first WindowHostFocusMorph instance, but then would deactivate and replace that instance with a fresh one, which would then receive the incorrect (false) value of #mouseOverForKeyboardFocus. Later, when the window was activated again, the incorrect value would be restored, because the correct value had already been forgotten (as it was contained in the first, rather than the second-and-current, WindowHostFocusMorph instance).
Change: Alter WindowHostFocusMorph>>#active: to not only set the active instvar but to save or restore the #mouseOverForKeyboardFocus preference. This way, any time a WindowHostFocusMorph is activated, the preference is saved, and any time it is deactivated, the preference is restored. This works with the current logic in PasteUpMorph>>#windowEvent:. One drawback is that it repeatedly toggles the preference, depending on how many redundant de/reactivation events the host sends us in a row, but the final value of the preference is at least correct now (I hope!).
=============== Diff against Morphic-ct.1996 ===============
Item was changed:
----- Method: PasteUpMorph>>windowEvent: (in category 'event handling')
windowEvent: anEvent
self windowEventHandler ifNotNil: [^self windowEventHandler windowEvent: anEvent]. anEvent type caseOf: { [#windowClose] -> [ Preferences eToyFriendly ifTrue: [ProjectNavigationMorph
basicNew quitSqueak] ifFalse: [TheWorldMenu basicNew quitSession]].
[#windowDeactivated] -> [
"The host window has been deactivated.
Until it regains the focus, honor the fact that we will not receive keyboard events again by changing the current keyboard focus morph. windowHostFocusMorph represents the host system which now holds the keyboard focus instead of the previousFocus."
"The host window has been deactivated.
Until it regains the focus, honor the fact that we will not receive keyboard events again by changing the current keyboard focus morph. windowHostFocusMorph represents the host system which now holds the keyboard focus instead of the previousFocus. If enabled, disable #mouseOverForKeyboardFocus temporarily because when inactive, we *can't* set the externally controlled keyboard focus." (self valueOfProperty: #windowHostFocusMorph) ifNotNil: [:hostFocus | "There is currently no exact-once guarantee for this event type from the VM. Mark any older host focus morph as inactive, it will be held as the previousFocus of the next host focus morph." hostFocus active: false]. self setProperty: #windowHostFocusMorph toValue: (WindowHostFocusMorph new in: [:hostFocus | hostFocus previousFocus: anEvent hand keyboardFocus.
anEvent hand
newKeyboardFocus: hostFocus.];
anEvent hand
newKeyboardFocus: hostFocus.
Preferences
mouseOverForKeyboardFocus ifTrue: [
hostFocus
previousMouseOverForKeyboardFocus: true.
Preferences
setPreference: #mouseOverForKeyboardFocus toValue: false]]; yourself)]. [#windowActivated] -> [
"Alright, the spook is over!! We have back
control over the keyboard focus, delete the windowHostFocusMorph and restore the previous focus holder."
"Alright, the spook is over!! We have back
control over the keyboard focus, delete the windowHostFocusMorph and restore the previous focus holder and the #mouseOverForKeyboardFocus preference." (self removeProperty: #windowHostFocusMorph) ifNotNil: [:hostFocus | hostFocus active: false. (anEvent hand keyboardFocus == hostFocus and: [hostFocus previousFocus notNil]) ifTrue:
[anEvent hand
newKeyboardFocus: hostFocus previousFocus]]]. }
[anEvent hand
newKeyboardFocus: hostFocus previousFocus].
hostFocus
previousMouseOverForKeyboardFocus ifNotNil: [:value |
Preferences setPreference:
#mouseOverForKeyboardFocus toValue: value]]]. } otherwise: []!
Item was changed:
----- Method: WindowHostFocusMorph>>active: (in category 'accessing')
active: aBoolean
active := aBoolean.
active
ifTrue: [
"If #mouseOverForKeyboardFocus is enabled, disable
it temporarily because when WindowHostFocusMorph 'has the focus', Squeak as a whole *doesn't*, and we *can't* set the externally controlled keyboard focus."
self saveMouseOverForKeyboardFocus]
ifFalse: [
"Restore the #mouseOverForKeyboardFocus preference
that we (maybe) saved when we were activated."
self restoreMouseOverForKeyboardFocus]!
active := aBoolean.!
Item was removed:
- ----- Method: WindowHostFocusMorph>>previousMouseOverForKeyboardFocus
(in category 'accessing') -----
- previousMouseOverForKeyboardFocus
^ previousMouseOverForKeyboardFocus!
Item was removed:
- ----- Method: WindowHostFocusMorph>>previousMouseOverForKeyboardFocus:
(in category 'accessing') -----
- previousMouseOverForKeyboardFocus: aBoolean
previousMouseOverForKeyboardFocus := aBoolean.!
Item was added:
- ----- Method: WindowHostFocusMorph>>restoreMouseOverForKeyboardFocus (in
category 'accessing') -----
- restoreMouseOverForKeyboardFocus
previousMouseOverForKeyboardFocus ifNotNil: [:value |
previousMouseOverForKeyboardFocus := nil.
Preferences setPreference: #mouseOverForKeyboardFocus
toValue: value].!
Item was added:
- ----- Method: WindowHostFocusMorph>>saveMouseOverForKeyboardFocus (in
category 'accessing') -----
- saveMouseOverForKeyboardFocus
Preferences mouseOverForKeyboardFocus ifTrue: [
previousMouseOverForKeyboardFocus := true.
Preferences setPreference: #mouseOverForKeyboardFocus
toValue: false].!
Ouch, sorry for the inconvenience. Thank you for fixing this! Still works for me on both Windows + Linux. :-)
Best,
Christoph
________________________________ Von: Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von Chris Muller asqueaker@gmail.com Gesendet: Mittwoch, 1. Juni 2022 02:20:37 An: squeak dev Cc: packages@lists.squeakfoundation.org Betreff: Re: [squeak-dev] The Trunk: Morphic-tonyg.1997.mcz
OMG, THANK YOU! I suffered by this for how Magma opens multiple images to run its test suite. Whenever the suite would fail, it's a pain to get all the windows closed, I almost sure, because of this bug. I searched high and low for the cause, but was never able to track it down. Great work!
On Tue, May 24, 2022 at 3:03 AM <commits@source.squeak.orgmailto:commits@source.squeak.org> wrote: Tony Garnock-Jones uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-tonyg.1997.mcz
==================== Summary ====================
Name: Morphic-tonyg.1997 Author: tonyg Time: 24 May 2022, 9:56:56.627629 am UUID: ea8cb549-5895-4ad8-8fde-4fcb6ea5594e Ancestors: Morphic-ct.1996
Repair bug that caused unconditional clearing of the #mouseOverForKeyboardFocus preference whenever the host window was de/reactivated.
Symptoms: switching away from Squeak and back (or save-and-quit followed by reopen) while #mouseOverForKeyboardFocus enabled would cause it to become disabled.
Cause: PasteUpMorph>>#windowEvent: was clearing the preference and then restoring it from state in a WindowHostFocusMorph. However, when #windowDeactivated occurred twice in a row (which happens), it would correctly store #mouseOverForKeyboardFocus in the first WindowHostFocusMorph instance, but then would deactivate and replace that instance with a fresh one, which would then receive the incorrect (false) value of #mouseOverForKeyboardFocus. Later, when the window was activated again, the incorrect value would be restored, because the correct value had already been forgotten (as it was contained in the first, rather than the second-and-current, WindowHostFocusMorph instance).
Change: Alter WindowHostFocusMorph>>#active: to not only set the active instvar but to save or restore the #mouseOverForKeyboardFocus preference. This way, any time a WindowHostFocusMorph is activated, the preference is saved, and any time it is deactivated, the preference is restored. This works with the current logic in PasteUpMorph>>#windowEvent:. One drawback is that it repeatedly toggles the preference, depending on how many redundant de/reactivation events the host sends us in a row, but the final value of the preference is at least correct now (I hope!).
=============== Diff against Morphic-ct.1996 ===============
Item was changed: ----- Method: PasteUpMorph>>windowEvent: (in category 'event handling') ----- windowEvent: anEvent
self windowEventHandler ifNotNil: [^self windowEventHandler windowEvent: anEvent].
anEvent type caseOf: { [#windowClose] -> [ Preferences eToyFriendly ifTrue: [ProjectNavigationMorph basicNew quitSqueak] ifFalse: [TheWorldMenu basicNew quitSession]].
[#windowDeactivated] -> [ + "The host window has been deactivated. Until it regains the focus, honor the fact that we will not receive keyboard events again by changing the current keyboard focus morph. windowHostFocusMorph represents the host system which now holds the keyboard focus instead of the previousFocus." - "The host window has been deactivated. Until it regains the focus, honor the fact that we will not receive keyboard events again by changing the current keyboard focus morph. windowHostFocusMorph represents the host system which now holds the keyboard focus instead of the previousFocus. If enabled, disable #mouseOverForKeyboardFocus temporarily because when inactive, we *can't* set the externally controlled keyboard focus." (self valueOfProperty: #windowHostFocusMorph) ifNotNil: [:hostFocus | "There is currently no exact-once guarantee for this event type from the VM. Mark any older host focus morph as inactive, it will be held as the previousFocus of the next host focus morph." hostFocus active: false]. self setProperty: #windowHostFocusMorph toValue: (WindowHostFocusMorph new in: [:hostFocus | hostFocus previousFocus: anEvent hand keyboardFocus. + anEvent hand newKeyboardFocus: hostFocus.]; - anEvent hand newKeyboardFocus: hostFocus. - Preferences mouseOverForKeyboardFocus ifTrue: [ - hostFocus previousMouseOverForKeyboardFocus: true. - Preferences setPreference: #mouseOverForKeyboardFocus toValue: false]]; yourself)]. [#windowActivated] -> [ + "Alright, the spook is over!! We have back control over the keyboard focus, delete the windowHostFocusMorph and restore the previous focus holder." - "Alright, the spook is over!! We have back control over the keyboard focus, delete the windowHostFocusMorph and restore the previous focus holder and the #mouseOverForKeyboardFocus preference." (self removeProperty: #windowHostFocusMorph) ifNotNil: [:hostFocus | hostFocus active: false. (anEvent hand keyboardFocus == hostFocus and: [hostFocus previousFocus notNil]) ifTrue: + [anEvent hand newKeyboardFocus: hostFocus previousFocus]]]. } - [anEvent hand newKeyboardFocus: hostFocus previousFocus]. - hostFocus previousMouseOverForKeyboardFocus ifNotNil: [:value | - Preferences setPreference: #mouseOverForKeyboardFocus toValue: value]]]. } otherwise: []!
Item was changed: ----- Method: WindowHostFocusMorph>>active: (in category 'accessing') ----- active: aBoolean + active := aBoolean.
+ active + ifTrue: [ + "If #mouseOverForKeyboardFocus is enabled, disable it temporarily because when WindowHostFocusMorph 'has the focus', Squeak as a whole *doesn't*, and we *can't* set the externally controlled keyboard focus." + self saveMouseOverForKeyboardFocus] + ifFalse: [ + "Restore the #mouseOverForKeyboardFocus preference that we (maybe) saved when we were activated." + self restoreMouseOverForKeyboardFocus]! - active := aBoolean.!
Item was removed: - ----- Method: WindowHostFocusMorph>>previousMouseOverForKeyboardFocus (in category 'accessing') ----- - previousMouseOverForKeyboardFocus - - ^ previousMouseOverForKeyboardFocus!
Item was removed: - ----- Method: WindowHostFocusMorph>>previousMouseOverForKeyboardFocus: (in category 'accessing') ----- - previousMouseOverForKeyboardFocus: aBoolean - - previousMouseOverForKeyboardFocus := aBoolean.!
Item was added: + ----- Method: WindowHostFocusMorph>>restoreMouseOverForKeyboardFocus (in category 'accessing') ----- + restoreMouseOverForKeyboardFocus + previousMouseOverForKeyboardFocus ifNotNil: [:value | + previousMouseOverForKeyboardFocus := nil. + Preferences setPreference: #mouseOverForKeyboardFocus toValue: value].!
Item was added: + ----- Method: WindowHostFocusMorph>>saveMouseOverForKeyboardFocus (in category 'accessing') ----- + saveMouseOverForKeyboardFocus + Preferences mouseOverForKeyboardFocus ifTrue: [ + previousMouseOverForKeyboardFocus := true. + Preferences setPreference: #mouseOverForKeyboardFocus toValue: false].!
squeak-dev@lists.squeakfoundation.org