// 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 }
// 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 }