1202 lines
31 KiB
Go
1202 lines
31 KiB
Go
// 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 (
|
|
xgb "janouch.name/haven/nexgb"
|
|
|
|
"janouch.name/haven/nexgb/xproto"
|
|
)
|
|
|
|
const (
|
|
MajorVersion = 1
|
|
MinorVersion = 13
|
|
)
|
|
|
|
// 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, 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, 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()
|
|
}
|
|
|
|
// createContextRequest writes a CreateContext request to a byte slice for transfer.
|
|
func createContextRequest(c *xgb.Conn, Context Context, ElementHeader ElementHeader, NumClientSpecs, 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()
|
|
}
|
|
|
|
// disableContextRequest writes a DisableContext request to a byte slice for transfer.
|
|
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
|
|
}
|
|
|
|
// enableContextRequest writes a EnableContext request to a byte slice for transfer.
|
|
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()
|
|
}
|
|
|
|
// freeContextRequest writes a FreeContext request to a byte slice for transfer.
|
|
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
|
|
}
|
|
|
|
// getContextRequest writes a GetContext request to a byte slice for transfer.
|
|
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, 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, 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
|
|
}
|
|
|
|
// queryVersionRequest writes a QueryVersion request to a byte slice for transfer.
|
|
func queryVersionRequest(c *xgb.Conn, MajorVersion, 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, 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, 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()
|
|
}
|
|
|
|
// registerClientsRequest writes a RegisterClients request to a byte slice for transfer.
|
|
func registerClientsRequest(c *xgb.Conn, Context Context, ElementHeader ElementHeader, NumClientSpecs, 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()
|
|
}
|
|
|
|
// unregisterClientsRequest writes a UnregisterClients request to a byte slice for transfer.
|
|
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
|
|
}
|