wm/vend/xgbutil/_examples/xmodmap/main.go

93 lines
2.8 KiB
Go

// Example xmodmap shows how one might implement a rudimentary version
// of xmodmap's modifier listing.
// (xmodmap is a program that shows all modifier keys, and which
// keysyms activate each modifier. xmodmap can also modify the modifier
// mapping, which this doesn't do.)
package main
import (
"fmt"
"log"
"strings"
"github.com/jezek/xgb/xproto"
"github.com/jezek/xgbutil"
"github.com/jezek/xgbutil/keybind"
)
func main() {
// Connect to the X server using the DISPLAY environment variable.
X, err := xgbutil.NewConn()
if err != nil {
log.Fatal(err)
}
// Nice names for the modifier keys (same ones used by xmodmap).
// This slice corresponds to the keybind.Modifiers slice (except for
// the last 'Any' modifier element).
nice := []string{
"shift", "lock", "control", "mod1", "mod2", "mod3", "mod4", "mod5",
}
// Whenever one uses the keybind package, Initialize should always be
// called first. In this case, it initializes the key and modifier maps.
keybind.Initialize(X)
// Get the current modifier map.
// The map is actually a table, where rows correspond to modifiers, and
// columns correspond to the keys that activate that modifier.
modMap := keybind.ModMapGet(X)
// The number of keycodes allowed per modifier (i.e., the number of
// columns in the modifier map).
kPerMod := int(modMap.KeycodesPerModifier)
// Get the number of allowable keysyms per keycode.
// This is used to search for a valid keysym for a particular keycode.
symsPerKc := int(keybind.KeyMapGet(X).KeysymsPerKeycode)
// Imitate everything...
fmt.Printf("xmodmap: up to %d keys per modifier, "+
"(keycodes in parentheses):\n\n", kPerMod)
// Iterate through all keyboard modifiers defined in xgb/xproto
// except the 'Any' modifier (which is last).
for mmi := range keybind.Modifiers[:len(keybind.Modifiers)-1] {
niceName := nice[mmi]
keys := make([]string, 0, kPerMod)
// row is the row for the 'mmi' modifier in the modifier mapping table.
row := mmi * kPerMod
// Iterate over each keycode in the modifier map for this modifier.
for _, kc := range modMap.Keycodes[row : row+kPerMod] {
// If this entry doesn't have a keycode (i.e., it's zero), we
// have to skip it.
if kc == 0 {
continue
}
// Look for the first valid keysym in the keyboard map corresponding
// to this keycode. If one can't be found, output "BadKey."
var ksym xproto.Keysym = 0
for column := 0; column < symsPerKc; column++ {
ksym = keybind.KeysymGet(X, kc, byte(column))
if ksym != 0 {
break
}
}
if ksym == 0 {
keys = append(keys, fmt.Sprintf("BadKey (0x%x)", kc))
} else {
keys = append(keys,
fmt.Sprintf("%s (0x%x)", keybind.KeysymToStr(ksym), kc))
}
}
fmt.Printf("%-12s%s\n", niceName, strings.Join(keys, ", "))
}
fmt.Println("")
}