package xturbo import "encoding/binary" // EventKind identifies a decoded event: uint16(ExtID)<<8 | code. Core events // use the wire code (2..34); extension events the code relative to the // extension's first event; XGE events 0x80|evtype. type EventKind uint16 // KindUnknown marks an event whose code or XGE extension is not known. const KindUnknown EventKind = 0xFFFF const ( codeGenericEvent = 35 codeKeymapNotify = 11 ) // Event is a decoded event value. Raw is a copy and survives Dispatch; Tail // borrows the read buffer (XGE bytes beyond 32) and is valid only until the // Handler callback returns. Copy what you keep. type Event struct { Kind EventKind SendEvent bool Ext ExtID Seq Seq // wire sequence; Conn widens it. 0 for KeymapNotify. Raw [32]byte Tail []byte } // DecodeEvent decodes one event packet at the start of raw. n is the number // of bytes consumed (32, or 32+4*length for XGE). ok is false for error and // reply packets and for short input. Unknown codes decode with // Kind == KindUnknown and ok == true. A nil ext decodes core events only. // The returned Seq is the 16-bit wire value; Conn widens it. func DecodeEvent(raw []byte, ext *ExtTable) (ev Event, n int, ok bool) { if len(raw) < 32 { return Event{}, 0, false } code := raw[0] & 0x7f if code < 2 { return Event{}, 0, false } n = 32 if code == codeGenericEvent { length := uint64(binary.LittleEndian.Uint32(raw[4:])) if uint64(len(raw)-32)/4 < length { return Event{}, 0, false } n = 32 + int(length)*4 ev.Tail = raw[32:n:n] } copy(ev.Raw[:], raw[:32]) ev.SendEvent = raw[0]&0x80 != 0 if code != codeKeymapNotify { ev.Seq = Seq(binary.LittleEndian.Uint16(raw[2:])) } ev.Kind = KindUnknown switch { case code < codeGenericEvent: ev.Kind = EventKind(code) case code == codeGenericEvent: if ext == nil { break } evtype := binary.LittleEndian.Uint16(raw[8:]) if id, found := ext.ByMajor(raw[1]); found && evtype < 0x80 { ev.Ext = id ev.Kind = EventKind(id)<<8 | 0x80 | EventKind(evtype) } case code >= 64 && ext != nil: if id, rel, found := ext.ByEvent(code); found { ev.Ext = id ev.Kind = EventKind(id)<<8 | EventKind(rel) } } return ev, n, true }