package xrandr import ( "fmt" "time" "github.com/jezek/xgb" "github.com/jezek/xgb/randr" "github.com/jezek/xgb/xproto" ) const xSettleTime = 3 type event struct { xgb.Event xgb.Error } func waitForEventSettle(timeout time.Duration, xgbConn *xgb.Conn, rootWindow *xproto.Window) error { enable := randr.NotifyMaskScreenChange | randr.NotifyMaskCrtcChange | randr.NotifyMaskOutputChange | randr.NotifyMaskOutputProperty if err := randr.SelectInputChecked(xgbConn, *rootWindow, uint16(enable)).Check(); err != nil { return fmt.Errorf("failed to check xrandr events: %w", err) } now := time.Now() timeoutTime := now.Add(timeout) for { eventChannel := make(chan event) go func() { e, err := xgbConn.WaitForEvent() eventChannel <- event{Event: e, Error: err} }() select { case e := <-eventChannel: if e.Event == nil && e.Error == nil { return fmt.Errorf("X connection closed unexpectedly while waiting for events") } case <-time.After(xSettleTime * time.Second): return nil } if time.Now().After(timeoutTime) { return fmt.Errorf("X events have not settled and timeout was reached") } } }