diff options
Diffstat (limited to 'xproto/xproto.go')
-rw-r--r-- | xproto/xproto.go | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/xproto/xproto.go b/xproto/xproto.go new file mode 100644 index 0000000..3791ae2 --- /dev/null +++ b/xproto/xproto.go @@ -0,0 +1,177 @@ +package xproto + +import ( + "xgob" +) + +type Atom uint32 +type Window uint32 + +type QueryTreeReply struct { + Error *xgob.Error + Root, Parent Window + Children []Window +} + +type InternAtomReply struct { + Error *xgob.Error + Atom Atom +} + +type GetPropertyReply struct { + Error *xgob.Error + Format uint8 + Type Atom + BytesAfter uint32 + Value []byte +} + +func appendUint16(buf []byte, val uint16) []byte { + buf = append(buf, uint8(val>>8)) + buf = append(buf, uint8(val&0xFF)) + return buf +} + +func appendUint32(buf []byte, val uint32) []byte { + buf = append(buf, uint8(val>>24)) + buf = append(buf, uint8(val>>16)) + buf = append(buf, uint8(val>>8)) + buf = append(buf, uint8(val&0xFF)) + return buf +} + +func getUint16(buf []byte) uint16 { + var rv uint16 + rv = uint16(buf[0]) << 8 + rv |= uint16(buf[1]) + return rv +} + +func getUint32(buf []byte) uint32 { + var rv uint32 + rv = uint32(buf[0]) << 24 + rv |= uint32(buf[1]) << 16 + rv |= uint32(buf[2]) << 8 + rv |= uint32(buf[3]) + return rv +} + +func queryTreeReply(data interface{}, out chan QueryTreeReply) { + var rv QueryTreeReply + + switch d := data.(type) { + case xgob.Error: + rv.Error = &d + case xgob.Reply: + rep := d.Remainder + rv.Root = Window(getUint32(rep)) + rep = rep[4:] + rv.Parent = Window(getUint32(rep)) + rep = rep[4:] + children_len := getUint16(rep) + rep = rep[2:] + rv.Children = make([]Window, 0, children_len) + rep = rep[14:] // Pad + + for i := uint16(0); i < children_len; i++ { + rv.Children = append(rv.Children, Window(getUint32(rep))) + rep = rep[4:] + } + } + out <- rv +} + +func QueryTree(c *xgob.Connection, window Window) chan QueryTreeReply { + req := make([]byte, 0, 8) + + req = append(req, 15) // Opcode + req = append(req, 0) // Pad + req = appendUint16(req, 2) // Length + req = appendUint32(req, uint32(window)) + + rv := make(chan QueryTreeReply, 1) + c.WriteReplyRequestCallback(req, func(in interface{}) { queryTreeReply(in, rv) }) + + return rv +} + +func internAtomReply(data interface{}, out chan InternAtomReply) { + var rv InternAtomReply + + switch d := data.(type) { + case xgob.Error: + rv.Error = &d + case xgob.Reply: + rv.Atom = Atom(getUint32(d.Remainder)) + } + out <- rv +} + +func InternAtom(c *xgob.Connection, only_if_exists bool, name string) chan InternAtomReply { + length := len(name) + 8 + length += -length & 3 + + req := make([]byte, 0, length) + + req = append(req, 16) // Opcode + if only_if_exists { + req = append(req, 1) + } else { + req = append(req, 0) + } + req = appendUint16(req, uint16(length/4)) + req = appendUint16(req, uint16(len(name))) + req = appendUint16(req, 0) // Pad + + req = req[0:length] // Expand for name + copy(req[8:], name) + + rv := make(chan InternAtomReply, 1) + c.WriteReplyRequestCallback(req, func(in interface{}) { internAtomReply(in, rv) }) + + return rv +} + +func getPropertyReply(data interface{}, out chan GetPropertyReply) { + var rv GetPropertyReply + + switch d := data.(type) { + case xgob.Error: + rv.Error = &d + case xgob.Reply: + rv.Format = d.Aux + rep := d.Remainder + rv.Type = Atom(getUint32(rep)) + rep = rep[4:] + rv.BytesAfter = getUint32(rep) + rep = rep[4:] + value_len := getUint32(rep) + rep = rep[4:] + rep = rep[12:] // Pad + rv.Value = rep[:value_len] + rep = rep[value_len:] + } + out <- rv +} + +func GetProperty(c *xgob.Connection, delete bool, window Window, property Atom, _type Atom, long_offset uint32, long_length uint32) chan GetPropertyReply { + req := make([]byte, 0, 6*4) + + req = append(req, 20) // Opcode + if delete { + req = append(req, 1) + } else { + req = append(req, 0) + } + req = appendUint16(req, 6) + req = appendUint32(req, uint32(window)) + req = appendUint32(req, uint32(property)) + req = appendUint32(req, uint32(_type)) + req = appendUint32(req, long_offset) + req = appendUint32(req, long_length) + + rv := make(chan GetPropertyReply, 1) + c.WriteReplyRequestCallback(req, func(in interface{}) { getPropertyReply(in, rv) }) + + return rv +} |