github.com/as/shiny@v0.8.2/driver/internal/x11key/x11key.go (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // x11key contains X11 numeric codes for the keyboard and mouse.
     6  package x11key // import "github.com/as/shiny/driver/internal/x11key"
     7  
     8  import (
     9  	"github.com/as/shiny/event/key"
    10  )
    11  
    12  // These constants come from /usr/include/X11/X.h
    13  const (
    14  	ShiftMask   = 1 << 0
    15  	LockMask    = 1 << 1
    16  	ControlMask = 1 << 2
    17  	Mod1Mask    = 1 << 3
    18  	Mod2Mask    = 1 << 4
    19  	Mod3Mask    = 1 << 5
    20  	Mod4Mask    = 1 << 6
    21  	Mod5Mask    = 1 << 7
    22  	Button1Mask = 1 << 8
    23  	Button2Mask = 1 << 9
    24  	Button3Mask = 1 << 10
    25  	Button4Mask = 1 << 11
    26  	Button5Mask = 1 << 12
    27  )
    28  
    29  type KeysymTable [256][2]uint32
    30  
    31  func (t *KeysymTable) Lookup(detail uint8, state uint16) (rune, key.Code) {
    32  	// The key event's rune depends on whether the shift key is down.
    33  	unshifted := rune(t[detail][0])
    34  	r := unshifted
    35  	if state&ShiftMask != 0 {
    36  		r = rune(t[detail][1])
    37  		// In X11, a zero keysym when shift is down means to use what the
    38  		// keysym is when shift is up.
    39  		if r == 0 {
    40  			r = unshifted
    41  		}
    42  	}
    43  
    44  	// The key event's code is independent of whether the shift key is down.
    45  	var c key.Code
    46  	if 0 <= unshifted && unshifted < 0x80 {
    47  		// TODO: distinguish the regular '2' key and number-pad '2' key (with
    48  		// Num-Lock).
    49  		c = asciiKeycodes[unshifted]
    50  	} else {
    51  		r, c = -1, nonUnicodeKeycodes[unshifted]
    52  	}
    53  
    54  	if state&ControlMask != 0 {
    55  		switch r {
    56  		case 'u':
    57  			r = '\x15'
    58  		case 'a':
    59  			r = '\x01'
    60  		case 'e':
    61  			r = '\x05'
    62  		case 'w':
    63  			r = '\x17'
    64  		}
    65  	}
    66  
    67  	// TODO: Unicode-but-not-ASCII keysyms like the Swiss keyboard's 'รถ'.
    68  	return r, c
    69  }
    70  
    71  func KeyModifiers(state uint16) (m key.Modifiers) {
    72  	if state&ShiftMask != 0 {
    73  		m |= key.ModShift
    74  	}
    75  	if state&ControlMask != 0 {
    76  		m |= key.ModControl
    77  	}
    78  	if state&Mod1Mask != 0 {
    79  		m |= key.ModAlt
    80  	}
    81  	if state&Mod4Mask != 0 {
    82  		m |= key.ModMeta
    83  	}
    84  	return m
    85  }
    86  
    87  // These constants come from /usr/include/X11/{keysymdef,XF86keysym}.h
    88  const (
    89  	xkISOLeftTab = 0xfe20
    90  	xkBackSpace  = 0xff08
    91  	xkTab        = 0xff09
    92  	xkReturn     = 0xff0d
    93  	xkEscape     = 0xff1b
    94  	xkMultiKey   = 0xff20
    95  	xkHome       = 0xff50
    96  	xkLeft       = 0xff51
    97  	xkUp         = 0xff52
    98  	xkRight      = 0xff53
    99  	xkDown       = 0xff54
   100  	xkPageUp     = 0xff55
   101  	xkPageDown   = 0xff56
   102  	xkEnd        = 0xff57
   103  	xkInsert     = 0xff63
   104  	xkMenu       = 0xff67
   105  	xkF1         = 0xffbe
   106  	xkF2         = 0xffbf
   107  	xkF3         = 0xffc0
   108  	xkF4         = 0xffc1
   109  	xkF5         = 0xffc2
   110  	xkF6         = 0xffc3
   111  	xkF7         = 0xffc4
   112  	xkF8         = 0xffc5
   113  	xkF9         = 0xffc6
   114  	xkF10        = 0xffc7
   115  	xkF11        = 0xffc8
   116  	xkF12        = 0xffc9
   117  	xkShiftL     = 0xffe1
   118  	xkShiftR     = 0xffe2
   119  	xkControlL   = 0xffe3
   120  	xkControlR   = 0xffe4
   121  	xkAltL       = 0xffe9
   122  	xkAltR       = 0xffea
   123  	xkSuperL     = 0xffeb
   124  	xkSuperR     = 0xffec
   125  	xkDelete     = 0xffff
   126  
   127  	xf86xkAudioLowerVolume = 0x1008ff11
   128  	xf86xkAudioMute        = 0x1008ff12
   129  	xf86xkAudioRaiseVolume = 0x1008ff13
   130  )
   131  
   132  // nonUnicodeKeycodes maps from those xproto.Keysym values (converted to runes)
   133  // that do not correspond to a Unicode code point, such as "Page Up", "F1" or
   134  // "Left Shift", to key.Code values.
   135  var nonUnicodeKeycodes = map[rune]key.Code{
   136  	xkISOLeftTab: key.CodeTab,
   137  	xkBackSpace:  key.CodeDeleteBackspace,
   138  	xkTab:        key.CodeTab,
   139  	xkReturn:     key.CodeReturnEnter,
   140  	xkEscape:     key.CodeEscape,
   141  	xkHome:       key.CodeHome,
   142  	xkLeft:       key.CodeLeftArrow,
   143  	xkUp:         key.CodeUpArrow,
   144  	xkRight:      key.CodeRightArrow,
   145  	xkDown:       key.CodeDownArrow,
   146  	xkPageUp:     key.CodePageUp,
   147  	xkPageDown:   key.CodePageDown,
   148  	xkEnd:        key.CodeEnd,
   149  	xkInsert:     key.CodeInsert,
   150  	xkMenu:       key.CodeRightGUI, // TODO: CodeRightGUI or CodeMenu??
   151  	xkMultiKey:   key.CodeCompose,
   152  
   153  	xkF1:  key.CodeF1,
   154  	xkF2:  key.CodeF2,
   155  	xkF3:  key.CodeF3,
   156  	xkF4:  key.CodeF4,
   157  	xkF5:  key.CodeF5,
   158  	xkF6:  key.CodeF6,
   159  	xkF7:  key.CodeF7,
   160  	xkF8:  key.CodeF8,
   161  	xkF9:  key.CodeF9,
   162  	xkF10: key.CodeF10,
   163  	xkF11: key.CodeF11,
   164  	xkF12: key.CodeF12,
   165  
   166  	xkShiftL:   key.CodeLeftShift,
   167  	xkShiftR:   key.CodeRightShift,
   168  	xkControlL: key.CodeLeftControl,
   169  	xkControlR: key.CodeRightControl,
   170  	xkAltL:     key.CodeLeftAlt,
   171  	xkAltR:     key.CodeRightAlt,
   172  	xkSuperL:   key.CodeLeftGUI,
   173  	xkSuperR:   key.CodeRightGUI,
   174  
   175  	xkDelete: key.CodeDeleteForward,
   176  
   177  	xf86xkAudioRaiseVolume: key.CodeVolumeUp,
   178  	xf86xkAudioLowerVolume: key.CodeVolumeDown,
   179  	xf86xkAudioMute:        key.CodeMute,
   180  }
   181  
   182  // asciiKeycodes maps lower-case ASCII runes to key.Code values.
   183  var asciiKeycodes = [0x80]key.Code{
   184  	'a': key.CodeA,
   185  	'b': key.CodeB,
   186  	'c': key.CodeC,
   187  	'd': key.CodeD,
   188  	'e': key.CodeE,
   189  	'f': key.CodeF,
   190  	'g': key.CodeG,
   191  	'h': key.CodeH,
   192  	'i': key.CodeI,
   193  	'j': key.CodeJ,
   194  	'k': key.CodeK,
   195  	'l': key.CodeL,
   196  	'm': key.CodeM,
   197  	'n': key.CodeN,
   198  	'o': key.CodeO,
   199  	'p': key.CodeP,
   200  	'q': key.CodeQ,
   201  	'r': key.CodeR,
   202  	's': key.CodeS,
   203  	't': key.CodeT,
   204  	'u': key.CodeU,
   205  	'v': key.CodeV,
   206  	'w': key.CodeW,
   207  	'x': key.CodeX,
   208  	'y': key.CodeY,
   209  	'z': key.CodeZ,
   210  
   211  	'1': key.Code1,
   212  	'2': key.Code2,
   213  	'3': key.Code3,
   214  	'4': key.Code4,
   215  	'5': key.Code5,
   216  	'6': key.Code6,
   217  	'7': key.Code7,
   218  	'8': key.Code8,
   219  	'9': key.Code9,
   220  	'0': key.Code0,
   221  
   222  	' ':  key.CodeSpacebar,
   223  	'-':  key.CodeHyphenMinus,
   224  	'=':  key.CodeEqualSign,
   225  	'[':  key.CodeLeftSquareBracket,
   226  	']':  key.CodeRightSquareBracket,
   227  	'\\': key.CodeBackslash,
   228  	';':  key.CodeSemicolon,
   229  	'\'': key.CodeApostrophe,
   230  	'`':  key.CodeGraveAccent,
   231  	',':  key.CodeComma,
   232  	'.':  key.CodeFullStop,
   233  	'/':  key.CodeSlash,
   234  
   235  	// TODO: distinguish CodeKeypadSlash vs CodeSlash, and similarly for other
   236  	// keypad codes.
   237  }