'From Squeak3.2gamma of 15 January 2002 [latest update: #4743] on 11 February 2002 at 12:46:13 pm'! "Change Set: swapBtnsAndKeys-nk Date: 11 February 2002 Author: Ned Konz This allows mouse buttons 2 and 3 to be swapped. It also lets you swap common control and alt keys (like c,x,v...) Use the Preferences called swapMouseButtons and swapControlAndAltKeys If you want to add other ctrl/alt swapped keys, use (for instance, for f): InputSensor installSwappedKeyEntryFor: $f (tweaked sw 7/4/2002 to allow loading both into 3.3 & 3.2) " ! Object subclass: #InputSensor instanceVariableNames: '' classVariableNames: 'ButtonDecodeTable InterruptSemaphore InterruptWatcherProcess KeyDecodeTable ' poolDictionaries: '' category: 'Kernel-Processes' module: #(Squeak Language Core Processes)! !InputSensor methodsFor: 'mouse' stamp: 'nk 7/12/2000 09:31'! anyButtonPressed "Answer whether a mouse button is being pressed." ^ self mouseButtons > 0! ! !InputSensor methodsFor: 'mouse' stamp: 'nk 7/12/2000 09:31'! blueButtonPressed "Answer whether only the blue mouse button is being pressed. This is the third mouse button or cmd+click on the Mac." ^ self mouseButtons = 1! ! !InputSensor methodsFor: 'mouse' stamp: 'nk 7/12/2000 09:31'! mouseButtons "Answer the result of primMouseButtons, but swap the mouse buttons if Preferences swapMouseButtons is set. Mask off just the lower 3 buttons (just the mouse buttons)" ^ (ButtonDecodeTable at: self primMouseButtons + 1) bitAnd: 7! ! !InputSensor methodsFor: 'mouse' stamp: 'nk 7/12/2000 09:31'! redButtonPressed "Answer true if the red mouse button is being pressed. This is the first mouse button." ^ self mouseButtons = 4! ! !InputSensor methodsFor: 'mouse' stamp: 'nk 7/12/2000 09:32'! yellowButtonPressed "Answer whether only the yellow mouse button is being pressed. This is the second mouse button or option+click on the Mac." ^ self mouseButtons = 2! ! !InputSensor methodsFor: 'buttons' stamp: 'nk 7/12/2000 09:33'! buttons "Answer the result of primMouseButtons, but swap the mouse buttons if Preferences swapMouseButtons is set." ^ ButtonDecodeTable at: self primMouseButtons + 1! ! !EventSensor methodsFor: 'accessing' stamp: 'nk 2/9/2001 23:00'! buttons ^ mouseButtons! ! !EventSensor methodsFor: 'accessing' stamp: 'nk 2/9/2001 23:00'! mouseButtons ^ mouseButtons bitAnd: 7! ! !EventSensor methodsFor: 'accessing' stamp: 'nk 2/9/2001 19:10'! nextEventSynthesized "Return a synthesized event. This method is called if an event driven client wants to receive events but the primary user interface is not event-driven (e.g., the receiver does not have an event queue but only updates its state). This can, for instance, happen if a Morphic World is run in an MVC window. To simplify the clients work this method will always return all available keyboard events first, and then (repeatedly) the mouse events. Since mouse events come last, the client can assume that after one mouse event has been received there are no more to come. Note that it is impossible for EventSensor to determine if a mouse event has been issued before so the client must be aware of the possible problem of getting repeatedly the same mouse events. See HandMorph>>processEvents for an example on how to deal with this." | kbd array buttons pos modifiers mapped | "First check for keyboard" array _ Array new: 8. kbd _ self primKbdNext. kbd = nil ifFalse: ["simulate keyboard event" array at: 1 put: EventTypeKeyboard. "evt type" array at: 2 put: Time millisecondClockValue. "time stamp" array at: 3 put: (kbd bitAnd: 255). "char code" array at: 4 put: EventKeyChar. "key press/release" array at: 5 put: (kbd bitShift: -8). "modifier keys" ^ array]. "Then check for mouse" buttons _ self buttons. pos _ self primMousePt. modifiers _ buttons bitShift: -3. buttons _ buttons bitAnd: 7. mapped _ self mapButtons: buttons modifiers: modifiers. array at: 1 put: EventTypeMouse; at: 2 put: Time millisecondClockValue; at: 3 put: pos x; at: 4 put: pos y; at: 5 put: mapped; at: 6 put: modifiers. ^ array! ! !EventSensor methodsFor: 'accessing' stamp: 'nk 2/11/2002 12:18'! processEvent: evt "Process a single event. This method is run at high priority." | type | type _ evt at: 1. "Check if the event is a user interrupt" (type = EventTypeKeyboard and:[(evt at: 4) = 0 and:[ ((evt at: 3) bitOr: ((evt at: 5) bitShift: 8)) = interruptKey]]) ifTrue:["interrupt key is meta - not reported as event" ^interruptSemaphore signal]. "Store the event in the queue if there's any" type = EventTypeMouse ifTrue: [evt at: 5 put: (ButtonDecodeTable at: (evt at: 5) + 1)]. type = EventTypeKeyboard ifTrue: ["swap ctrl/alt keys" KeyDecodeTable at: { evt at: 3 . evt at: 5 } ifPresent: [:a | evt at: 3 put: a first; at: 5 put: a second]]. self queueEvent: evt. "Update state for InputSensor." EventTypeMouse = type ifTrue:[self processMouseEvent: evt]. EventTypeKeyboard = type ifTrue:[self processKeyboardEvent: evt]! ! !EventSensor methodsFor: 'private-I/O' stamp: 'nk 4/11/2001 18:28'! processKeyboardEvent: evt "process a keyboard event, updating InputSensor state" | charCode pressCode | "Never update keyboardBuffer if we have an eventQueue active" mouseButtons _ (mouseButtons bitAnd: 7) bitOr: ((evt at: 5) bitShift: 3). eventQueue ifNotNil:[^self]. charCode _ evt at: 3. charCode = nil ifTrue:[^self]. "extra characters not handled in MVC" pressCode _ evt at: 4. pressCode = EventKeyChar ifFalse:[^self]. "key down/up not handled in MVC" "mix in modifiers" charCode _ charCode bitOr: ((evt at: 5) bitShift: 8). keyboardBuffer nextPut: charCode.! ! !InputSensor class methodsFor: 'public' stamp: 'nk 2/11/2002 12:39'! installSwappedKeyEntryFor: c | key | key _ c asInteger. "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 }! ! !InputSensor class methodsFor: 'public' stamp: 'nk 2/10/2002 11:57'! keyDecodeTable ^KeyDecodeTable ifNil: [ self installKeyDecodeTable ]! ! !InputSensor class methodsFor: 'public' stamp: 'nk 2/10/2002 11:57'! swapControlAndAltKeys: aBoolean "InputSensor swapControlAndAltKeys: true" Preferences setPreference: #swapControlAndAltKeys toValue: aBoolean. self installKeyDecodeTable! ! !InputSensor class methodsFor: 'public' stamp: 'nk 2/10/2002 11:57'! swapMouseButtons: aBoolean "InputSensor swapMouseButtons: true" Preferences setPreference: #swapMouseButtons toValue: aBoolean. self installMouseDecodeTable.! ! !InputSensor class methodsFor: 'class initialization' stamp: 'nk 2/11/2002 12:23'! installKeyDecodeTable "Create a decode table that swaps some keys if Preferences swapControlAndAltKeys is set" KeyDecodeTable _ Dictionary new. Preferences swapControlAndAltKeys ifTrue: [ { $c . $x . $v . $a } do: [ :c | self installSwappedKeyEntryFor: c ]. ]! ! !InputSensor class methodsFor: 'class initialization' stamp: 'nk 2/10/2002 11:55'! installMouseDecodeTable "Create a decode table that swaps the lowest-order 2 bits if Preferences swapMouseButtons is set" ButtonDecodeTable _ Preferences swapMouseButtons ifTrue: [ByteArray withAll: ((0 to: 255) collect: [:ea | ((ea bitAnd: 1) << 1 bitOr: (ea bitAnd: 2) >> 1) bitOr: (ea bitAnd: 16rFC) ])] ifFalse: [ByteArray withAll: (0 to: 255)]! ! !InputSensor class methodsFor: 'system startup' stamp: 'nk 2/10/2002 11:57'! startUp self installMouseDecodeTable. self installKeyDecodeTable. self default startUp! ! !Preferences class methodsFor: 'standard queries'! swapControlAndAltKeys ^ self valueOfFlag: #swapControlAndAltKeys ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! swapMouseButtons ^ self valueOfFlag: #swapMouseButtons ifAbsent: [false]! ! InputSensor class removeSelector: #buttonDecodeTable! "Postscript: Add the preference properly, then initialize the InputSensor class. " Preferences addPreference: #swapMouseButtons categories: #(general) default: false balloonHelp: 'if true, swaps mouse buttons 2 and 3' projectLocal: false changeInformee: InputSensor changeSelector: #installMouseDecodeTable . Preferences addPreference: #swapControlAndAltKeys categories: #(general) default: false balloonHelp: 'if true, swaps some control- and alt-keys (making ctrl-c be copy instead of alt-c)' projectLocal: false changeInformee: InputSensor changeSelector: #installKeyDecodeTable . InputSensor startUp. !