93 lines
2.8 KiB
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("")
|
||
|
}
|