Skip to content

Commit

Permalink
reworking xgb. cleaned up connection stuff a little. making new xid g…
Browse files Browse the repository at this point in the history
…eneration cleaner and use goroutines for it.
  • Loading branch information
Andrew Gallant (Ocelot) authored and Andrew Gallant (Ocelot) committed May 4, 2012
1 parent 9028aaf commit 9f44c62
Show file tree
Hide file tree
Showing 5 changed files with 317 additions and 175 deletions.
6 changes: 4 additions & 2 deletions auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ func getString(r io.Reader, b []byte) (string, error) {

// readAuthority reads the X authority file for the DISPLAY.
// If hostname == "" or hostname == "localhost",
// readAuthority uses the system's hostname (as returned by os.Hostname) instead.
func readAuthority(hostname, display string) (name string, data []byte, err error) {
// then use the system's hostname (as returned by os.Hostname) instead.
func readAuthority(hostname, display string) (
name string, data []byte, err error) {

// b is a scratch buffer to use and should be at least 256 bytes long
// (i.e. it should be able to hold a hostname).
var b [256]byte
Expand Down
161 changes: 161 additions & 0 deletions conn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package xgb

import (
"errors"
"fmt"
"io"
"net"
"os"
"strconv"
"strings"
)

// connect connects to the X server given in the 'display' string.
// If 'display' is empty it will be taken from os.Getenv("DISPLAY").
// Note that you should read and understand the "Connection Setup" of the
// X Protocol Reference Manual before changing this function:
// http://goo.gl/4zGQg
func (c *Conn) connect(display string) error {
err := c.dial(display)
if err != nil {
return err
}

// Get authentication data
authName, authData, err := readAuthority(c.host, c.display)
noauth := false
if err != nil {
fmt.Fprintf(os.Stderr, "Could not get authority info: %v\n", err)
fmt.Fprintf(os.Stderr, "Trying connection without authority info...\n")
authName = ""
authData = []byte{}
noauth = true
}

// Assume that the authentication protocol is "MIT-MAGIC-COOKIE-1".
if !noauth && (authName != "MIT-MAGIC-COOKIE-1" || len(authData) != 16) {
return errors.New("unsupported auth protocol " + authName)
}

buf := make([]byte, 12+pad(len(authName))+pad(len(authData)))
buf[0] = 0x6c
buf[1] = 0
Put16(buf[2:], 11)
Put16(buf[4:], 0)
Put16(buf[6:], uint16(len(authName)))
Put16(buf[8:], uint16(len(authData)))
Put16(buf[10:], 0)
copy(buf[12:], []byte(authName))
copy(buf[12+pad(len(authName)):], authData)
if _, err = c.conn.Write(buf); err != nil {
return err
}

head := make([]byte, 8)
if _, err = io.ReadFull(c.conn, head[0:8]); err != nil {
return err
}
code := head[0]
reasonLen := head[1]
major := Get16(head[2:])
minor := Get16(head[4:])
dataLen := Get16(head[6:])

if major != 11 || minor != 0 {
return errors.New(fmt.Sprintf("x protocol version mismatch: %d.%d",
major, minor))
}

buf = make([]byte, int(dataLen)*4+8, int(dataLen)*4+8)
copy(buf, head)
if _, err = io.ReadFull(c.conn, buf[8:]); err != nil {
return err
}

if code == 0 {
reason := buf[8 : 8+reasonLen]
return errors.New(fmt.Sprintf("x protocol authentication refused: %s",
string(reason)))
}

ReadSetupInfo(buf, &c.Setup)

if c.defaultScreen >= len(c.Setup.Roots) {
c.defaultScreen = 0
}

return nil
}

func (c *Conn) dial(display string) error {
if len(display) == 0 {
display = os.Getenv("DISPLAY")
}

display0 := display
if len(display) == 0 {
return errors.New("empty display string")
}

colonIdx := strings.LastIndex(display, ":")
if colonIdx < 0 {
return errors.New("bad display string: " + display0)
}

var protocol, socket string

if display[0] == '/' {
socket = display[0:colonIdx]
} else {
slashIdx := strings.LastIndex(display, "/")
if slashIdx >= 0 {
protocol = display[0:slashIdx]
c.host = display[slashIdx+1 : colonIdx]
} else {
c.host = display[0:colonIdx]
}
}

display = display[colonIdx+1 : len(display)]
if len(display) == 0 {
return errors.New("bad display string: " + display0)
}

var scr string
dotIdx := strings.LastIndex(display, ".")
if dotIdx < 0 {
c.display = display[0:]
} else {
c.display = display[0:dotIdx]
scr = display[dotIdx+1:]
}

dispnum, err := strconv.Atoi(c.display)
if err != nil || dispnum < 0 {
return errors.New("bad display string: " + display0)
}

if len(scr) != 0 {
c.defaultScreen, err = strconv.Atoi(scr)
if err != nil {
return errors.New("bad display string: " + display0)
}
}

// Connect to server
if len(socket) != 0 {
c.conn, err = net.Dial("unix", socket+":"+c.display)
} else if len(c.host) != 0 {
if protocol == "" {
protocol = "tcp"
}
c.conn, err = net.Dial(protocol, c.host+":"+strconv.Itoa(6000+dispnum))
} else {
c.conn, err = net.Dial("unix", "/tmp/.X11-unix/X"+c.display)
}

if err != nil {
return errors.New("cannot connect to " + display0 + ": " + err.Error())
}
return nil
}
27 changes: 27 additions & 0 deletions examples/atom.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package main

import (
// "fmt"
"log"

"github.com/BurntSushi/xgb"
)

func init() {
log.SetFlags(0)
}

func main() {
X, err := xgb.NewConn()
if err != nil {
log.Fatal(err)
}

aname := "_NET_ACTIVE_WINDOW"
atom, err := X.InternAtom(true, uint16(len(aname)), aname)
if err != nil {
log.Fatal(err)
}
log.Printf("%d", atom.Atom)
}

39 changes: 39 additions & 0 deletions examples/property.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package main

import (
"log"

"github.com/BurntSushi/xgb"
)

func init() {
log.SetFlags(0)
}

func get32(buf []byte) uint32 {
v := uint32(buf[0])
v |= uint32(buf[1]) << 8
v |= uint32(buf[2]) << 16
v |= uint32(buf[3]) << 24
return v
}

func main() {
X, err := xgb.NewConn()
if err != nil {
log.Fatal(err)
}

root := X.DefaultScreen().Root

aname := "_NET_ACTIVE_WINDOW"
atom, err := X.InternAtom(true, uint16(len(aname)), aname)
if err != nil {
log.Fatal(err)
}

reply, err := X.GetProperty(false, root, atom.Atom, xgb.GetPropertyTypeAny,
0, (1<<32)-1)
log.Printf("%X", get32(reply.Value))
}

Loading

0 comments on commit 9f44c62

Please sign in to comment.