예제 #1
0
// updateMaps runs in response to MappingNotify events.
// It is responsible for making sure our view of the world's keyboard
// and modifier maps is correct. (Pointer mappings should be handled in
// a similar callback in the mousebind package.)
func updateMaps(xu *xgbutil.XUtil, e xevent.MappingNotifyEvent) {
	keyMap, modMap := MapsGet(xu)

	// So we used to go through the old mapping and the new mapping and pick
	// out precisely where there are changes. But after allowing for a
	// one-to-many mapping from keysym to keycodes, this process became too
	// complex. So we're going to bust out our hammer and rebind everything
	// based on the initial key strings.
	if e.Request == xproto.MappingKeyboard {
		// We must ungrab everything first, in case two keys are being swapped.
		keys := keyKeys(xu)
		for _, key := range keys {
			Ungrab(xu, key.Win, key.Mod, key.Code)
			detach(xu, key.Evtype, key.Win)
		}

		// Wipe the slate clean.
		xu.KeybindsLck.Lock()
		xu.Keybinds = make(map[xgbutil.KeyKey][]xgbutil.CallbackKey, len(keys))
		xu.Keygrabs = make(map[xgbutil.KeyKey]int, len(keys))
		keyStrs := xu.Keystrings
		xu.KeybindsLck.Unlock()

		// Update our mappings before rebinding.
		KeyMapSet(xu, keyMap)
		ModMapSet(xu, modMap)

		// Now rebind everything in Keystrings
		for _, ks := range keyStrs {
			err := connect(xu,
				ks.Callback, ks.Evtype, ks.Win, ks.Str, ks.Grab, true)
			if err != nil {
				xgbutil.Logger.Println(err)
			}
		}
	} else {
		// We don't have to do something with MappingModifier like we do with
		// MappingKeyboard. This is due to us requiring that key strings use
		// modifier names built into X. (i.e., the names seen in the output of
		// `xmodmap`.) This means that the modifier mappings happen on the X
		// server side, so we don't *typically* have to care what key is
		// actually being pressed to trigger a modifier. (There are some
		// exceptional cases, and when that happens, we simply query on-demand
		// which keys are modifiers. See the RunKey{Press,Release}Callbacks
		// functions in keybind/callback.go for the deets.)
		KeyMapSet(xu, keyMap)
		ModMapSet(xu, modMap)
	}
}