diff --git a/plugin_x11.go b/plugin_x11.go index ed0a98d..23ff6f6 100644 --- a/plugin_x11.go +++ b/plugin_x11.go @@ -25,6 +25,7 @@ package main // #include // #include // #include +// #include import "C" import ( "errors" @@ -40,6 +41,9 @@ const ( scrollDiv int = 20 ) +var modifierIndices [6]uint = [...]uint{C.ShiftMapIndex, C.Mod1MapIndex, + C.Mod2MapIndex, C.Mod3MapIndex, C.Mod4MapIndex, C.Mod5MapIndex} + type x11Plugin struct { display *C.Display lock sync.Mutex @@ -71,25 +75,16 @@ func (p *x11Plugin) Close() error { return nil } -func (p *x11Plugin) keyboardKeys(keys []Keysym) error { - p.lock.Lock() - defer p.lock.Unlock() - if p.display == nil { - return errors.New("X server connection closed") - } - if len(keys) == 0 { - return nil - } +func (p *x11Plugin) findEmptyKeycodeLocked() (C.KeyCode, C.int, error) { var minKeycodes, maxKeycodes C.int C.XDisplayKeycodes(p.display, &minKeycodes, &maxKeycodes) var keysymsPerKeycode C.int keysyms := C.XGetKeyboardMapping(p.display, C.KeyCode(minKeycodes), maxKeycodes-minKeycodes+1, &keysymsPerKeycode) if keysyms == nil { - return errors.New("failed to get keyboard mapping") + return 0, 0, errors.New("failed to get keyboard mapping") } defer C.XFree(unsafe.Pointer(keysyms)) - emptyKeycode := C.KeyCode(0) keycodes: for keycode := C.KeyCode(minKeycodes); keycode <= C.KeyCode(maxKeycodes); keycode++ { for i := 0; i < int(keysymsPerKeycode); i++ { @@ -101,35 +96,142 @@ keycodes: continue keycodes } } - emptyKeycode = keycode - break - } - if emptyKeycode == 0 { - return errors.New("no empty keycode found") + return keycode, keysymsPerKeycode, nil } + return 0, 0, errors.New("no empty keycode found") +} + +func (p *x11Plugin) changeKeyMappingLocked(keysymsPerKeycode C.int, + keycode C.KeyCode, keysym Keysym) { keycodeMapping := make([]C.KeySym, keysymsPerKeycode) - defer func() { - for i := range keycodeMapping { - keycodeMapping[i] = 0 + for i := range keycodeMapping { + keycodeMapping[i] = C.KeySym(keysym) + } + C.XChangeKeyboardMapping(p.display, C.int(keycode), keysymsPerKeycode, + (*C.KeySym)(unsafe.Pointer(&keycodeMapping[0])), 1) + C.XFlush(p.display) +} + +func (p *x11Plugin) getModKeycodesLocked() map[uint]C.KeyCode { + modKeymap := C.XGetModifierMapping(p.display) + defer C.XFreeModifiermap(modKeymap) + modKeycodes := make(map[uint]C.KeyCode) + for _, modIndex := range modifierIndices { + for i := 0; i < int(modKeymap.max_keypermod); i++ { + keycode := *(*C.KeyCode)(unsafe.Pointer(uintptr(unsafe.Pointer(modKeymap.modifiermap)) + + uintptr(uint(modIndex)*uint(modKeymap.max_keypermod)+uint(i)))) + if keycode != 0 { + modKeycodes[1<