Пример #1
0
// connect is essentially 'Connect' for either KeyPress or KeyRelease events.
// Namely, it parses the key string, issues a grab request if necessary,
// sets up the appropriate event handlers for the main event loop, and attaches
// the callback to the keybinding state.
func connect(xu *xgbutil.XUtil, callback xgbutil.CallbackKey,
	evtype int, win xproto.Window, keyStr string, grab, reconnect bool) error {

	// Get the mods/key first
	mods, keycodes, err := ParseString(xu, keyStr)
	if err != nil {
		return err
	}

	// Only do the grab if we haven't yet on this window.
	for _, keycode := range keycodes {
		if grab && keyBindGrabs(xu, evtype, win, mods, keycode) == 0 {
			if err := GrabChecked(xu, win, mods, keycode); err != nil {
				// If a bad access, let's be nice and give a good error message.
				switch err.(type) {
				case xproto.AccessError:
					return fmt.Errorf("Got a bad access error when trying to "+
						"bind '%s'. This usually means another client has "+
						"already grabbed this keybinding.", keyStr)
				default:
					return fmt.Errorf("Could not bind '%s' because: %s",
						keyStr, err)
				}
			}
		}

		// If we've never grabbed anything on this window before, we need to
		// make sure we can respond to it in the main event loop.
		// Never do this if we're reconnecting.
		if !reconnect {
			var allCb xgbutil.Callback
			if evtype == xevent.KeyPress {
				allCb = xevent.KeyPressFun(runKeyPressCallbacks)
			} else {
				allCb = xevent.KeyReleaseFun(runKeyReleaseCallbacks)
			}

			// If this is the first Key{Press|Release}Event on this window,
			// then we need to listen to Key{Press|Release} events in the main
			// loop.
			if !connectedKeyBind(xu, evtype, win) {
				allCb.Connect(xu, win)
			}
		}

		// Finally, attach the callback.
		attachKeyBindCallback(xu, evtype, win, mods, keycode, callback)
	}

	// Keep track of all unique key connections.
	if !reconnect {
		addKeyString(xu, callback, evtype, win, keyStr, grab)
	}

	return nil
}
Пример #2
0
// connect is essentially 'Connect' for either ButtonPress or
// ButtonRelease events.
func connect(xu *xgbutil.XUtil, callback xgbutil.CallbackMouse, evtype int,
	win xproto.Window, buttonStr string, sync bool, grab bool) error {

	// Get the mods/button first
	mods, button, err := ParseString(xu, buttonStr)
	if err != nil {
		return err
	}

	// Only do the grab if we haven't yet on this window.
	// And if we WANT a grab...
	if grab && mouseBindGrabs(xu, evtype, win, mods, button) == 0 {
		err := GrabChecked(xu, win, mods, button, sync)
		if err != nil {
			// If a bad access, let's be nice and give a good error message.
			switch err.(type) {
			case xproto.AccessError:
				return fmt.Errorf("Got a bad access error when trying to bind "+
					"'%s'. This usually means another client has already "+
					"grabbed this mouse binding.", buttonStr)
			default:
				return fmt.Errorf("Could not bind '%s' because: %s",
					buttonStr, err)
			}
		}
	}

	// If we've never grabbed anything on this window before, we need to
	// make sure we can respond to it in the main event loop.
	var allCb xgbutil.Callback
	if evtype == xevent.ButtonPress {
		allCb = xevent.ButtonPressFun(runButtonPressCallbacks)
	} else {
		allCb = xevent.ButtonReleaseFun(runButtonReleaseCallbacks)
	}

	// If this is the first Button{Press|Release}Event on this window,
	// then we need to listen to Button{Press|Release} events in the main loop.
	if !connectedMouseBind(xu, evtype, win) {
		allCb.Connect(xu, win)
	}

	// Finally, attach the callback.
	attachMouseBindCallback(xu, evtype, win, mods, button, callback)

	return nil
}