[squeak-dev] The Trunk: Kernel-mt.1286.mcz

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Fri Dec 13 23:47:22 UTC 2019


Hi Marcel,

Le ven. 13 déc. 2019 à 16:24, <commits at source.squeak.org> a écrit :

> 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."
>

Err, bitAnd: 16r9F remove the high bits.
So for upper letter $A to $Z it will remove 64
And for lower letter $a to $z it will remove 96
It thus converts printable characters to control characters, and not the
other way around
(I explained that in
https://github.com/OpenSmalltalk/opensmalltalk-vm/issues/396#issuecomment-501459729
)

-       "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."
>
same remark as above...

-       "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
>
In an unpublished change, I have replaced above 0 with EventKeyChar, we
should use semantic constants where due...

>                                 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: [
>
please use  EventKeyChar rather than 0 as said above

> +                               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."
>
I also corrected the typo above (should be Keyboard), so if you can
duplicate my unfinished effort, it's all good ;)

        self queueEvent: evt.
>         !
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20191214/63cee1a3/attachment.html>


More information about the Squeak-dev mailing list