blob: 546d4630633caa54a31d9d353b8d7b57e3c382cd [file] [log] [blame]
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:generate go run gen.go
// x11key contains X11 numeric codes for the keyboard and mouse.
package x11key // import "golang.org/x/exp/shiny/driver/internal/x11key"
import (
"unicode"
"golang.org/x/mobile/event/key"
)
// These constants come from /usr/include/X11/X.h
const (
ShiftMask = 1 << 0
LockMask = 1 << 1
ControlMask = 1 << 2
Mod1Mask = 1 << 3
Mod2Mask = 1 << 4
Mod3Mask = 1 << 5
Mod4Mask = 1 << 6
Mod5Mask = 1 << 7
Button1Mask = 1 << 8
Button2Mask = 1 << 9
Button3Mask = 1 << 10
Button4Mask = 1 << 11
Button5Mask = 1 << 12
)
type KeysymTable struct {
Table [256][6]uint32
NumLockMod, ModeSwitchMod, ISOLevel3ShiftMod uint16
}
func (t *KeysymTable) Lookup(detail uint8, state uint16) (rune, key.Code) {
te := t.Table[detail][0:2]
if state&t.ModeSwitchMod != 0 {
te = t.Table[detail][2:4]
}
if state&t.ISOLevel3ShiftMod != 0 {
te = t.Table[detail][4:6]
}
// The key event's rune depends on whether the shift key is down.
unshifted := rune(te[0])
r := unshifted
if state&t.NumLockMod != 0 && isKeypad(te[1]) {
if state&ShiftMask == 0 {
r = rune(te[1])
}
} else if state&ShiftMask != 0 {
r = rune(te[1])
// In X11, a zero keysym when shift is down means to use what the
// keysym is when shift is up.
if r == 0 {
r = unshifted
}
}
// The key event's code is independent of whether the shift key is down.
var c key.Code
if 0 <= unshifted && unshifted < 0x80 {
c = asciiKeycodes[unshifted]
if state&LockMask != 0 {
r = unicode.ToUpper(r)
}
} else if kk, isKeypad := keypadKeysyms[r]; isKeypad {
r, c = kk.rune, kk.code
} else if nuk := nonUnicodeKeycodes[unshifted]; nuk != key.CodeUnknown {
r, c = -1, nuk
} else {
r = keysymCodePoints[r]
if state&LockMask != 0 {
r = unicode.ToUpper(r)
}
}
return r, c
}
func isKeypad(keysym uint32) bool {
return keysym >= 0xff80 && keysym <= 0xffbd
}
func KeyModifiers(state uint16) (m key.Modifiers) {
if state&ShiftMask != 0 {
m |= key.ModShift
}
if state&ControlMask != 0 {
m |= key.ModControl
}
if state&Mod1Mask != 0 {
m |= key.ModAlt
}
if state&Mod4Mask != 0 {
m |= key.ModMeta
}
return m
}
// These constants come from /usr/include/X11/{keysymdef,XF86keysym}.h
const (
xkISOLeftTab = 0xfe20
xkBackSpace = 0xff08
xkTab = 0xff09
xkReturn = 0xff0d
xkEscape = 0xff1b
xkMultiKey = 0xff20
xkHome = 0xff50
xkLeft = 0xff51
xkUp = 0xff52
xkRight = 0xff53
xkDown = 0xff54
xkPageUp = 0xff55
xkPageDown = 0xff56
xkEnd = 0xff57
xkInsert = 0xff63
xkMenu = 0xff67
xkHelp = 0xff6a
xkNumLock = 0xff7f
xkKeypadEnter = 0xff8d
xkKeypadHome = 0xff95
xkKeypadLeft = 0xff96
xkKeypadUp = 0xff97
xkKeypadRight = 0xff98
xkKeypadDown = 0xff99
xkKeypadPageUp = 0xff9a
xkKeypadPageDown = 0xff9b
xkKeypadEnd = 0xff9c
xkKeypadInsert = 0xff9e
xkKeypadDelete = 0xff9f
xkKeypadEqual = 0xffbd
xkKeypadMultiply = 0xffaa
xkKeypadAdd = 0xffab
xkKeypadSubtract = 0xffad
xkKeypadDecimal = 0xffae
xkKeypadDivide = 0xffaf
xkKeypad0 = 0xffb0
xkKeypad1 = 0xffb1
xkKeypad2 = 0xffb2
xkKeypad3 = 0xffb3
xkKeypad4 = 0xffb4
xkKeypad5 = 0xffb5
xkKeypad6 = 0xffb6
xkKeypad7 = 0xffb7
xkKeypad8 = 0xffb8
xkKeypad9 = 0xffb9
xkF1 = 0xffbe
xkF2 = 0xffbf
xkF3 = 0xffc0
xkF4 = 0xffc1
xkF5 = 0xffc2
xkF6 = 0xffc3
xkF7 = 0xffc4
xkF8 = 0xffc5
xkF9 = 0xffc6
xkF10 = 0xffc7
xkF11 = 0xffc8
xkF12 = 0xffc9
xkShiftL = 0xffe1
xkShiftR = 0xffe2
xkControlL = 0xffe3
xkControlR = 0xffe4
xkCapsLock = 0xffe5
xkAltL = 0xffe9
xkAltR = 0xffea
xkSuperL = 0xffeb
xkSuperR = 0xffec
xkDelete = 0xffff
xf86xkAudioLowerVolume = 0x1008ff11
xf86xkAudioMute = 0x1008ff12
xf86xkAudioRaiseVolume = 0x1008ff13
)
// nonUnicodeKeycodes maps from those xproto.Keysym values (converted to runes)
// that do not correspond to a Unicode code point, such as "Page Up", "F1" or
// "Left Shift", to key.Code values.
var nonUnicodeKeycodes = map[rune]key.Code{
xkISOLeftTab: key.CodeTab,
xkBackSpace: key.CodeDeleteBackspace,
xkTab: key.CodeTab,
xkReturn: key.CodeReturnEnter,
xkEscape: key.CodeEscape,
xkHome: key.CodeHome,
xkLeft: key.CodeLeftArrow,
xkUp: key.CodeUpArrow,
xkRight: key.CodeRightArrow,
xkDown: key.CodeDownArrow,
xkPageUp: key.CodePageUp,
xkPageDown: key.CodePageDown,
xkEnd: key.CodeEnd,
xkInsert: key.CodeInsert,
xkMenu: key.CodeRightGUI, // TODO: CodeRightGUI or CodeMenu??
xkHelp: key.CodeHelp,
xkNumLock: key.CodeKeypadNumLock,
xkMultiKey: key.CodeCompose,
xkKeypadEnter: key.CodeKeypadEnter,
xkKeypadHome: key.CodeHome,
xkKeypadLeft: key.CodeLeftArrow,
xkKeypadUp: key.CodeUpArrow,
xkKeypadRight: key.CodeRightArrow,
xkKeypadDown: key.CodeDownArrow,
xkKeypadPageUp: key.CodePageUp,
xkKeypadPageDown: key.CodePageDown,
xkKeypadEnd: key.CodeEnd,
xkKeypadInsert: key.CodeInsert,
xkKeypadDelete: key.CodeDeleteForward,
xkF1: key.CodeF1,
xkF2: key.CodeF2,
xkF3: key.CodeF3,
xkF4: key.CodeF4,
xkF5: key.CodeF5,
xkF6: key.CodeF6,
xkF7: key.CodeF7,
xkF8: key.CodeF8,
xkF9: key.CodeF9,
xkF10: key.CodeF10,
xkF11: key.CodeF11,
xkF12: key.CodeF12,
xkShiftL: key.CodeLeftShift,
xkShiftR: key.CodeRightShift,
xkControlL: key.CodeLeftControl,
xkControlR: key.CodeRightControl,
xkCapsLock: key.CodeCapsLock,
xkAltL: key.CodeLeftAlt,
xkAltR: key.CodeRightAlt,
xkSuperL: key.CodeLeftGUI,
xkSuperR: key.CodeRightGUI,
xkDelete: key.CodeDeleteForward,
xf86xkAudioRaiseVolume: key.CodeVolumeUp,
xf86xkAudioLowerVolume: key.CodeVolumeDown,
xf86xkAudioMute: key.CodeMute,
}
// asciiKeycodes maps lower-case ASCII runes to key.Code values.
var asciiKeycodes = [0x80]key.Code{
'a': key.CodeA,
'b': key.CodeB,
'c': key.CodeC,
'd': key.CodeD,
'e': key.CodeE,
'f': key.CodeF,
'g': key.CodeG,
'h': key.CodeH,
'i': key.CodeI,
'j': key.CodeJ,
'k': key.CodeK,
'l': key.CodeL,
'm': key.CodeM,
'n': key.CodeN,
'o': key.CodeO,
'p': key.CodeP,
'q': key.CodeQ,
'r': key.CodeR,
's': key.CodeS,
't': key.CodeT,
'u': key.CodeU,
'v': key.CodeV,
'w': key.CodeW,
'x': key.CodeX,
'y': key.CodeY,
'z': key.CodeZ,
'1': key.Code1,
'2': key.Code2,
'3': key.Code3,
'4': key.Code4,
'5': key.Code5,
'6': key.Code6,
'7': key.Code7,
'8': key.Code8,
'9': key.Code9,
'0': key.Code0,
' ': key.CodeSpacebar,
'-': key.CodeHyphenMinus,
'=': key.CodeEqualSign,
'[': key.CodeLeftSquareBracket,
']': key.CodeRightSquareBracket,
'\\': key.CodeBackslash,
';': key.CodeSemicolon,
'\'': key.CodeApostrophe,
'`': key.CodeGraveAccent,
',': key.CodeComma,
'.': key.CodeFullStop,
'/': key.CodeSlash,
}
type keypadKeysym struct {
rune rune
code key.Code
}
var keypadKeysyms = map[rune]keypadKeysym{
xkKeypadEqual: {'=', key.CodeKeypadEqualSign},
xkKeypadMultiply: {'*', key.CodeKeypadAsterisk},
xkKeypadAdd: {'+', key.CodeKeypadPlusSign},
xkKeypadSubtract: {'-', key.CodeKeypadHyphenMinus},
xkKeypadDecimal: {'.', key.CodeKeypadFullStop},
xkKeypadDivide: {'/', key.CodeKeypadSlash},
xkKeypad0: {'0', key.CodeKeypad0},
xkKeypad1: {'1', key.CodeKeypad1},
xkKeypad2: {'2', key.CodeKeypad2},
xkKeypad3: {'3', key.CodeKeypad3},
xkKeypad4: {'4', key.CodeKeypad4},
xkKeypad5: {'5', key.CodeKeypad5},
xkKeypad6: {'6', key.CodeKeypad6},
xkKeypad7: {'7', key.CodeKeypad7},
xkKeypad8: {'8', key.CodeKeypad8},
xkKeypad9: {'9', key.CodeKeypad9},
}