X11: Cleanup code
This commit is contained in:
parent
6ef2be8776
commit
346d9cf375
1 changed files with 69 additions and 46 deletions
|
|
@ -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 {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue