Marcel Taeumel uploaded a new version of Tools to project The Trunk:
http://source.squeak.org/trunk/Tools-mt.925.mcz
==================== Summary ====================
Name: Tools-mt.925
Author: mt
Time: 17 December 2019, 12:20:36.750485 pm
UUID: 17c98235-d38d-a54b-8f11-ae0965831640
Ancestors: Tools-ct.924
Improves debugger documentation.
=============== Diff against Tools-ct.924 ===============
Item was changed:
CodeHolder subclass: #Debugger
instanceVariableNames: 'interruptedProcess contextStack contextStackIndex contextStackList receiverInspector receiverInspectorState contextVariablesInspector contextVariablesInspectorState externalInterrupt proceedValue selectingPC savedCursor isolationHead failedProject labelString message untilExpression'
classVariableNames: 'ContextStackKeystrokes ErrorReportServer FullStackSize InterruptUIProcessIfBlockedOnErrorInBackgroundProcess NotifierStackSize SavedExtent StackSizeLimit WantsAnnotationPane'
poolDictionaries: ''
category: 'Tools-Debugger'!
+ !Debugger commentStamp: 'mt 12/17/2019 12:19' prior: 0!
- !Debugger commentStamp: '<historical>' prior: 0!
I represent the machine state at the time of an interrupted process. I also represent a query path into the state of the process. The debugger is typically viewed through a window that views the stack of suspended contexts, the code for, and execution point in, the currently selected message, and inspectors on both the receiver of the currently selected message, and the variables in the current context.
Special note on recursive errors:
Some errors affect Squeak's ability to present a debugger. This is normally an unrecoverable situation. However, if such an error occurs in an isolation layer, Squeak will attempt to exit from the isolation layer and then present a debugger. Here is the chain of events in such a recovery.
* A recursive error is detected.
* The current project is queried for an isolationHead
* Changes in the isolationHead are revoked
* The parent project of isolated project is returned to
* The debugger is opened there and execution resumes.
+ If the user closes that debugger, execution continues in the outer project and layer. If, after repairing some damage, the user proceeds from the debugger, then the isolationHead is re-invoked, the failed project is re-entered, and execution resumes in that world.
+
+ ---
+
+ In September 2019, we added MorphicDebugger and MVCDebugger to untangle framework-specific features in our debugger infrastructure. However, this is just an intermediate step. The overall goal would be to remove those two subclasses again while preserving their functionality. Mostly, MVC and Morphic differ in their GUI-process management. This means that "proceed" and "close" work differently depending on the process that is being debugged. --- One idea is to attach that framework-specific information to the process objects. See Process >> #environmentAt: and #environmentAt:put:. Also see ToolSet's #handle* and #debug* methods.!
- If the user closes that debugger, execution continues in the outer project and layer. If, after repairing some damage, the user proceeds from the debugger, then the isolationHead is re-invoked, the failed project is re-entered, and execution resumes in that world. !
Marcel Taeumel uploaded a new version of Nebraska to project The Trunk:
http://source.squeak.org/trunk/Nebraska-mt.56.mcz
==================== Summary ====================
Name: Nebraska-mt.56
Author: mt
Time: 17 December 2019, 12:07:02.761485 pm
UUID: 90147475-1225-5b47-84ec-00a105e196a6
Ancestors: Nebraska-mt.55
Fixes invalid message categories, found via ReleaseBuilder-mt.204.
=============== Diff against Nebraska-mt.55 ===============
Item was changed:
+ ----- Method: RemoteCanvas>>apply: (in category 'private') -----
- ----- Method: RemoteCanvas>>apply: (in category 'as yet unclassified') -----
apply: ignored
"added for the convenience of BufferedCanvas"!
Item was changed:
+ ----- Method: RemoteCanvas>>backlog (in category 'accessing') -----
- ----- Method: RemoteCanvas>>backlog (in category 'nil') -----
backlog
^connection backlog!
Marcel Taeumel uploaded a new version of CollectionsTests to project The Trunk:
http://source.squeak.org/trunk/CollectionsTests-mt.330.mcz
==================== Summary ====================
Name: CollectionsTests-mt.330
Author: mt
Time: 16 December 2019, 12:01:26.779045 pm
UUID: 779ba425-f187-324a-9b83-27c0e2c70ba3
Ancestors: CollectionsTests-mt.329
Adds a generator test that got only documented on the mailing list so far.
=============== Diff against CollectionsTests-mt.329 ===============
Item was added:
+ ----- Method: GeneratorTest>>testYieldLookAhead (in category 'tests') -----
+ testYieldLookAhead
+ "Check the look-ahead in our current implementation. See http://forum.world.st/Generators-td4941886.html."
+
+ | x gen result |
+ x := 0.
+
+ gen := Generator on: [:g |
+ x := 1.
+ g yield: nil.
+
+ x := 2.
+ g yield: nil.
+
+ x := 3.
+ g yield: nil].
+
+ result := OrderedCollection new.
+ gen do: [:i | result add: x].
+
+ self deny: (result hasEqualElements: #(1 2 3)).
+ self assert: (result hasEqualElements: #(2 3 3)).!
Marcel Taeumel uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-mt.1288.mcz
==================== Summary ====================
Name: Kernel-mt.1288
Author: mt
Time: 16 December 2019, 9:06:49.662845 am
UUID: 3e88e0c8-27ef-dc4a-9017-227b63e2ce72
Ancestors: Kernel-mt.1286
Clean up documentation and code of latest key-code fix. Thanks Nicolas (nice) for the tip!
=============== Diff against Kernel-mt.1286 ===============
Item was changed:
----- Method: EventSensor class>>installDuplicateKeyEntryFor: (in category 'key decode table') -----
+ installDuplicateKeyEntryFor: aPrintableCharacter
+ "Updates the key-decode table, which maps between pairs of {character code . modifier code}. See the class comment for more information.
+ Note that the bitmask 16r9F removes the high bits, which subtracts 64 from the key code for (upper) $A to $Z and 96 for (lower) $a to $z. The VM sends non-printable control characters for [ctrl]+[A-Za-Z] in ASCII < 32, but the given character is expected to be ASCII >= 32 and thus printable. So we have to convert printable characters to control characters in this mapping table."
- installDuplicateKeyEntryFor: c
- "Updates key-decode table. The table maps pairs of {character code . modifier code}. See the class comment for more information. Note that the bitmask 16r9F is used to convert control characters (ascii 0 to 31) to printable characters."
| upper lower |
+ upper := aPrintableCharacter asUppercase asInteger.
+ lower := aPrintableCharacter asLowercase asInteger.
- upper := c asUppercase asInteger.
- lower := c asLowercase asInteger.
KeyDecodeTable at: { lower bitAnd: 16r9F . 2 "ctrl" } put: { lower . 8 "cmd/alt" }.
KeyDecodeTable at: { upper bitAnd: 16r9F . 2 bitOr: 1 "ctrl+shift" } put: { upper . 8 bitOr: 1 "cmd/alt+shift" }.
!
Item was changed:
----- Method: EventSensor class>>installSwappedKeyEntryFor: (in category 'key decode table') -----
+ installSwappedKeyEntryFor: aPrintableCharacter
+ "Updates the key-decode table, which maps between pairs of {character code . modifier code}. See the class comment for more information.
+ Note that the bitmask 16r9F removes the high bits, which subtracts 64 from the key code for (upper) $A to $Z and 96 for (lower) $a to $z. The VM sends non-printable control characters for [ctrl]+[A-Za-Z] in ASCII < 32, but the given character is expected to be ASCII >= 32 and thus printable. So we have to convert printable characters to control characters in this mapping table."
- installSwappedKeyEntryFor: c
- "Updates key-decode table. The table maps pairs of {character code . modifier code}. See the class comment for more information. Note that the bitmask 16r9F is used to convert control characters (ascii 0 to 31) to printable characters."
| upper lower |
+ upper := aPrintableCharacter asUppercase asInteger.
+ lower := aPrintableCharacter asLowercase asInteger.
- upper := c asUppercase asInteger.
- lower := c asLowercase asInteger.
KeyDecodeTable at: { lower bitAnd: 16r9F . 2 "ctrl" } put: { lower . 8 "cmd/alt" }.
KeyDecodeTable at: { lower . 8 "cmd/alt" } put: { lower bitAnd: 16r9F . 2 "ctrl" }.
KeyDecodeTable at: { upper bitAnd: 16r9F . 2 bitOr: 1 "ctrl+shift" } put: { upper . 8 bitOr: 1 "cmd/alt+shift" }.
KeyDecodeTable at: { upper . 8 bitOr: 1 "cmd/alt+shift" } put: { upper bitAnd: 16r9F . 2 bitOr: 1 "ctrl+shift" }.!
Item was changed:
----- Method: EventSensor>>processEvent: (in category 'private-I/O') -----
processEvent: evt
"Process a single event. This method is run at high priority."
| type buttons window |
type := evt at: 1.
"Only process main window events, forward others to host window proxies"
window := evt at: 8.
(window isNil or: [window isZero]) ifTrue:
[window := 1.
evt at: 8 put: window].
window = 1 ifFalse: [
^Smalltalk at: #HostWindowProxy ifPresent: [:w | w processEvent: evt]].
"Tackle mouse events and mouse wheel events first"
(type = EventTypeMouse or: [type = EventTypeMouseWheel])
ifTrue: [buttons := (ButtonDecodeTable at: (evt at: 5) + 1).
evt at: 5 put: (Smalltalk platformName = 'Mac OS'
ifTrue: [ buttons ]
ifFalse: [ self mapButtons: buttons modifiers: (evt at: 6) ]).
self queueEvent: evt.
type = EventTypeMouse ifTrue: [self processMouseEvent: evt].
type = EventTypeMouseWheel ifTrue: [self processMouseWheelEvent: evt].
^self].
"Store the event in the queue if there's any"
type = EventTypeKeyboard
ifTrue: [ "Check if the event is a user interrupt"
+ ((evt at: 4) = EventKeyChar
- ((evt at: 4) = 0
and: [((evt at: 3)
bitOr: (((evt at: 5)
bitAnd: 8)
bitShift: 8))
= interruptKey])
ifTrue: ["interrupt key is meta - not reported as event"
^ interruptSemaphore signal].
+ "Decode keys for characters (i.e., duplicate or swap, ctrl <-> alt/cmd)."
+ (evt at: 4) = EventKeyChar
+ ifTrue: [
+ KeyDecodeTable "Unicode character first"
+ at: {evt at: 6. evt at: 5}
+ ifPresent: [:a | evt at: 6 put: a first;
+ at: 5 put: a second].
+ KeyDecodeTable "ASCII character second"
+ at: {evt at: 3. evt at: 5}
+ ifPresent: [:a | evt at: 3 put: a first;
+ at: 5 put: a second]].
- "Else swap ctrl/alt keys if neeeded.
- Look at the Unicode char first, then ascii."
- (evt at: 4) = 0 "key stroke only" ifTrue: [
- KeyDecodeTable
- at: {evt at: 6. evt at: 5}
- ifPresent: [:a | evt at: 6 put: a first;
- at: 5 put: a second].
- KeyDecodeTable
- at: {evt at: 3. evt at: 5}
- ifPresent: [:a | evt at: 3 put: a first;
- at: 5 put: a second]].
self queueEvent: evt.
self processKeyboardEvent: evt .
^self ].
+ "Handle all events other than Keyboard or Mouse."
- "Handle all events other than Keyborad or Mouse."
self queueEvent: evt.
!
Marcel Taeumel uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-mt.1286.mcz
==================== Summary ====================
Name: Kernel-mt.1286
Author: mt
Time: 13 December 2019, 4:24:23.507615 pm
UUID: 2f99cd52-d053-cb40-a84a-6c257ee118f4
Ancestors: Kernel-mt.1285
Fixes key-code mapping to map only in key-stroke events. This fixes the bug where a key-down/up event on [ctrl] appeared as [ctrl+q], [shift] as [shift+P], and [cmd] as [cmd+r]. Also fix key swapping and duplication for [ctrl+shift] combinations. Improves documentation in EventSensor class comment.
=============== Diff against Kernel-mt.1285 ===============
Item was changed:
Object subclass: #EventSensor
instanceVariableNames: 'mouseButtons mousePosition mouseWheelDelta keyboardBuffer interruptKey interruptSemaphore eventQueue inputSemaphore lastEventPoll hasInputSemaphore'
classVariableNames: 'ButtonDecodeTable EventPollPeriod EventTicklerProcess InterruptSemaphore InterruptWatcherProcess KeyDecodeTable'
poolDictionaries: 'EventSensorConstants'
category: 'Kernel-Processes'!
+ !EventSensor commentStamp: 'mt 12/13/2019 14:38' prior: 0!
- !EventSensor commentStamp: 'mt 12/13/2019 13:57' prior: 0!
An EventSensor is an interface to the user input devices.
There is at least one instance of EventSensor named Sensor in the system.
EventSensor is a replacement for the earlier InputSensor implementation based on a set of (optional) event primitives. An EventSensor updates its state when events are received so that all state based users of Sensor (e.g., Sensor keyboard, Sensor leftShiftDown, Sensor mouseButtons) will work exactly as before, by moving the current VM mechanisms into EventSensor itself. An optional input semaphore is part of the new design.
For platforms that support true asynchronous event notification, the semaphore will be signaled to indicate pending events.
On platforms that do not support asynchronous notifications about events, the UI will have to poll EventSensor periodically to read events from the VM.
Instance variables:
mouseButtons <Integer> - mouse button state as replacement for primMouseButtons
mousePosition <Point> - mouse position as replacement for primMousePt
keyboardBuffer <SharedQueue> - keyboard input buffer
interruptKey <Integer> - currently defined interrupt key
interruptSemaphore <Semaphore> - the semaphore signaled when the interruptKey is detected
eventQueue <SharedQueue> - an optional event queue for event driven applications
inputSemaphore <Semaphore>- the semaphore signaled by the VM if asynchronous event notification is supported
lastEventPoll <Integer> - the last millisecondClockValue at which we called fetchMoreEvents
hasInputSemaphore <Boolean> - true if my inputSemaphore has actually been signaled at least once.
Class variables:
ButtonDecodeTable <ByteArray> - maps mouse buttons as reported by the VM to ones reported in the events.
KeyDecodeTable <Dictionary<SmallInteger->SmallInteger>> - maps some keys and their modifiers to other keys (used for instance to map Ctrl-X to Alt-X)
InterruptSemaphore <Semaphore> - signalled by the the VM and/or the event loop upon receiving an interrupt keystroke.
InterruptWatcherProcess <Process> - waits on the InterruptSemaphore and then responds as appropriate.
EventPollPeriod <Integer> - the number of milliseconds to wait between polling for more events in the userInterruptHandler.
EventTicklerProcess <Process> - the process that makes sure that events are polled for often enough (at least every EventPollPeriod milliseconds).
Event format:
The current event format is very simple. Each event is recorded into an 8 element array. All events must provide some SmallInteger ID (the first field in the event buffer) and a time stamp (the second field in the event buffer), so that the difference between the time stamp of an event and the current time can be reported.
Currently, the following events are defined:
Null event
=============
The Null event is returned when the ST side asks for more events but no more events are available.
Structure:
[1] - event type 0
[2-8] - unused
Mouse event structure
==========================
Mouse events are generated when mouse input is detected.
[1] - event type 1
[2] - time stamp
[3] - mouse x position
[4] - mouse y position
[5] - button state; bitfield with the following entries:
1 - 2r001 yellow (e.g., right) button
2 - 2r010 blue (e.g., middle) button
4 - 2r100 red (e.g., left) button
[all other bits are currently undefined]
[6] - modifier keys; bitfield with the following entries:
1 - shift key
2 - ctrl key
4 - (Mac specific) option key
8 - Cmd/Alt key
[all other bits are currently undefined]
[7] - reserved.
+ [8] - host window id.
- [8] - reserved.
Keyboard events
====================
Keyboard events are generated when keyboard input is detected.
[1] - event type 2
[2] - time stamp
[3] - character code (Ascii)
For now the character code is in Mac Roman encoding. See #macToSqueak.
For key press/release (see [4]), character codes are normalized.
[4] - press state; integer with the following meaning
0 - character (aka. key stroke or key still pressed)
1 - key press (aka. key down)
2 - key release (aka. key up)
[5] - modifier keys (same as in mouse events)
For key press/release (see [4]), modifier keys are still accessible.
[6] - character code (Unicode UTF32)
Manual decoding via KeyboardInputInterpreter possible.
For key press/release (see [4]), character codes are normalized.
[7] - reserved.
+ [8] - host window id.
- [8] - reserved.
Mouse-wheel event structure
==========================
Mouse-wheel events are generated when mouse-wheel input is detected.
[1] - event type 7
[2] - time stamp
[3] - horizontal scroll delta
[4] - vertical scroll delta
[5] - button state (same as in mouse events)
[6] - modifier keys (same as in mouse events)
[7] - reserved.
+ [8] - host window id.
- [8] - reserved.
!
Item was changed:
----- Method: EventSensor class>>installDuplicateKeyEntryFor: (in category 'key decode table') -----
installDuplicateKeyEntryFor: c
+ "Updates key-decode table. The table maps pairs of {character code . modifier code}. See the class comment for more information. Note that the bitmask 16r9F is used to convert control characters (ascii 0 to 31) to printable characters."
- "Updates key-decode table. The table maps pairs of {character code . modifier code}. See the class comment for more information."
+ | upper lower |
+ upper := c asUppercase asInteger.
+ lower := c asLowercase asInteger.
+
+ KeyDecodeTable at: { lower bitAnd: 16r9F . 2 "ctrl" } put: { lower . 8 "cmd/alt" }.
+ KeyDecodeTable at: { upper bitAnd: 16r9F . 2 bitOr: 1 "ctrl+shift" } put: { upper . 8 bitOr: 1 "cmd/alt+shift" }.
- | key |
- key := c asInteger.
- self flag: #toDocument. "mt: Why that 'key bitAnd: 16r9F' conversion? Some old VM hack?"
- KeyDecodeTable at: { key bitAnd: 16r9F . 2 "ctrl" } put: { key . 8 "cmd/alt" }.
- KeyDecodeTable at: { key . 8 "cmd/alt" } put: { key . 8 "cmd/alt"}
!
Item was changed:
----- Method: EventSensor class>>installSwappedKeyEntryFor: (in category 'key decode table') -----
installSwappedKeyEntryFor: c
+ "Updates key-decode table. The table maps pairs of {character code . modifier code}. See the class comment for more information. Note that the bitmask 16r9F is used to convert control characters (ascii 0 to 31) to printable characters."
- "Updates key-decode table. The table maps pairs of {character code . modifier code}. See the class comment for more information."
+ | upper lower |
+ upper := c asUppercase asInteger.
+ lower := c asLowercase asInteger.
+
+ KeyDecodeTable at: { lower bitAnd: 16r9F . 2 "ctrl" } put: { lower . 8 "cmd/alt" }.
+ KeyDecodeTable at: { lower . 8 "cmd/alt" } put: { lower bitAnd: 16r9F . 2 "ctrl" }.
+ KeyDecodeTable at: { upper bitAnd: 16r9F . 2 bitOr: 1 "ctrl+shift" } put: { upper . 8 bitOr: 1 "cmd/alt+shift" }.
+ KeyDecodeTable at: { upper . 8 bitOr: 1 "cmd/alt+shift" } put: { upper bitAnd: 16r9F . 2 bitOr: 1 "ctrl+shift" }.!
- | key |
- key := c asInteger.
- self flag: #toDocument. "mt: Why that 'key bitAnd: 16r9F' conversion? Some old VM hack?"
- KeyDecodeTable at: { key bitAnd: 16r9F . 2 "ctrl" } put: { key . 8 "cmd/alt" }.
- KeyDecodeTable at: { key . 8 "cmd/alt" } put: { key bitAnd: 16r9F . 2 "cmd/alt" }!
Item was changed:
----- Method: EventSensor>>processEvent: (in category 'private-I/O') -----
processEvent: evt
"Process a single event. This method is run at high priority."
| type buttons window |
type := evt at: 1.
"Only process main window events, forward others to host window proxies"
window := evt at: 8.
(window isNil or: [window isZero]) ifTrue:
[window := 1.
evt at: 8 put: window].
window = 1 ifFalse: [
^Smalltalk at: #HostWindowProxy ifPresent: [:w | w processEvent: evt]].
"Tackle mouse events and mouse wheel events first"
(type = EventTypeMouse or: [type = EventTypeMouseWheel])
ifTrue: [buttons := (ButtonDecodeTable at: (evt at: 5) + 1).
evt at: 5 put: (Smalltalk platformName = 'Mac OS'
ifTrue: [ buttons ]
ifFalse: [ self mapButtons: buttons modifiers: (evt at: 6) ]).
self queueEvent: evt.
type = EventTypeMouse ifTrue: [self processMouseEvent: evt].
type = EventTypeMouseWheel ifTrue: [self processMouseWheelEvent: evt].
^self].
"Store the event in the queue if there's any"
type = EventTypeKeyboard
ifTrue: [ "Check if the event is a user interrupt"
((evt at: 4) = 0
and: [((evt at: 3)
bitOr: (((evt at: 5)
bitAnd: 8)
bitShift: 8))
= interruptKey])
ifTrue: ["interrupt key is meta - not reported as event"
^ interruptSemaphore signal].
"Else swap ctrl/alt keys if neeeded.
Look at the Unicode char first, then ascii."
+ (evt at: 4) = 0 "key stroke only" ifTrue: [
+ KeyDecodeTable
+ at: {evt at: 6. evt at: 5}
+ ifPresent: [:a | evt at: 6 put: a first;
+ at: 5 put: a second].
+ KeyDecodeTable
+ at: {evt at: 3. evt at: 5}
+ ifPresent: [:a | evt at: 3 put: a first;
+ at: 5 put: a second]].
- KeyDecodeTable
- at: {evt at: 6. evt at: 5}
- ifPresent: [:a | evt at: 6 put: a first;
- at: 5 put: a second].
- KeyDecodeTable
- at: {evt at: 3. evt at: 5}
- ifPresent: [:a | evt at: 3 put: a first;
- at: 5 put: a second].
self queueEvent: evt.
self processKeyboardEvent: evt .
^self ].
"Handle all events other than Keyborad or Mouse."
self queueEvent: evt.
!
Marcel Taeumel uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-mt.1285.mcz
==================== Summary ====================
Name: Kernel-mt.1285
Author: mt
Time: 13 December 2019, 2:25:24.279249 pm
UUID: 1c18d133-29d7-6049-a7be-40a8d045b474
Ancestors: Kernel-mt.1284
Improves documentation in EventSensor.
=============== Diff against Kernel-mt.1284 ===============
Item was changed:
Object subclass: #EventSensor
instanceVariableNames: 'mouseButtons mousePosition mouseWheelDelta keyboardBuffer interruptKey interruptSemaphore eventQueue inputSemaphore lastEventPoll hasInputSemaphore'
classVariableNames: 'ButtonDecodeTable EventPollPeriod EventTicklerProcess InterruptSemaphore InterruptWatcherProcess KeyDecodeTable'
poolDictionaries: 'EventSensorConstants'
category: 'Kernel-Processes'!
+ !EventSensor commentStamp: 'mt 12/13/2019 13:57' prior: 0!
- !EventSensor commentStamp: 'dtl 1/30/2016 14:44' prior: 0!
An EventSensor is an interface to the user input devices.
There is at least one instance of EventSensor named Sensor in the system.
EventSensor is a replacement for the earlier InputSensor implementation based on a set of (optional) event primitives. An EventSensor updates its state when events are received so that all state based users of Sensor (e.g., Sensor keyboard, Sensor leftShiftDown, Sensor mouseButtons) will work exactly as before, by moving the current VM mechanisms into EventSensor itself. An optional input semaphore is part of the new design.
For platforms that support true asynchronous event notification, the semaphore will be signaled to indicate pending events.
On platforms that do not support asynchronous notifications about events, the UI will have to poll EventSensor periodically to read events from the VM.
Instance variables:
mouseButtons <Integer> - mouse button state as replacement for primMouseButtons
mousePosition <Point> - mouse position as replacement for primMousePt
keyboardBuffer <SharedQueue> - keyboard input buffer
interruptKey <Integer> - currently defined interrupt key
interruptSemaphore <Semaphore> - the semaphore signaled when the interruptKey is detected
eventQueue <SharedQueue> - an optional event queue for event driven applications
inputSemaphore <Semaphore>- the semaphore signaled by the VM if asynchronous event notification is supported
lastEventPoll <Integer> - the last millisecondClockValue at which we called fetchMoreEvents
hasInputSemaphore <Boolean> - true if my inputSemaphore has actually been signaled at least once.
Class variables:
ButtonDecodeTable <ByteArray> - maps mouse buttons as reported by the VM to ones reported in the events.
KeyDecodeTable <Dictionary<SmallInteger->SmallInteger>> - maps some keys and their modifiers to other keys (used for instance to map Ctrl-X to Alt-X)
InterruptSemaphore <Semaphore> - signalled by the the VM and/or the event loop upon receiving an interrupt keystroke.
InterruptWatcherProcess <Process> - waits on the InterruptSemaphore and then responds as appropriate.
EventPollPeriod <Integer> - the number of milliseconds to wait between polling for more events in the userInterruptHandler.
EventTicklerProcess <Process> - the process that makes sure that events are polled for often enough (at least every EventPollPeriod milliseconds).
Event format:
The current event format is very simple. Each event is recorded into an 8 element array. All events must provide some SmallInteger ID (the first field in the event buffer) and a time stamp (the second field in the event buffer), so that the difference between the time stamp of an event and the current time can be reported.
Currently, the following events are defined:
Null event
=============
The Null event is returned when the ST side asks for more events but no more events are available.
Structure:
[1] - event type 0
[2-8] - unused
Mouse event structure
==========================
Mouse events are generated when mouse input is detected.
- Structure:
[1] - event type 1
[2] - time stamp
[3] - mouse x position
[4] - mouse y position
[5] - button state; bitfield with the following entries:
+ 1 - 2r001 yellow (e.g., right) button
+ 2 - 2r010 blue (e.g., middle) button
+ 4 - 2r100 red (e.g., left) button
- 1 - yellow (e.g., right) button
- 2 - blue (e.g., middle) button
- 4 - red (e.g., left) button
[all other bits are currently undefined]
[6] - modifier keys; bitfield with the following entries:
1 - shift key
2 - ctrl key
4 - (Mac specific) option key
8 - Cmd/Alt key
[all other bits are currently undefined]
[7] - reserved.
[8] - reserved.
Keyboard events
====================
Keyboard events are generated when keyboard input is detected.
[1] - event type 2
[2] - time stamp
+ [3] - character code (Ascii)
+ For now the character code is in Mac Roman encoding. See #macToSqueak.
+ For key press/release (see [4]), character codes are normalized.
- [3] - character code
- For now the character code is in Mac Roman encoding.
[4] - press state; integer with the following meaning
+ 0 - character (aka. key stroke or key still pressed)
+ 1 - key press (aka. key down)
+ 2 - key release (aka. key up)
- 0 - character
- 1 - key press (down)
- 2 - key release (up)
[5] - modifier keys (same as in mouse events)
+ For key press/release (see [4]), modifier keys are still accessible.
+ [6] - character code (Unicode UTF32)
+ Manual decoding via KeyboardInputInterpreter possible.
+ For key press/release (see [4]), character codes are normalized.
- [6] - reserved.
[7] - reserved.
[8] - reserved.
+
+ Mouse-wheel event structure
+ ==========================
+ Mouse-wheel events are generated when mouse-wheel input is detected.
+ [1] - event type 7
+ [2] - time stamp
+ [3] - horizontal scroll delta
+ [4] - vertical scroll delta
+ [5] - button state (same as in mouse events)
+ [6] - modifier keys (same as in mouse events)
+ [7] - reserved.
+ [8] - reserved.
!
Item was changed:
----- Method: EventSensor class>>installDuplicateKeyEntryFor: (in category 'key decode table') -----
installDuplicateKeyEntryFor: c
+ "Updates key-decode table. The table maps pairs of {character code . modifier code}. See the class comment for more information."
+
| key |
key := c asInteger.
+ self flag: #toDocument. "mt: Why that 'key bitAnd: 16r9F' conversion? Some old VM hack?"
+ KeyDecodeTable at: { key bitAnd: 16r9F . 2 "ctrl" } put: { key . 8 "cmd/alt" }.
+ KeyDecodeTable at: { key . 8 "cmd/alt" } put: { key . 8 "cmd/alt"}
- "first do control->alt key"
- KeyDecodeTable at: { key bitAnd: 16r9F . 2 } put: { key . 8 }.
- "then alt->alt key"
- KeyDecodeTable at: { key . 8 } put: { key . 8 }
!
Item was changed:
----- Method: EventSensor class>>installSwappedKeyEntryFor: (in category 'key decode table') -----
installSwappedKeyEntryFor: c
+ "Updates key-decode table. The table maps pairs of {character code . modifier code}. See the class comment for more information."
+
| key |
key := c asInteger.
+ self flag: #toDocument. "mt: Why that 'key bitAnd: 16r9F' conversion? Some old VM hack?"
+ KeyDecodeTable at: { key bitAnd: 16r9F . 2 "ctrl" } put: { key . 8 "cmd/alt" }.
+ KeyDecodeTable at: { key . 8 "cmd/alt" } put: { key bitAnd: 16r9F . 2 "cmd/alt" }!
- "first do control->alt key"
- KeyDecodeTable at: { key bitAnd: 16r9F . 2 } put: { key . 8 }.
- "then alt->control key"
- KeyDecodeTable at: { key . 8 } put: { key bitAnd: 16r9F . 2 }!
Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-mt.1608.mcz
==================== Summary ====================
Name: Morphic-mt.1608
Author: mt
Time: 13 December 2019, 10:02:28.682784 am
UUID: aefd108e-0a66-0041-a417-669c5b08df12
Ancestors: Morphic-mt.1607
Fixes a small glitch that I introduced in the last commit.
=============== Diff against Morphic-mt.1607 ===============
Item was changed:
----- Method: TextEditor>>evaluateSelectionAndDo: (in category 'do-its') -----
evaluateSelectionAndDo: aBlock
"Treat the current selection as an expression; evaluate it and invoke aBlock with the result."
| result rcvr ctxt selectionInterval |
self lineSelectAndEmptyCheck: [^ nil].
(model respondsTo: #evaluateExpression:) ifTrue: [
^ aBlock value: (model perform: #evaluateExpression: with: self selection)].
(model respondsTo: #doItReceiver)
ifTrue: [ rcvr := model doItReceiver.
ctxt := model doItContext]
ifFalse: [rcvr := ctxt := nil].
selectionInterval := self selectionInterval.
+ result := [
- result := [[
rcvr class evaluatorClass new
evaluate: self selectionAsStream
in: ctxt
to: rcvr
environment: (model environment ifNil: [Smalltalk globals])
notifying: self
ifFail: [morph flash. ^ nil]
logged: true.
]
on: OutOfScopeNotification
+ do: [ :ex | ex resume: true].
+ "The parser might change the current selection for interactive error correction."
+ self selectInterval: selectionInterval.
- do: [ :ex | ex resume: true]
- ]
- ensure: [
- "The parser might change the current selection for interactive error correction."
- self selectInterval: selectionInterval].
(model respondsTo: #expressionEvaluated:result:) ifTrue: [
model perform: #expressionEvaluated:result: with: self selection with: result].
^aBlock value: result!