diff options
-rw-r--r-- | nexgb/randr/randr.go | 339 | ||||
-rw-r--r-- | nexgb/res/res.go | 12 | ||||
-rw-r--r-- | nexgb/xproto/xproto.go | 14 |
3 files changed, 356 insertions, 9 deletions
diff --git a/nexgb/randr/randr.go b/nexgb/randr/randr.go index 9570434..99cf4f0 100644 --- a/nexgb/randr/randr.go +++ b/nexgb/randr/randr.go @@ -12,7 +12,7 @@ import ( const ( MajorVersion = 1 - MinorVersion = 5 + MinorVersion = 6 ) // Init must be called before using the RANDR extension. @@ -350,6 +350,89 @@ func CrtcChangeListBytes(buf []byte, list []CrtcChange) int { return xgb.Pad(b) } +type Lease uint32 + +func NewLeaseId(c *xgb.Conn) (Lease, error) { + id, err := c.NewId() + if err != nil { + return 0, err + } + return Lease(id), nil +} + +type LeaseNotify struct { + Timestamp xproto.Timestamp + Window xproto.Window + Lease Lease + Created byte + // padding: 15 bytes +} + +// LeaseNotifyRead reads a byte slice into a LeaseNotify value. +func LeaseNotifyRead(buf []byte, v *LeaseNotify) int { + b := 0 + + v.Timestamp = xproto.Timestamp(xgb.Get32(buf[b:])) + b += 4 + + v.Window = xproto.Window(xgb.Get32(buf[b:])) + b += 4 + + v.Lease = Lease(xgb.Get32(buf[b:])) + b += 4 + + v.Created = buf[b] + b += 1 + + b += 15 // padding + + return b +} + +// LeaseNotifyReadList reads a byte slice into a list of LeaseNotify values. +func LeaseNotifyReadList(buf []byte, dest []LeaseNotify) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = LeaseNotify{} + b += LeaseNotifyRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a LeaseNotify value to a byte slice. +func (v LeaseNotify) Bytes() []byte { + buf := make([]byte, 28) + b := 0 + + xgb.Put32(buf[b:], uint32(v.Timestamp)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Window)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Lease)) + b += 4 + + buf[b] = v.Created + b += 1 + + b += 15 // padding + + return buf[:b] +} + +// LeaseNotifyListBytes writes a list of LeaseNotify values to a byte slice. +func LeaseNotifyListBytes(buf []byte, list []LeaseNotify) 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 Mode uint32 func NewModeId(c *xgb.Conn) (Mode, error) { @@ -662,6 +745,7 @@ const ( NotifyProviderChange = 3 NotifyProviderProperty = 4 NotifyResourceChange = 5 + NotifyLease = 6 ) // Notify is the event number for a NotifyEvent. @@ -742,6 +826,7 @@ func init() { // NotifyDataUnionPcNew(Pc ProviderChange) NotifyDataUnion // NotifyDataUnionPpNew(Pp ProviderProperty) NotifyDataUnion // NotifyDataUnionRcNew(Rc ResourceChange) NotifyDataUnion +// NotifyDataUnionLcNew(Lc LeaseNotify) NotifyDataUnion type NotifyDataUnion struct { Cc CrtcChange Oc OutputChange @@ -749,6 +834,7 @@ type NotifyDataUnion struct { Pc ProviderChange Pp ProviderProperty Rc ResourceChange + Lc LeaseNotify } // NotifyDataUnionCcNew constructs a new NotifyDataUnion union type with the Cc field. @@ -791,6 +877,10 @@ func NotifyDataUnionCcNew(Cc CrtcChange) NotifyDataUnion { v.Rc = ResourceChange{} b += ResourceChangeRead(buf[b:], &v.Rc) + b = 0 // always read the same bytes + v.Lc = LeaseNotify{} + b += LeaseNotifyRead(buf[b:], &v.Lc) + return v } @@ -834,6 +924,10 @@ func NotifyDataUnionOcNew(Oc OutputChange) NotifyDataUnion { v.Rc = ResourceChange{} b += ResourceChangeRead(buf[b:], &v.Rc) + b = 0 // always read the same bytes + v.Lc = LeaseNotify{} + b += LeaseNotifyRead(buf[b:], &v.Lc) + return v } @@ -877,6 +971,10 @@ func NotifyDataUnionOpNew(Op OutputProperty) NotifyDataUnion { v.Rc = ResourceChange{} b += ResourceChangeRead(buf[b:], &v.Rc) + b = 0 // always read the same bytes + v.Lc = LeaseNotify{} + b += LeaseNotifyRead(buf[b:], &v.Lc) + return v } @@ -920,6 +1018,10 @@ func NotifyDataUnionPcNew(Pc ProviderChange) NotifyDataUnion { v.Rc = ResourceChange{} b += ResourceChangeRead(buf[b:], &v.Rc) + b = 0 // always read the same bytes + v.Lc = LeaseNotify{} + b += LeaseNotifyRead(buf[b:], &v.Lc) + return v } @@ -963,6 +1065,10 @@ func NotifyDataUnionPpNew(Pp ProviderProperty) NotifyDataUnion { v.Rc = ResourceChange{} b += ResourceChangeRead(buf[b:], &v.Rc) + b = 0 // always read the same bytes + v.Lc = LeaseNotify{} + b += LeaseNotifyRead(buf[b:], &v.Lc) + return v } @@ -1006,6 +1112,57 @@ func NotifyDataUnionRcNew(Rc ResourceChange) NotifyDataUnion { v.Rc = ResourceChange{} b += ResourceChangeRead(buf[b:], &v.Rc) + b = 0 // always read the same bytes + v.Lc = LeaseNotify{} + b += LeaseNotifyRead(buf[b:], &v.Lc) + + return v +} + +// NotifyDataUnionLcNew constructs a new NotifyDataUnion union type with the Lc field. +func NotifyDataUnionLcNew(Lc LeaseNotify) NotifyDataUnion { + var b int + buf := make([]byte, 28) + + { + structBytes := Lc.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + + // Create the Union type + v := NotifyDataUnion{} + + // Now copy buf into all fields + + b = 0 // always read the same bytes + v.Cc = CrtcChange{} + b += CrtcChangeRead(buf[b:], &v.Cc) + + b = 0 // always read the same bytes + v.Oc = OutputChange{} + b += OutputChangeRead(buf[b:], &v.Oc) + + b = 0 // always read the same bytes + v.Op = OutputProperty{} + b += OutputPropertyRead(buf[b:], &v.Op) + + b = 0 // always read the same bytes + v.Pc = ProviderChange{} + b += ProviderChangeRead(buf[b:], &v.Pc) + + b = 0 // always read the same bytes + v.Pp = ProviderProperty{} + b += ProviderPropertyRead(buf[b:], &v.Pp) + + b = 0 // always read the same bytes + v.Rc = ResourceChange{} + b += ResourceChangeRead(buf[b:], &v.Rc) + + b = 0 // always read the same bytes + v.Lc = LeaseNotify{} + b += LeaseNotifyRead(buf[b:], &v.Lc) + return v } @@ -1037,6 +1194,10 @@ func NotifyDataUnionRead(buf []byte, v *NotifyDataUnion) int { v.Rc = ResourceChange{} b += ResourceChangeRead(buf[b:], &v.Rc) + b = 0 // re-read the same bytes + v.Lc = LeaseNotify{} + b += LeaseNotifyRead(buf[b:], &v.Lc) + return 28 } @@ -1085,6 +1246,7 @@ const ( NotifyMaskProviderChange = 16 NotifyMaskProviderProperty = 32 NotifyMaskResourceChange = 64 + NotifyMaskLease = 128 ) type Output uint32 @@ -2214,6 +2376,118 @@ func configureProviderPropertyRequest(c *xgb.Conn, Provider Provider, Property x return buf } +// CreateLeaseCookie is a cookie used only for CreateLease requests. +type CreateLeaseCookie struct { + *xgb.Cookie +} + +// CreateLease sends a checked request. +// If an error occurs, it will be returned with the reply by calling CreateLeaseCookie.Reply. +func CreateLease(c *xgb.Conn, Window xproto.Window, Lid Lease, NumCrtcs, NumOutputs uint16, Crtcs []Crtc, Outputs []Output) CreateLeaseCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["RANDR"]; !ok { + panic("Cannot issue request 'CreateLease' using the uninitialized extension 'RANDR'. randr.Init(connObj) must be called first.") + } + cookie := c.NewCookie(true, true) + c.NewRequest(createLeaseRequest(c, Window, Lid, NumCrtcs, NumOutputs, Crtcs, Outputs), cookie) + return CreateLeaseCookie{cookie} +} + +// CreateLeaseUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func CreateLeaseUnchecked(c *xgb.Conn, Window xproto.Window, Lid Lease, NumCrtcs, NumOutputs uint16, Crtcs []Crtc, Outputs []Output) CreateLeaseCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["RANDR"]; !ok { + panic("Cannot issue request 'CreateLease' using the uninitialized extension 'RANDR'. randr.Init(connObj) must be called first.") + } + cookie := c.NewCookie(false, true) + c.NewRequest(createLeaseRequest(c, Window, Lid, NumCrtcs, NumOutputs, Crtcs, Outputs), cookie) + return CreateLeaseCookie{cookie} +} + +// CreateLeaseReply represents the data returned from a CreateLease request. +type CreateLeaseReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + Nfd byte + // padding: 24 bytes +} + +// Reply blocks and returns the reply data for a CreateLease request. +func (cook CreateLeaseCookie) Reply() (*CreateLeaseReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return createLeaseReply(buf), nil +} + +// createLeaseReply reads a byte slice into a CreateLeaseReply value. +func createLeaseReply(buf []byte) *CreateLeaseReply { + v := new(CreateLeaseReply) + b := 1 // skip reply determinant + + v.Nfd = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + b += 24 // padding + + return v +} + +// createLeaseRequest writes a CreateLease request to a byte slice for transfer. +func createLeaseRequest(c *xgb.Conn, Window xproto.Window, Lid Lease, NumCrtcs, NumOutputs uint16, Crtcs []Crtc, Outputs []Output) []byte { + size := xgb.Pad(((16 + xgb.Pad((int(NumCrtcs) * 4))) + xgb.Pad((int(NumOutputs) * 4)))) + b := 0 + buf := make([]byte, size) + + c.ExtLock.RLock() + buf[b] = c.Extensions["RANDR"] + c.ExtLock.RUnlock() + b += 1 + + buf[b] = 45 // 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(Window)) + b += 4 + + xgb.Put32(buf[b:], uint32(Lid)) + b += 4 + + xgb.Put16(buf[b:], NumCrtcs) + b += 2 + + xgb.Put16(buf[b:], NumOutputs) + b += 2 + + for i := 0; i < int(NumCrtcs); i++ { + xgb.Put32(buf[b:], uint32(Crtcs[i])) + b += 4 + } + + for i := 0; i < int(NumOutputs); i++ { + xgb.Put32(buf[b:], uint32(Outputs[i])) + b += 4 + } + + return buf +} + // CreateModeCookie is a cookie used only for CreateMode requests. type CreateModeCookie struct { *xgb.Cookie @@ -2631,6 +2905,69 @@ func destroyModeRequest(c *xgb.Conn, Mode Mode) []byte { return buf } +// FreeLeaseCookie is a cookie used only for FreeLease requests. +type FreeLeaseCookie struct { + *xgb.Cookie +} + +// FreeLease sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func FreeLease(c *xgb.Conn, Lid Lease, Terminate byte) FreeLeaseCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["RANDR"]; !ok { + panic("Cannot issue request 'FreeLease' using the uninitialized extension 'RANDR'. randr.Init(connObj) must be called first.") + } + cookie := c.NewCookie(false, false) + c.NewRequest(freeLeaseRequest(c, Lid, Terminate), cookie) + return FreeLeaseCookie{cookie} +} + +// FreeLeaseChecked sends a checked request. +// If an error occurs, it can be retrieved using FreeLeaseCookie.Check. +func FreeLeaseChecked(c *xgb.Conn, Lid Lease, Terminate byte) FreeLeaseCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["RANDR"]; !ok { + panic("Cannot issue request 'FreeLease' using the uninitialized extension 'RANDR'. randr.Init(connObj) must be called first.") + } + cookie := c.NewCookie(true, false) + c.NewRequest(freeLeaseRequest(c, Lid, Terminate), cookie) + return FreeLeaseCookie{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 FreeLeaseCookie) Check() error { + return cook.Cookie.Check() +} + +// freeLeaseRequest writes a FreeLease request to a byte slice for transfer. +func freeLeaseRequest(c *xgb.Conn, Lid Lease, Terminate byte) []byte { + size := 12 + b := 0 + buf := make([]byte, size) + + c.ExtLock.RLock() + buf[b] = c.Extensions["RANDR"] + c.ExtLock.RUnlock() + b += 1 + + buf[b] = 46 // 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(Lid)) + b += 4 + + buf[b] = Terminate + b += 1 + + return buf +} + // GetCrtcGammaCookie is a cookie used only for GetCrtcGamma requests. type GetCrtcGammaCookie struct { *xgb.Cookie diff --git a/nexgb/res/res.go b/nexgb/res/res.go index 6b1a807..6e686b6 100644 --- a/nexgb/res/res.go +++ b/nexgb/res/res.go @@ -157,7 +157,7 @@ func ClientIdSpecListBytes(buf []byte, list []ClientIdSpec) int { type ClientIdValue struct { Spec ClientIdSpec Length uint32 - Value []uint32 // size: xgb.Pad((int(Length) * 4)) + Value []uint32 // size: xgb.Pad(((int(Length) / 4) * 4)) } // ClientIdValueRead reads a byte slice into a ClientIdValue value. @@ -170,8 +170,8 @@ func ClientIdValueRead(buf []byte, v *ClientIdValue) int { v.Length = xgb.Get32(buf[b:]) b += 4 - v.Value = make([]uint32, v.Length) - for i := 0; i < int(v.Length); i++ { + v.Value = make([]uint32, (int(v.Length) / 4)) + for i := 0; i < int((int(v.Length) / 4)); i++ { v.Value[i] = xgb.Get32(buf[b:]) b += 4 } @@ -191,7 +191,7 @@ func ClientIdValueReadList(buf []byte, dest []ClientIdValue) int { // Bytes writes a ClientIdValue value to a byte slice. func (v ClientIdValue) Bytes() []byte { - buf := make([]byte, (12 + xgb.Pad((int(v.Length) * 4)))) + buf := make([]byte, (12 + xgb.Pad(((int(v.Length) / 4) * 4)))) b := 0 { @@ -203,7 +203,7 @@ func (v ClientIdValue) Bytes() []byte { xgb.Put32(buf[b:], v.Length) b += 4 - for i := 0; i < int(v.Length); i++ { + for i := 0; i < int((int(v.Length) / 4)); i++ { xgb.Put32(buf[b:], v.Value[i]) b += 4 } @@ -227,7 +227,7 @@ func ClientIdValueListBytes(buf []byte, list []ClientIdValue) int { func ClientIdValueListSize(list []ClientIdValue) int { size := 0 for _, item := range list { - size += (12 + xgb.Pad((int(item.Length) * 4))) + size += (12 + xgb.Pad(((int(item.Length) / 4) * 4))) } return size } diff --git a/nexgb/xproto/xproto.go b/nexgb/xproto/xproto.go index 82f893d..fc3bfe0 100644 --- a/nexgb/xproto/xproto.go +++ b/nexgb/xproto/xproto.go @@ -5882,7 +5882,9 @@ type SetupRequest struct { AuthorizationProtocolDataLen uint16 // padding: 2 bytes AuthorizationProtocolName string // size: xgb.Pad((int(AuthorizationProtocolNameLen) * 1)) + // alignment gap to multiple of 4 AuthorizationProtocolData string // size: xgb.Pad((int(AuthorizationProtocolDataLen) * 1)) + // alignment gap to multiple of 4 } // SetupRequestRead reads a byte slice into a SetupRequest value. @@ -5915,6 +5917,8 @@ func SetupRequestRead(buf []byte, v *SetupRequest) int { b += int(v.AuthorizationProtocolNameLen) } + b = (b + 3) & ^3 // alignment gap + { byteString := make([]byte, v.AuthorizationProtocolDataLen) copy(byteString[:v.AuthorizationProtocolDataLen], buf[b:]) @@ -5922,6 +5926,8 @@ func SetupRequestRead(buf []byte, v *SetupRequest) int { b += int(v.AuthorizationProtocolDataLen) } + b = (b + 3) & ^3 // alignment gap + return b } @@ -5937,7 +5943,7 @@ func SetupRequestReadList(buf []byte, dest []SetupRequest) int { // Bytes writes a SetupRequest value to a byte slice. func (v SetupRequest) Bytes() []byte { - buf := make([]byte, ((12 + xgb.Pad((int(v.AuthorizationProtocolNameLen) * 1))) + xgb.Pad((int(v.AuthorizationProtocolDataLen) * 1)))) + buf := make([]byte, ((((12 + xgb.Pad((int(v.AuthorizationProtocolNameLen) * 1))) + 4) + xgb.Pad((int(v.AuthorizationProtocolDataLen) * 1))) + 4)) b := 0 buf[b] = v.ByteOrder @@ -5962,9 +5968,13 @@ func (v SetupRequest) Bytes() []byte { copy(buf[b:], v.AuthorizationProtocolName[:v.AuthorizationProtocolNameLen]) b += int(v.AuthorizationProtocolNameLen) + b = (b + 3) & ^3 // alignment gap + copy(buf[b:], v.AuthorizationProtocolData[:v.AuthorizationProtocolDataLen]) b += int(v.AuthorizationProtocolDataLen) + b = (b + 3) & ^3 // alignment gap + return buf[:b] } @@ -5984,7 +5994,7 @@ func SetupRequestListBytes(buf []byte, list []SetupRequest) int { func SetupRequestListSize(list []SetupRequest) int { size := 0 for _, item := range list { - size += ((12 + xgb.Pad((int(item.AuthorizationProtocolNameLen) * 1))) + xgb.Pad((int(item.AuthorizationProtocolDataLen) * 1))) + size += ((((12 + xgb.Pad((int(item.AuthorizationProtocolNameLen) * 1))) + 4) + xgb.Pad((int(item.AuthorizationProtocolDataLen) * 1))) + 4) } return size } |