summaryrefslogtreecommitdiff
path: root/xproto/xproto.go
diff options
context:
space:
mode:
Diffstat (limited to 'xproto/xproto.go')
-rw-r--r--xproto/xproto.go177
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
+}