diff options
Diffstat (limited to 'nexgb/record/record.go')
-rw-r--r-- | nexgb/record/record.go | 1204 |
1 files changed, 1204 insertions, 0 deletions
diff --git a/nexgb/record/record.go b/nexgb/record/record.go new file mode 100644 index 0000000..1cb022b --- /dev/null +++ b/nexgb/record/record.go @@ -0,0 +1,1204 @@ +// Package record is the X client API for the RECORD extension. +package record + +// This file is automatically generated from record.xml. Edit at your peril! + +import ( + "github.com/BurntSushi/xgb" + + "github.com/BurntSushi/xgb/xproto" +) + +// Init must be called before using the RECORD extension. +func Init(c *xgb.Conn) error { + reply, err := xproto.QueryExtension(c, 6, "RECORD").Reply() + switch { + case err != nil: + return err + case !reply.Present: + return xgb.Errorf("No extension named RECORD could be found on on the server.") + } + + c.ExtLock.Lock() + c.Extensions["RECORD"] = reply.MajorOpcode + c.ExtLock.Unlock() + for evNum, fun := range xgb.NewExtEventFuncs["RECORD"] { + xgb.NewEventFuncs[int(reply.FirstEvent)+evNum] = fun + } + for errNum, fun := range xgb.NewExtErrorFuncs["RECORD"] { + xgb.NewErrorFuncs[int(reply.FirstError)+errNum] = fun + } + return nil +} + +func init() { + xgb.NewExtEventFuncs["RECORD"] = make(map[int]xgb.NewEventFun) + xgb.NewExtErrorFuncs["RECORD"] = make(map[int]xgb.NewErrorFun) +} + +// BadBadContext is the error number for a BadBadContext. +const BadBadContext = 0 + +type BadContextError struct { + Sequence uint16 + NiceName string + InvalidRecord uint32 +} + +// BadContextErrorNew constructs a BadContextError value that implements xgb.Error from a byte slice. +func BadContextErrorNew(buf []byte) xgb.Error { + v := BadContextError{} + v.NiceName = "BadContext" + + b := 1 // skip error determinant + b += 1 // don't read error number + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.InvalidRecord = xgb.Get32(buf[b:]) + b += 4 + + return v +} + +// SequenceId returns the sequence id attached to the BadBadContext error. +// This is mostly used internally. +func (err BadContextError) SequenceId() uint16 { + return err.Sequence +} + +// BadId returns the 'BadValue' number if one exists for the BadBadContext error. If no bad value exists, 0 is returned. +func (err BadContextError) BadId() uint32 { + return 0 +} + +// Error returns a rudimentary string representation of the BadBadContext error. + +func (err BadContextError) Error() string { + fieldVals := make([]string, 0, 1) + fieldVals = append(fieldVals, "NiceName: "+err.NiceName) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", err.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("InvalidRecord: %d", err.InvalidRecord)) + return "BadBadContext {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewExtErrorFuncs["RECORD"][0] = BadContextErrorNew +} + +type ClientInfo struct { + ClientResource ClientSpec + NumRanges uint32 + Ranges []Range // size: xgb.Pad((int(NumRanges) * 24)) +} + +// ClientInfoRead reads a byte slice into a ClientInfo value. +func ClientInfoRead(buf []byte, v *ClientInfo) int { + b := 0 + + v.ClientResource = ClientSpec(xgb.Get32(buf[b:])) + b += 4 + + v.NumRanges = xgb.Get32(buf[b:]) + b += 4 + + v.Ranges = make([]Range, v.NumRanges) + b += RangeReadList(buf[b:], v.Ranges) + + return b +} + +// ClientInfoReadList reads a byte slice into a list of ClientInfo values. +func ClientInfoReadList(buf []byte, dest []ClientInfo) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = ClientInfo{} + b += ClientInfoRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a ClientInfo value to a byte slice. +func (v ClientInfo) Bytes() []byte { + buf := make([]byte, (8 + xgb.Pad((int(v.NumRanges) * 24)))) + b := 0 + + xgb.Put32(buf[b:], uint32(v.ClientResource)) + b += 4 + + xgb.Put32(buf[b:], v.NumRanges) + b += 4 + + b += RangeListBytes(buf[b:], v.Ranges) + + return buf[:b] +} + +// ClientInfoListBytes writes a list of ClientInfo values to a byte slice. +func ClientInfoListBytes(buf []byte, list []ClientInfo) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +// ClientInfoListSize computes the size (bytes) of a list of ClientInfo values. +func ClientInfoListSize(list []ClientInfo) int { + size := 0 + for _, item := range list { + size += (8 + xgb.Pad((int(item.NumRanges) * 24))) + } + return size +} + +type ClientSpec uint32 + +type Context uint32 + +func NewContextId(c *xgb.Conn) (Context, error) { + id, err := c.NewId() + if err != nil { + return 0, err + } + return Context(id), nil +} + +const ( + CsCurrentClients = 1 + CsFutureClients = 2 + CsAllClients = 3 +) + +type ElementHeader byte + +type ExtRange struct { + Major Range8 + Minor Range16 +} + +// ExtRangeRead reads a byte slice into a ExtRange value. +func ExtRangeRead(buf []byte, v *ExtRange) int { + b := 0 + + v.Major = Range8{} + b += Range8Read(buf[b:], &v.Major) + + v.Minor = Range16{} + b += Range16Read(buf[b:], &v.Minor) + + return b +} + +// ExtRangeReadList reads a byte slice into a list of ExtRange values. +func ExtRangeReadList(buf []byte, dest []ExtRange) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = ExtRange{} + b += ExtRangeRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a ExtRange value to a byte slice. +func (v ExtRange) Bytes() []byte { + buf := make([]byte, 6) + b := 0 + + { + structBytes := v.Major.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + + { + structBytes := v.Minor.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + + return buf[:b] +} + +// ExtRangeListBytes writes a list of ExtRange values to a byte slice. +func ExtRangeListBytes(buf []byte, list []ExtRange) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +const ( + HTypeFromServerTime = 1 + HTypeFromClientTime = 2 + HTypeFromClientSequence = 4 +) + +type Range struct { + CoreRequests Range8 + CoreReplies Range8 + ExtRequests ExtRange + ExtReplies ExtRange + DeliveredEvents Range8 + DeviceEvents Range8 + Errors Range8 + ClientStarted bool + ClientDied bool +} + +// RangeRead reads a byte slice into a Range value. +func RangeRead(buf []byte, v *Range) int { + b := 0 + + v.CoreRequests = Range8{} + b += Range8Read(buf[b:], &v.CoreRequests) + + v.CoreReplies = Range8{} + b += Range8Read(buf[b:], &v.CoreReplies) + + v.ExtRequests = ExtRange{} + b += ExtRangeRead(buf[b:], &v.ExtRequests) + + v.ExtReplies = ExtRange{} + b += ExtRangeRead(buf[b:], &v.ExtReplies) + + v.DeliveredEvents = Range8{} + b += Range8Read(buf[b:], &v.DeliveredEvents) + + v.DeviceEvents = Range8{} + b += Range8Read(buf[b:], &v.DeviceEvents) + + v.Errors = Range8{} + b += Range8Read(buf[b:], &v.Errors) + + if buf[b] == 1 { + v.ClientStarted = true + } else { + v.ClientStarted = false + } + b += 1 + + if buf[b] == 1 { + v.ClientDied = true + } else { + v.ClientDied = false + } + b += 1 + + return b +} + +// RangeReadList reads a byte slice into a list of Range values. +func RangeReadList(buf []byte, dest []Range) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = Range{} + b += RangeRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a Range value to a byte slice. +func (v Range) Bytes() []byte { + buf := make([]byte, 24) + b := 0 + + { + structBytes := v.CoreRequests.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + + { + structBytes := v.CoreReplies.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + + { + structBytes := v.ExtRequests.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + + { + structBytes := v.ExtReplies.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + + { + structBytes := v.DeliveredEvents.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + + { + structBytes := v.DeviceEvents.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + + { + structBytes := v.Errors.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + + if v.ClientStarted { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + if v.ClientDied { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + return buf[:b] +} + +// RangeListBytes writes a list of Range values to a byte slice. +func RangeListBytes(buf []byte, list []Range) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +type Range16 struct { + First uint16 + Last uint16 +} + +// Range16Read reads a byte slice into a Range16 value. +func Range16Read(buf []byte, v *Range16) int { + b := 0 + + v.First = xgb.Get16(buf[b:]) + b += 2 + + v.Last = xgb.Get16(buf[b:]) + b += 2 + + return b +} + +// Range16ReadList reads a byte slice into a list of Range16 values. +func Range16ReadList(buf []byte, dest []Range16) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = Range16{} + b += Range16Read(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a Range16 value to a byte slice. +func (v Range16) Bytes() []byte { + buf := make([]byte, 4) + b := 0 + + xgb.Put16(buf[b:], v.First) + b += 2 + + xgb.Put16(buf[b:], v.Last) + b += 2 + + return buf[:b] +} + +// Range16ListBytes writes a list of Range16 values to a byte slice. +func Range16ListBytes(buf []byte, list []Range16) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +type Range8 struct { + First byte + Last byte +} + +// Range8Read reads a byte slice into a Range8 value. +func Range8Read(buf []byte, v *Range8) int { + b := 0 + + v.First = buf[b] + b += 1 + + v.Last = buf[b] + b += 1 + + return b +} + +// Range8ReadList reads a byte slice into a list of Range8 values. +func Range8ReadList(buf []byte, dest []Range8) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = Range8{} + b += Range8Read(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a Range8 value to a byte slice. +func (v Range8) Bytes() []byte { + buf := make([]byte, 2) + b := 0 + + buf[b] = v.First + b += 1 + + buf[b] = v.Last + b += 1 + + return buf[:b] +} + +// Range8ListBytes writes a list of Range8 values to a byte slice. +func Range8ListBytes(buf []byte, list []Range8) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +// Skipping definition for base type 'Bool' + +// Skipping definition for base type 'Byte' + +// Skipping definition for base type 'Card8' + +// Skipping definition for base type 'Char' + +// Skipping definition for base type 'Void' + +// Skipping definition for base type 'Double' + +// Skipping definition for base type 'Float' + +// Skipping definition for base type 'Int16' + +// Skipping definition for base type 'Int32' + +// Skipping definition for base type 'Int8' + +// Skipping definition for base type 'Card16' + +// Skipping definition for base type 'Card32' + +// CreateContextCookie is a cookie used only for CreateContext requests. +type CreateContextCookie struct { + *xgb.Cookie +} + +// CreateContext sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func CreateContext(c *xgb.Conn, Context Context, ElementHeader ElementHeader, NumClientSpecs uint32, NumRanges uint32, ClientSpecs []ClientSpec, Ranges []Range) CreateContextCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["RECORD"]; !ok { + panic("Cannot issue request 'CreateContext' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") + } + cookie := c.NewCookie(false, false) + c.NewRequest(createContextRequest(c, Context, ElementHeader, NumClientSpecs, NumRanges, ClientSpecs, Ranges), cookie) + return CreateContextCookie{cookie} +} + +// CreateContextChecked sends a checked request. +// If an error occurs, it can be retrieved using CreateContextCookie.Check() +func CreateContextChecked(c *xgb.Conn, Context Context, ElementHeader ElementHeader, NumClientSpecs uint32, NumRanges uint32, ClientSpecs []ClientSpec, Ranges []Range) CreateContextCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["RECORD"]; !ok { + panic("Cannot issue request 'CreateContext' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") + } + cookie := c.NewCookie(true, false) + c.NewRequest(createContextRequest(c, Context, ElementHeader, NumClientSpecs, NumRanges, ClientSpecs, Ranges), cookie) + return CreateContextCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook CreateContextCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for CreateContext +// createContextRequest writes a CreateContext request to a byte slice. +func createContextRequest(c *xgb.Conn, Context Context, ElementHeader ElementHeader, NumClientSpecs uint32, NumRanges uint32, ClientSpecs []ClientSpec, Ranges []Range) []byte { + size := xgb.Pad(((20 + xgb.Pad((int(NumClientSpecs) * 4))) + xgb.Pad((int(NumRanges) * 24)))) + b := 0 + buf := make([]byte, size) + + c.ExtLock.RLock() + buf[b] = c.Extensions["RECORD"] + c.ExtLock.RUnlock() + b += 1 + + buf[b] = 1 // request opcode + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Context)) + b += 4 + + buf[b] = byte(ElementHeader) + b += 1 + + b += 3 // padding + + xgb.Put32(buf[b:], NumClientSpecs) + b += 4 + + xgb.Put32(buf[b:], NumRanges) + b += 4 + + for i := 0; i < int(NumClientSpecs); i++ { + xgb.Put32(buf[b:], uint32(ClientSpecs[i])) + b += 4 + } + + b += RangeListBytes(buf[b:], Ranges) + + return buf +} + +// DisableContextCookie is a cookie used only for DisableContext requests. +type DisableContextCookie struct { + *xgb.Cookie +} + +// DisableContext sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func DisableContext(c *xgb.Conn, Context Context) DisableContextCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["RECORD"]; !ok { + panic("Cannot issue request 'DisableContext' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") + } + cookie := c.NewCookie(false, false) + c.NewRequest(disableContextRequest(c, Context), cookie) + return DisableContextCookie{cookie} +} + +// DisableContextChecked sends a checked request. +// If an error occurs, it can be retrieved using DisableContextCookie.Check() +func DisableContextChecked(c *xgb.Conn, Context Context) DisableContextCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["RECORD"]; !ok { + panic("Cannot issue request 'DisableContext' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") + } + cookie := c.NewCookie(true, false) + c.NewRequest(disableContextRequest(c, Context), cookie) + return DisableContextCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook DisableContextCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for DisableContext +// disableContextRequest writes a DisableContext request to a byte slice. +func disableContextRequest(c *xgb.Conn, Context Context) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + c.ExtLock.RLock() + buf[b] = c.Extensions["RECORD"] + c.ExtLock.RUnlock() + b += 1 + + buf[b] = 6 // request opcode + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Context)) + b += 4 + + return buf +} + +// EnableContextCookie is a cookie used only for EnableContext requests. +type EnableContextCookie struct { + *xgb.Cookie +} + +// EnableContext sends a checked request. +// If an error occurs, it will be returned with the reply by calling EnableContextCookie.Reply() +func EnableContext(c *xgb.Conn, Context Context) EnableContextCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["RECORD"]; !ok { + panic("Cannot issue request 'EnableContext' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") + } + cookie := c.NewCookie(true, true) + c.NewRequest(enableContextRequest(c, Context), cookie) + return EnableContextCookie{cookie} +} + +// EnableContextUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func EnableContextUnchecked(c *xgb.Conn, Context Context) EnableContextCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["RECORD"]; !ok { + panic("Cannot issue request 'EnableContext' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") + } + cookie := c.NewCookie(false, true) + c.NewRequest(enableContextRequest(c, Context), cookie) + return EnableContextCookie{cookie} +} + +// EnableContextReply represents the data returned from a EnableContext request. +type EnableContextReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + Category byte + ElementHeader ElementHeader + ClientSwapped bool + // padding: 2 bytes + XidBase uint32 + ServerTime uint32 + RecSequenceNum uint32 + // padding: 8 bytes + Data []byte // size: xgb.Pad(((int(Length) * 4) * 1)) +} + +// Reply blocks and returns the reply data for a EnableContext request. +func (cook EnableContextCookie) Reply() (*EnableContextReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return enableContextReply(buf), nil +} + +// enableContextReply reads a byte slice into a EnableContextReply value. +func enableContextReply(buf []byte) *EnableContextReply { + v := new(EnableContextReply) + b := 1 // skip reply determinant + + v.Category = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + v.ElementHeader = ElementHeader(buf[b]) + b += 1 + + if buf[b] == 1 { + v.ClientSwapped = true + } else { + v.ClientSwapped = false + } + b += 1 + + b += 2 // padding + + v.XidBase = xgb.Get32(buf[b:]) + b += 4 + + v.ServerTime = xgb.Get32(buf[b:]) + b += 4 + + v.RecSequenceNum = xgb.Get32(buf[b:]) + b += 4 + + b += 8 // padding + + v.Data = make([]byte, (int(v.Length) * 4)) + copy(v.Data[:(int(v.Length)*4)], buf[b:]) + b += int((int(v.Length) * 4)) + + return v +} + +// Write request to wire for EnableContext +// enableContextRequest writes a EnableContext request to a byte slice. +func enableContextRequest(c *xgb.Conn, Context Context) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + c.ExtLock.RLock() + buf[b] = c.Extensions["RECORD"] + c.ExtLock.RUnlock() + b += 1 + + buf[b] = 5 // request opcode + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Context)) + b += 4 + + return buf +} + +// FreeContextCookie is a cookie used only for FreeContext requests. +type FreeContextCookie struct { + *xgb.Cookie +} + +// FreeContext sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func FreeContext(c *xgb.Conn, Context Context) FreeContextCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["RECORD"]; !ok { + panic("Cannot issue request 'FreeContext' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") + } + cookie := c.NewCookie(false, false) + c.NewRequest(freeContextRequest(c, Context), cookie) + return FreeContextCookie{cookie} +} + +// FreeContextChecked sends a checked request. +// If an error occurs, it can be retrieved using FreeContextCookie.Check() +func FreeContextChecked(c *xgb.Conn, Context Context) FreeContextCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["RECORD"]; !ok { + panic("Cannot issue request 'FreeContext' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") + } + cookie := c.NewCookie(true, false) + c.NewRequest(freeContextRequest(c, Context), cookie) + return FreeContextCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook FreeContextCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for FreeContext +// freeContextRequest writes a FreeContext request to a byte slice. +func freeContextRequest(c *xgb.Conn, Context Context) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + c.ExtLock.RLock() + buf[b] = c.Extensions["RECORD"] + c.ExtLock.RUnlock() + b += 1 + + buf[b] = 7 // request opcode + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Context)) + b += 4 + + return buf +} + +// GetContextCookie is a cookie used only for GetContext requests. +type GetContextCookie struct { + *xgb.Cookie +} + +// GetContext sends a checked request. +// If an error occurs, it will be returned with the reply by calling GetContextCookie.Reply() +func GetContext(c *xgb.Conn, Context Context) GetContextCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["RECORD"]; !ok { + panic("Cannot issue request 'GetContext' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") + } + cookie := c.NewCookie(true, true) + c.NewRequest(getContextRequest(c, Context), cookie) + return GetContextCookie{cookie} +} + +// GetContextUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GetContextUnchecked(c *xgb.Conn, Context Context) GetContextCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["RECORD"]; !ok { + panic("Cannot issue request 'GetContext' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") + } + cookie := c.NewCookie(false, true) + c.NewRequest(getContextRequest(c, Context), cookie) + return GetContextCookie{cookie} +} + +// GetContextReply represents the data returned from a GetContext request. +type GetContextReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + Enabled bool + ElementHeader ElementHeader + // padding: 3 bytes + NumInterceptedClients uint32 + // padding: 16 bytes + InterceptedClients []ClientInfo // size: ClientInfoListSize(InterceptedClients) +} + +// Reply blocks and returns the reply data for a GetContext request. +func (cook GetContextCookie) Reply() (*GetContextReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return getContextReply(buf), nil +} + +// getContextReply reads a byte slice into a GetContextReply value. +func getContextReply(buf []byte) *GetContextReply { + v := new(GetContextReply) + b := 1 // skip reply determinant + + if buf[b] == 1 { + v.Enabled = true + } else { + v.Enabled = false + } + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + v.ElementHeader = ElementHeader(buf[b]) + b += 1 + + b += 3 // padding + + v.NumInterceptedClients = xgb.Get32(buf[b:]) + b += 4 + + b += 16 // padding + + v.InterceptedClients = make([]ClientInfo, v.NumInterceptedClients) + b += ClientInfoReadList(buf[b:], v.InterceptedClients) + + return v +} + +// Write request to wire for GetContext +// getContextRequest writes a GetContext request to a byte slice. +func getContextRequest(c *xgb.Conn, Context Context) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + c.ExtLock.RLock() + buf[b] = c.Extensions["RECORD"] + c.ExtLock.RUnlock() + b += 1 + + buf[b] = 4 // request opcode + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Context)) + b += 4 + + return buf +} + +// QueryVersionCookie is a cookie used only for QueryVersion requests. +type QueryVersionCookie struct { + *xgb.Cookie +} + +// QueryVersion sends a checked request. +// If an error occurs, it will be returned with the reply by calling QueryVersionCookie.Reply() +func QueryVersion(c *xgb.Conn, MajorVersion uint16, MinorVersion uint16) QueryVersionCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["RECORD"]; !ok { + panic("Cannot issue request 'QueryVersion' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") + } + cookie := c.NewCookie(true, true) + c.NewRequest(queryVersionRequest(c, MajorVersion, MinorVersion), cookie) + return QueryVersionCookie{cookie} +} + +// QueryVersionUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func QueryVersionUnchecked(c *xgb.Conn, MajorVersion uint16, MinorVersion uint16) QueryVersionCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["RECORD"]; !ok { + panic("Cannot issue request 'QueryVersion' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") + } + cookie := c.NewCookie(false, true) + c.NewRequest(queryVersionRequest(c, MajorVersion, MinorVersion), cookie) + return QueryVersionCookie{cookie} +} + +// QueryVersionReply represents the data returned from a QueryVersion request. +type QueryVersionReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + MajorVersion uint16 + MinorVersion uint16 +} + +// Reply blocks and returns the reply data for a QueryVersion request. +func (cook QueryVersionCookie) Reply() (*QueryVersionReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return queryVersionReply(buf), nil +} + +// queryVersionReply reads a byte slice into a QueryVersionReply value. +func queryVersionReply(buf []byte) *QueryVersionReply { + v := new(QueryVersionReply) + b := 1 // skip reply determinant + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + v.MajorVersion = xgb.Get16(buf[b:]) + b += 2 + + v.MinorVersion = xgb.Get16(buf[b:]) + b += 2 + + return v +} + +// Write request to wire for QueryVersion +// queryVersionRequest writes a QueryVersion request to a byte slice. +func queryVersionRequest(c *xgb.Conn, MajorVersion uint16, MinorVersion uint16) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + c.ExtLock.RLock() + buf[b] = c.Extensions["RECORD"] + c.ExtLock.RUnlock() + b += 1 + + buf[b] = 0 // request opcode + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put16(buf[b:], MajorVersion) + b += 2 + + xgb.Put16(buf[b:], MinorVersion) + b += 2 + + return buf +} + +// RegisterClientsCookie is a cookie used only for RegisterClients requests. +type RegisterClientsCookie struct { + *xgb.Cookie +} + +// RegisterClients sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func RegisterClients(c *xgb.Conn, Context Context, ElementHeader ElementHeader, NumClientSpecs uint32, NumRanges uint32, ClientSpecs []ClientSpec, Ranges []Range) RegisterClientsCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["RECORD"]; !ok { + panic("Cannot issue request 'RegisterClients' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") + } + cookie := c.NewCookie(false, false) + c.NewRequest(registerClientsRequest(c, Context, ElementHeader, NumClientSpecs, NumRanges, ClientSpecs, Ranges), cookie) + return RegisterClientsCookie{cookie} +} + +// RegisterClientsChecked sends a checked request. +// If an error occurs, it can be retrieved using RegisterClientsCookie.Check() +func RegisterClientsChecked(c *xgb.Conn, Context Context, ElementHeader ElementHeader, NumClientSpecs uint32, NumRanges uint32, ClientSpecs []ClientSpec, Ranges []Range) RegisterClientsCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["RECORD"]; !ok { + panic("Cannot issue request 'RegisterClients' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") + } + cookie := c.NewCookie(true, false) + c.NewRequest(registerClientsRequest(c, Context, ElementHeader, NumClientSpecs, NumRanges, ClientSpecs, Ranges), cookie) + return RegisterClientsCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook RegisterClientsCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for RegisterClients +// registerClientsRequest writes a RegisterClients request to a byte slice. +func registerClientsRequest(c *xgb.Conn, Context Context, ElementHeader ElementHeader, NumClientSpecs uint32, NumRanges uint32, ClientSpecs []ClientSpec, Ranges []Range) []byte { + size := xgb.Pad(((20 + xgb.Pad((int(NumClientSpecs) * 4))) + xgb.Pad((int(NumRanges) * 24)))) + b := 0 + buf := make([]byte, size) + + c.ExtLock.RLock() + buf[b] = c.Extensions["RECORD"] + c.ExtLock.RUnlock() + b += 1 + + buf[b] = 2 // request opcode + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Context)) + b += 4 + + buf[b] = byte(ElementHeader) + b += 1 + + b += 3 // padding + + xgb.Put32(buf[b:], NumClientSpecs) + b += 4 + + xgb.Put32(buf[b:], NumRanges) + b += 4 + + for i := 0; i < int(NumClientSpecs); i++ { + xgb.Put32(buf[b:], uint32(ClientSpecs[i])) + b += 4 + } + + b += RangeListBytes(buf[b:], Ranges) + + return buf +} + +// UnregisterClientsCookie is a cookie used only for UnregisterClients requests. +type UnregisterClientsCookie struct { + *xgb.Cookie +} + +// UnregisterClients sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func UnregisterClients(c *xgb.Conn, Context Context, NumClientSpecs uint32, ClientSpecs []ClientSpec) UnregisterClientsCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["RECORD"]; !ok { + panic("Cannot issue request 'UnregisterClients' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") + } + cookie := c.NewCookie(false, false) + c.NewRequest(unregisterClientsRequest(c, Context, NumClientSpecs, ClientSpecs), cookie) + return UnregisterClientsCookie{cookie} +} + +// UnregisterClientsChecked sends a checked request. +// If an error occurs, it can be retrieved using UnregisterClientsCookie.Check() +func UnregisterClientsChecked(c *xgb.Conn, Context Context, NumClientSpecs uint32, ClientSpecs []ClientSpec) UnregisterClientsCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["RECORD"]; !ok { + panic("Cannot issue request 'UnregisterClients' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") + } + cookie := c.NewCookie(true, false) + c.NewRequest(unregisterClientsRequest(c, Context, NumClientSpecs, ClientSpecs), cookie) + return UnregisterClientsCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook UnregisterClientsCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for UnregisterClients +// unregisterClientsRequest writes a UnregisterClients request to a byte slice. +func unregisterClientsRequest(c *xgb.Conn, Context Context, NumClientSpecs uint32, ClientSpecs []ClientSpec) []byte { + size := xgb.Pad((12 + xgb.Pad((int(NumClientSpecs) * 4)))) + b := 0 + buf := make([]byte, size) + + c.ExtLock.RLock() + buf[b] = c.Extensions["RECORD"] + c.ExtLock.RUnlock() + b += 1 + + buf[b] = 3 // request opcode + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Context)) + b += 4 + + xgb.Put32(buf[b:], NumClientSpecs) + b += 4 + + for i := 0; i < int(NumClientSpecs); i++ { + xgb.Put32(buf[b:], uint32(ClientSpecs[i])) + b += 4 + } + + return buf +} |