shiny: support AltGr under X11
Supports key combinations involving AltGr.
Change-Id: Ib431d31dad9493b7ced7192e4b5157b6a2dfcd40
Reviewed-on: https://go-review.googlesource.com/c/exp/+/192778
Reviewed-by: Nigel Tao <nigeltao@golang.org>
diff --git a/shiny/driver/gldriver/x11.go b/shiny/driver/gldriver/x11.go
index f73098d..7aaeaff 100644
--- a/shiny/driver/gldriver/x11.go
+++ b/shiny/driver/gldriver/x11.go
@@ -194,8 +194,8 @@
//export onKeysym
func onKeysym(k, unshifted, shifted uint32) {
- theKeysyms[k][0] = unshifted
- theKeysyms[k][1] = shifted
+ theKeysyms.Table[k][0] = unshifted
+ theKeysyms.Table[k][1] = shifted
}
//export onKey
@@ -208,7 +208,7 @@
return
}
- r, c := theKeysyms.Lookup(detail, state, 0)
+ r, c := theKeysyms.Lookup(detail, state)
w.Send(key.Event{
Rune: r,
Code: c,
diff --git a/shiny/driver/internal/x11key/x11key.go b/shiny/driver/internal/x11key/x11key.go
index b916a44..546d463 100644
--- a/shiny/driver/internal/x11key/x11key.go
+++ b/shiny/driver/internal/x11key/x11key.go
@@ -30,18 +30,30 @@
Button5Mask = 1 << 12
)
-type KeysymTable [256][2]uint32
+type KeysymTable struct {
+ Table [256][6]uint32
-func (t *KeysymTable) Lookup(detail uint8, state uint16, numLockMod uint16) (rune, key.Code) {
+ 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(t[detail][0])
+ unshifted := rune(te[0])
r := unshifted
- if state&numLockMod != 0 && isKeypad(t[detail][1]) {
+ if state&t.NumLockMod != 0 && isKeypad(te[1]) {
if state&ShiftMask == 0 {
- r = rune(t[detail][1])
+ r = rune(te[1])
}
} else if state&ShiftMask != 0 {
- r = rune(t[detail][1])
+ 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 {
diff --git a/shiny/driver/x11driver/screen.go b/shiny/driver/x11driver/screen.go
index c734797..7e0d3bb 100644
--- a/shiny/driver/x11driver/screen.go
+++ b/shiny/driver/x11driver/screen.go
@@ -33,8 +33,6 @@
xsi *xproto.ScreenInfo
keysyms x11key.KeysymTable
- numLockMod uint16
-
atomNETWMName xproto.Atom
atomUTF8String xproto.Atom
atomWMDeleteWindow xproto.Atom
@@ -496,8 +494,13 @@
return fmt.Errorf("x11driver: too few keysyms per keycode: %d", n)
}
for i := keyLo; i <= keyHi; i++ {
- s.keysyms[i][0] = uint32(km.Keysyms[(i-keyLo)*n+0])
- s.keysyms[i][1] = uint32(km.Keysyms[(i-keyLo)*n+1])
+ for j := 0; j < 6; j++ {
+ if j < n {
+ s.keysyms.Table[i][j] = uint32(km.Keysyms[(i-keyLo)*n+j])
+ } else {
+ s.keysyms.Table[i][j] = 0
+ }
+ }
}
// Figure out which modifier is the numlock modifier (see chapter 12.7 of the XLib Manual).
@@ -505,12 +508,30 @@
if err != nil {
return err
}
+ s.keysyms.NumLockMod, s.keysyms.ModeSwitchMod, s.keysyms.ISOLevel3ShiftMod = 0, 0, 0
+ numLockFound, modeSwitchFound, isoLevel3ShiftFound := false, false, false
+modifierSearchLoop:
for modifier := 0; modifier < 8; modifier++ {
for i := 0; i < int(mm.KeycodesPerModifier); i++ {
- const xkNumLock = 0xff7f // XK_Num_Lock from /usr/include/X11/keysymdef.h.
- if s.keysyms[mm.Keycodes[modifier*int(mm.KeycodesPerModifier)+i]][0] == xkNumLock {
- s.numLockMod = 1 << uint(modifier)
- break
+ const (
+ // XK_Num_Lock, XK_Mode_switch and XK_ISO_Level3_Shift from /usr/include/X11/keysymdef.h.
+ xkNumLock = 0xff7f
+ xkModeSwitch = 0xff7e
+ xkISOLevel3Shift = 0xfe03
+ )
+ switch s.keysyms.Table[mm.Keycodes[modifier*int(mm.KeycodesPerModifier)+i]][0] {
+ case xkNumLock:
+ s.keysyms.NumLockMod = 1 << uint(modifier)
+ numLockFound = true
+ case xkModeSwitch:
+ s.keysyms.ModeSwitchMod = 1 << uint(modifier)
+ modeSwitchFound = true
+ case xkISOLevel3Shift:
+ s.keysyms.ISOLevel3ShiftMod = 1 << uint(modifier)
+ isoLevel3ShiftFound = true
+ }
+ if numLockFound && modeSwitchFound && isoLevel3ShiftFound {
+ break modifierSearchLoop
}
}
}
diff --git a/shiny/driver/x11driver/window.go b/shiny/driver/x11driver/window.go
index cf0c6fa..5ebdbcd 100644
--- a/shiny/driver/x11driver/window.go
+++ b/shiny/driver/x11driver/window.go
@@ -131,7 +131,7 @@
}
func (w *windowImpl) handleKey(detail xproto.Keycode, state uint16, dir key.Direction) {
- r, c := w.s.keysyms.Lookup(uint8(detail), state, w.s.numLockMod)
+ r, c := w.s.keysyms.Lookup(uint8(detail), state)
w.Send(key.Event{
Rune: r,
Code: c,