X11: Cleanup code

This commit is contained in:
Unrud 2026-08-03 00:32:33 +02:00
parent 6ef2be8776
commit 346d9cf375

View file

@ -47,9 +47,13 @@ const (
scrollDiv int = 20 scrollDiv int = 20
) )
var modifierIndices [6]uint = [...]uint{ var modifierIndexes = [...]int{
C.ShiftMapIndex, C.Mod1MapIndex, C.ShiftMapIndex,
C.Mod2MapIndex, C.Mod3MapIndex, C.Mod4MapIndex, C.Mod5MapIndex, C.Mod1MapIndex,
C.Mod2MapIndex,
C.Mod3MapIndex,
C.Mod4MapIndex,
C.Mod5MapIndex,
} }
type x11Controller struct { type x11Controller struct {
@ -118,41 +122,52 @@ func (p *x11Controller) Close() error {
return nil return nil
} }
func (p *x11Controller) findEmptyKeycodeLocked() (C.KeyCode, C.int, error) { func (p *x11Controller) findEmptyKeycodeLocked() (keycode C.KeyCode, keysymsPerKeycode int, err error) {
var minKeycodes, maxKeycodes C.int var minKeycodes, maxKeycodes C.int
C.XDisplayKeycodes(p.display, &minKeycodes, &maxKeycodes) C.XDisplayKeycodes(p.display, &minKeycodes, &maxKeycodes)
var keysymsPerKeycode C.int var keysymsPerKeycodeC C.int
keysyms := C.XGetKeyboardMapping(p.display, C.KeyCode(minKeycodes), keysyms := C.XGetKeyboardMapping(
maxKeycodes-minKeycodes+1, &keysymsPerKeycode) p.display,
C.KeyCode(minKeycodes),
maxKeycodes-minKeycodes+1,
&keysymsPerKeycodeC,
)
if keysyms == nil { if keysyms == nil {
return 0, 0, errors.New("failed to get keyboard mapping") return 0, 0, errors.New("failed to get keyboard mapping")
} }
defer C.XFree(unsafe.Pointer(keysyms)) defer C.XFree(unsafe.Pointer(keysyms))
keysymsPerKeycode = int(keysymsPerKeycodeC)
keycodes: keycodes:
for keycode := C.KeyCode(minKeycodes); keycode <= C.KeyCode(maxKeycodes); keycode++ { for keycode := int(minKeycodes); keycode <= int(maxKeycodes); keycode++ {
for i := range int(keysymsPerKeycode) { for i := range keysymsPerKeycode {
keysymsIndex := int(keycode- keysymsIndex := (keycode-int(minKeycodes))*keysymsPerKeycode + i
C.KeyCode(minKeycodes))*int(keysymsPerKeycode) + i keysym := *(*C.KeySym)(unsafe.Pointer(
keysym := *(*C.KeySym)(unsafe.Pointer(uintptr(unsafe.Pointer(keysyms)) + uintptr(unsafe.Pointer(keysyms)) +
uintptr(keysymsIndex)*unsafe.Sizeof(*keysyms))) uintptr(keysymsIndex)*unsafe.Sizeof(*keysyms),
))
if keysym != 0 { if keysym != 0 {
continue keycodes continue keycodes
} }
} }
return keycode, keysymsPerKeycode, nil return C.KeyCode(keycode), keysymsPerKeycode, nil
} }
return 0, 0, errors.New("no empty keycode found") return 0, 0, errors.New("no empty keycode found")
} }
func (p *x11Controller) changeKeyMappingLocked(keysymsPerKeycode C.int, func (p *x11Controller) changeKeyMappingLocked(
keycode C.KeyCode, keysym Keysym, keycode C.KeyCode, keysymsPerKeycode int, keysym Keysym,
) { ) {
keycodeMapping := make([]C.KeySym, keysymsPerKeycode) keycodeMapping := make([]C.KeySym, keysymsPerKeycode)
for i := range keycodeMapping { for i := range keycodeMapping {
keycodeMapping[i] = C.KeySym(keysym) keycodeMapping[i] = C.KeySym(keysym)
} }
C.XChangeKeyboardMapping(p.display, C.int(keycode), keysymsPerKeycode, C.XChangeKeyboardMapping(
(*C.KeySym)(unsafe.Pointer(&keycodeMapping[0])), 1) p.display,
C.int(keycode),
C.int(keysymsPerKeycode),
(*C.KeySym)(unsafe.Pointer(&keycodeMapping[0])),
1,
)
C.XSync(p.display, C.False) C.XSync(p.display, C.False)
} }
@ -160,12 +175,15 @@ func (p *x11Controller) getModKeycodesLocked() map[uint]C.KeyCode {
modKeymap := C.XGetModifierMapping(p.display) modKeymap := C.XGetModifierMapping(p.display)
defer C.XFreeModifiermap(modKeymap) defer C.XFreeModifiermap(modKeymap)
modKeycodes := make(map[uint]C.KeyCode) modKeycodes := make(map[uint]C.KeyCode)
for _, modIndex := range modifierIndices { for _, modIndex := range modifierIndexes {
for i := range int(modKeymap.max_keypermod) { for i := range int(modKeymap.max_keypermod) {
keycode := *(*C.KeyCode)(unsafe.Pointer(uintptr(unsafe.Pointer(modKeymap.modifiermap)) + keycodeIndex := modIndex*int(modKeymap.max_keypermod) + i
uintptr(uint(modIndex)*uint(modKeymap.max_keypermod)+uint(i)))) keycode := *(*C.KeyCode)(unsafe.Pointer(
uintptr(unsafe.Pointer(modKeymap.modifiermap)) +
uintptr(keycodeIndex)*unsafe.Sizeof(*modKeymap.modifiermap),
))
if keycode != 0 { if keycode != 0 {
modKeycodes[1<<uint(modIndex)] = keycode modKeycodes[1<<modIndex] = keycode
break break
} }
} }
@ -173,35 +191,34 @@ func (p *x11Controller) getModKeycodesLocked() map[uint]C.KeyCode {
return modKeycodes return modKeycodes
} }
func (p *x11Controller) findKeycodeLocked(keyboard C.XkbDescPtr, func (p *x11Controller) findKeycodeLocked(
modKeycodes map[uint]C.KeyCode, activeMods C.uint, keyboard C.XkbDescPtr, modKeycodes map[uint]C.KeyCode, activeMods uint, keysym Keysym,
keysym Keysym, ) (keycode C.KeyCode, mods uint) {
) (C.KeyCode, C.uint) { keycode = C.XKeysymToKeycode(p.display, C.KeySym(keysym))
keycode := C.XKeysymToKeycode(p.display, C.KeySym(keysym))
if keycode == 0 { if keycode == 0 {
return 0, 0 return 0, 0
} }
var alwaysActiveMods C.uint var alwaysActiveMods uint
for modIndex := uint(0); modIndex < 8; modIndex++ { for _, modIndex := range modifierIndexes {
mod := uint(1) << modIndex mod := uint(1) << modIndex
if _, modAvailable := modKeycodes[mod]; !modAvailable { if _, modAvailable := modKeycodes[mod]; !modAvailable {
alwaysActiveMods |= activeMods & C.uint(mod) alwaysActiveMods |= activeMods & mod
} }
} }
_, shiftModAvailable := modKeycodes[C.ShiftMask] _, shiftModAvailable := modKeycodes[C.ShiftMask]
for _, modIndex := range modifierIndices { for _, modIndex := range modifierIndexes {
var mod C.uint var mod uint
if modIndex != C.ShiftMapIndex { if modIndex != C.ShiftMapIndex {
mod = 1 << modIndex mod = 1 << modIndex
} }
for _, shiftMod := range [...]C.uint{0, C.ShiftMask} { for _, shiftMod := range [...]uint{0, C.ShiftMask} {
if shiftMod != 0 && !shiftModAvailable { if shiftMod != 0 && !shiftModAvailable {
continue continue
} }
mods := alwaysActiveMods | shiftMod | mod mods := alwaysActiveMods | shiftMod | mod
var retMods C.uint var retMods C.uint
var retKeysym C.KeySym var retKeysym C.KeySym
C.XkbTranslateKeyCode(keyboard, keycode, mods, &retMods, &retKeysym) C.XkbTranslateKeyCode(keyboard, keycode, C.uint(mods), &retMods, &retKeysym)
if retKeysym == C.KeySym(keysym) { if retKeysym == C.KeySym(keysym) {
return keycode, mods return keycode, mods
} }
@ -210,15 +227,15 @@ func (p *x11Controller) findKeycodeLocked(keyboard C.XkbDescPtr,
return 0, 0 return 0, 0
} }
func (p *x11Controller) sendModsLocked(modKeycodes map[uint]C.KeyCode, mods C.uint, func (p *x11Controller) sendModsLocked(
press bool, modKeycodes map[uint]C.KeyCode, mods uint, press bool,
) { ) {
var pressC C.int = C.False var pressC C.int = C.False
if press { if press {
pressC = C.True pressC = C.True
} }
for mod, keycode := range modKeycodes { for mod, keycode := range modKeycodes {
if mods&C.uint(mod) != 0 { if mods&mod != 0 {
C.XTestFakeKeyEvent(p.display, C.uint(keycode), pressC, 0) C.XTestFakeKeyEvent(p.display, C.uint(keycode), pressC, 0)
} }
} }
@ -239,16 +256,22 @@ func (p *x11Controller) keyboardKeys(keys []Keysym) error {
C.XkbCompatMapMask|C.XkbGeometryMask, C.XkbUseCoreKbd) C.XkbCompatMapMask|C.XkbGeometryMask, C.XkbUseCoreKbd)
defer C.XkbFreeKeyboard(keyboard, C.XkbAllComponentsMask, C.True) defer C.XkbFreeKeyboard(keyboard, C.XkbAllComponentsMask, C.True)
var emptyKeycode C.KeyCode var emptyKeycode C.KeyCode
var keysymsPerKeycode C.int var keysymsPerKeycode int
for _, keysym := range keys { for _, keysym := range keys {
var root, child C.Window var root, child C.Window
var rootX, rootY, x, y C.int var rootX, rootY, x, y C.int
var activeMods C.uint var activeModsC C.uint
C.XQueryPointer(p.display, rootWindow, &root, &child, &rootX, &rootY, C.XQueryPointer(
&x, &y, &activeMods) p.display,
keycode, mods := p.findKeycodeLocked(keyboard, modKeycodes, activeMods, rootWindow,
keysym) &root, &child,
var pressMods, releaseMods C.uint &rootX, &rootY,
&x, &y,
&activeModsC,
)
activeMods := uint(activeModsC)
keycode, mods := p.findKeycodeLocked(keyboard, modKeycodes, activeMods, keysym)
var pressMods, releaseMods uint
if keycode == 0 { if keycode == 0 {
if emptyKeycode == 0 { if emptyKeycode == 0 {
var err error var err error
@ -256,10 +279,10 @@ func (p *x11Controller) keyboardKeys(keys []Keysym) error {
if err != nil { if err != nil {
return err return err
} }
defer p.changeKeyMappingLocked(keysymsPerKeycode, emptyKeycode, 0) defer p.changeKeyMappingLocked(emptyKeycode, keysymsPerKeycode, 0)
} }
keycode = emptyKeycode keycode = emptyKeycode
p.changeKeyMappingLocked(keysymsPerKeycode, keycode, keysym) p.changeKeyMappingLocked(keycode, keysymsPerKeycode, keysym)
// race condition! // race condition!
time.Sleep(keyboardMappingDelay) time.Sleep(keyboardMappingDelay)
} else { } else {