[racket] Key events, shift, and, get-shift-key-code

From: Jens Axel Søgaard (jensaxel at soegaard.net)
Date: Thu Jan 1 19:51:33 EST 2015

2014-12-24 16:57 GMT+01:00 Robby Findler <robby at eecs.northwestern.edu>:
> I believe that "other-shift-key-code" is really just a field with
> getters and setters; there's no smarts in the key-event class that can
> do the translation you want.

> It may be possible to do this via calls directly to the os, but I'm
> not sure how to do that and I've never had much luck reading the cocoa
> docs, I'm sorry to say. It might help to look at the code inside
> racket/gui that constructs the key-event; it's in the collection
> mred/private/wx/cocoa.

I'll see what I can do with respect to an FFI. I had a bit of trouble
getting simple example working directly in Swift, but I have finally
figured it out.

The output is:

  Keyboard: <TSMInputSource 0x1005139a0> KB Layout: U.S. (id=0)
  Layout: 0x0000000100812830
  KbdType 44
  Status: 0
  Out:>
  Done
  Program ended with exit code: 0



import Foundation
import Cocoa
import Carbon
import AppKit

// The current text input source (read keyboard) has a layout in which
// we can lookup how key-codes are resolved.

// Get keyboard using the current layout.
let keyboard = TISCopyCurrentKeyboardInputSource().takeRetainedValue()
let rawLayoutData = TISGetInputSourceProperty(keyboard,
kTISPropertyUnicodeKeyLayoutData)
print("Keyboard: ") ; println(keyboard)

// Get the layout
var layoutData      = unsafeBitCast(rawLayoutData, CFDataRef.self)
var layout: UnsafePointer<UCKeyboardLayout> =
unsafeBitCast(CFDataGetBytePtr(layoutData),
UnsafePointer<UCKeyboardLayout>.self)
print("Layout: "); println(layout)
print("KbdType "); println(LMGetKbdType()) // Sanity check (prints 44)

// As an example, let's figure out what <shift>+<period> is:

var keycode             = UInt16(kVK_ANSI_Period)
   // Keycode for a
var keyaction           = UInt16(kUCKeyActionDisplay)
var modifierKeyState    = UInt32(1 << 1)
   // Shift
var keyboardType        = UInt32(LMGetKbdType())
var keyTranslateOptions = OptionBits(kUCKeyTranslateNoDeadKeysBit)
var deadKeyState        = UInt32(0)
   // Is 0 the correct value?
var maxStringLength     = UniCharCount(4)
   // uint32
var chars: [UniChar]    = [0,0,0,0]
var actualStringLength  = UniCharCount(1)
var result = UCKeyTranslate(layout, keycode, keyaction,
modifierKeyState, keyboardType, keyTranslateOptions,
                            &deadKeyState, maxStringLength,
&actualStringLength, &chars)

// Print the results
print("Status: "); println(result)
print("Out:"); println(UnicodeScalar(chars[0]))
println("Done")

Posted on the users mailing list.