code: func MainPing(xu *xgbutil.XUtil) (chan struct{}, chan struct{}, chan struct{}) {
  	pingBefore := make(chan struct{}, 0)
  	pingAfter := make(chan struct{}, 0)
  	pingQuit := make(chan struct{}, 0)
  	go func() {
  		mainEventLoop(xu, pingBefore, pingAfter, pingQuit)
  	}()
  	return pingBefore, pingAfter, pingQuit
  }
docs: // MainPing starts the main X event loop, and returns three "ping" channels:
  // the first is pinged before an event is dequeued, the second is pinged
  // after all callbacks for a particular event have been called and the last
  // is pinged when the event loop stops (e.g., after a call to xevent.Quit).
  // pingAfter channel.
  //
  // This is useful if your event loop needs to draw from other sources. e.g.,
  //
  //	pingBefore, pingAfter, pingQuit := xevent.MainPing()
  //	for {
  //		select {
  //		case <-pingBefore:
  //			// Wait for event processing to finish.
  //			<-pingAfter
  //		case val <- someOtherChannel:
  //			// do some work with val
  //		case <-pingQuit:
  //			fmt.Printf("xevent loop has quit")
  //			return
  //		}
  //	}
  //
  // Note that an unbuffered channel is returned, which implies that any work
  // done with 'val' will delay further X event processing.
  //
  // A complete example using MainPing can be found in the examples directory in
  // the xgbutil package under the name multiple-source-event-loop.