// 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 }
// Drag is the public interface that will make the appropriate connections // to register a drag event for three functions: the begin function, the // step function and the end function. // The 'grabwin' is the window that the grab is placed on (and therefore the // window where all button events are redirected to after the drag has started), // and the 'win' is the window that the initial 'begin' callback is set on. // In typical use cases, these windows should be the same. // If 'grab' is false, then no pointer grab is issued. func Drag(xu *xgbutil.XUtil, grabwin xproto.Window, win xproto.Window, buttonStr string, grab bool, begin xgbutil.MouseDragBeginFun, step xgbutil.MouseDragFun, end xgbutil.MouseDragFun) { ButtonPressFun( func(xu *xgbutil.XUtil, ev xevent.ButtonPressEvent) { DragBegin(xu, ev, grabwin, win, begin, step, end) }).Connect(xu, win, buttonStr, false, grab) // If the grab win isn't the dummy, then setup event handlers for the // grab window. if grabwin != xu.Dummy() { xevent.MotionNotifyFun(dragStep).Connect(xu, grabwin) xevent.ButtonReleaseFun(DragEnd).Connect(xu, grabwin) } }
// Initialize attaches the appropriate callbacks to make mouse bindings easier. // i.e., prep the dummy window to handle mouse dragging events func Initialize(xu *xgbutil.XUtil) { xevent.MotionNotifyFun(dragStep).Connect(xu, xu.Dummy()) xevent.ButtonReleaseFun(DragEnd).Connect(xu, xu.Dummy()) }