diff options
39 files changed, 234 insertions, 157 deletions
@@ -10,7 +10,9 @@ # Go package. # My path to the X protocol XML descriptions. +ifndef XPROTO XPROTO=/usr/share/xcb +endif # All of the XML files in my /usr/share/xcb directory EXCEPT XKB. -_- # This is intended to build xgbgen and generate Go code for each supported @@ -10,10 +10,18 @@ Please see doc.go for more info. Note that unless you know you need XGB, you can probably make your life easier by using a slightly higher level library: xgbutil. +This is a fork of github.com/BurntSushi/xgb + Quick Usage =========== -go get github.com/BurntSushi/xgb -go run go/path/src/github.com/BurntSushi/xgb/examples/create-window/main.go +go get github.com/jezek/xgb +go run go/path/src/github.com/jezek/xgb/examples/create-window/main.go + +jezek's Fork +============ +I've forked the XGB repository from BurntSushi's github to be used in other project. + +Will make some changes to tailor it for my needs. BurntSushi's Fork ================= diff --git a/bigreq/bigreq.go b/bigreq/bigreq.go index 6590376..d8a5859 100644 --- a/bigreq/bigreq.go +++ b/bigreq/bigreq.go @@ -4,9 +4,9 @@ package bigreq // This file is automatically generated from bigreq.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the BIG-REQUESTS extension. diff --git a/composite/composite.go b/composite/composite.go index 1373f8b..4622cee 100644 --- a/composite/composite.go +++ b/composite/composite.go @@ -4,10 +4,10 @@ package composite // This file is automatically generated from composite.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xfixes" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xfixes" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the Composite extension. @@ -2,6 +2,7 @@ package xgb import ( "errors" + "io" ) // Cookie is the internal representation of a cookie, where one is generated @@ -80,6 +81,7 @@ func (c Cookie) Reply() ([]byte, error) { // channels. If the former arrives, the bytes are returned with a nil error. // If the latter arrives, no bytes are returned (nil) and the error received // is returned. +// Returns (nil, io.EOF) when the connection is closed. // // Unless you're building requests from bytes by hand, this method should // not be used. @@ -98,6 +100,9 @@ func (c Cookie) replyChecked() ([]byte, error) { return reply, nil case err := <-c.errorChan: return nil, err + case <-c.conn.doneRead: + // c.conn.readResponses is no more, there will be no replys or errors + return nil, io.EOF } } @@ -106,6 +111,7 @@ func (c Cookie) replyChecked() ([]byte, error) { // If the latter arrives, no bytes are returned (nil) and a nil error // is returned. (In the latter case, the corresponding error can be retrieved // from (Wait|Poll)ForEvent asynchronously.) +// Returns (nil, io.EOF) when the connection is closed. // In all honesty, you *probably* don't want to use this method. // // Unless you're building requests from bytes by hand, this method should @@ -121,6 +127,9 @@ func (c Cookie) replyUnchecked() ([]byte, error) { return reply, nil case <-c.pingChan: return nil, nil + case <-c.conn.doneRead: + // c.conn.readResponses is no more, there will be no replys or pings + return nil, io.EOF } } @@ -132,6 +141,7 @@ func (c Cookie) replyUnchecked() ([]byte, error) { // Thus, pingChan is sent a value when the *next* reply is read. // If no more replies are being processed, we force a round trip request with // GetInputFocus. +// Returns io.EOF error when the connection is closed. // // Unless you're building requests from bytes by hand, this method should // not be used. @@ -161,5 +171,8 @@ func (c Cookie) Check() error { return err case <-c.pingChan: return nil + case <-c.conn.doneRead: + // c.conn.readResponses is no more, there will be no errors or pings + return io.EOF } } diff --git a/damage/damage.go b/damage/damage.go index 26eca04..53326d9 100644 --- a/damage/damage.go +++ b/damage/damage.go @@ -4,10 +4,10 @@ package damage // This file is automatically generated from damage.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xfixes" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xfixes" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the DAMAGE extension. @@ -10,7 +10,7 @@ Most uses of XGB typically fall under the realm of window manager and GUI kit development, but other applications (like pagers, panels, tilers, etc.) may also require XGB. Moreover, it is a near certainty that if you need to work with X, xgbutil will be of great use to you as well: -https://github.com/BurntSushi/xgbutil +https://github.com/jezek/xgbutil Example @@ -23,8 +23,8 @@ accompanying documentation can be found in examples/create-window. import ( "fmt" - "github.com/BurntSushi/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb" + "github.com/jezek/xgb/xproto" ) func main() { @@ -74,8 +74,8 @@ can be found in examples/xinerama. import ( "fmt" "log" - "github.com/BurntSushi/xgb" - "github.com/BurntSushi/xgb/xinerama" + "github.com/jezek/xgb" + "github.com/jezek/xgb/xinerama" ) func main() { diff --git a/dpms/dpms.go b/dpms/dpms.go index 4bf5883..da28f1e 100644 --- a/dpms/dpms.go +++ b/dpms/dpms.go @@ -4,9 +4,9 @@ package dpms // This file is automatically generated from dpms.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the DPMS extension. diff --git a/dri2/dri2.go b/dri2/dri2.go index 820cf2b..1cc1d0a 100644 --- a/dri2/dri2.go +++ b/dri2/dri2.go @@ -4,9 +4,9 @@ package dri2 // This file is automatically generated from dri2.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the DRI2 extension. diff --git a/examples/atoms/main.go b/examples/atoms/main.go index 8985768..b94a772 100644 --- a/examples/atoms/main.go +++ b/examples/atoms/main.go @@ -9,8 +9,8 @@ import ( "runtime/pprof" "time" - "github.com/BurntSushi/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb" + "github.com/jezek/xgb/xproto" ) var ( diff --git a/examples/create-window/main.go b/examples/create-window/main.go index 73a0099..50a9bff 100644 --- a/examples/create-window/main.go +++ b/examples/create-window/main.go @@ -7,8 +7,8 @@ package main import ( "fmt" - "github.com/BurntSushi/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb" + "github.com/jezek/xgb/xproto" ) func main() { diff --git a/examples/doc.go b/examples/doc.go index 80ea5b7..20fed98 100644 --- a/examples/doc.go +++ b/examples/doc.go @@ -11,7 +11,7 @@ to events. If you're looking to query information about your window manager, get-active-window is a start. However, to do anything extensive requires a lot of boiler plate. To that end, I'd recommend use of my higher level -library, xgbutil: https://github.com/BurntSushi/xgbutil +library, xgbutil: https://github.com/jezek/xgbutil There are also examples of using the Xinerama and RandR extensions, if you're interested in querying information about your active heads. In RandR's case, diff --git a/examples/get-active-window/main.go b/examples/get-active-window/main.go index 48e020c..37f374c 100644 --- a/examples/get-active-window/main.go +++ b/examples/get-active-window/main.go @@ -6,8 +6,8 @@ import ( "fmt" "log" - "github.com/BurntSushi/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb" + "github.com/jezek/xgb/xproto" ) func main() { diff --git a/examples/randr/main.go b/examples/randr/main.go index e349144..13b934a 100644 --- a/examples/randr/main.go +++ b/examples/randr/main.go @@ -14,9 +14,9 @@ import ( "fmt" "log" - "github.com/BurntSushi/xgb" - "github.com/BurntSushi/xgb/randr" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb" + "github.com/jezek/xgb/randr" + "github.com/jezek/xgb/xproto" ) func main() { diff --git a/examples/xinerama/main.go b/examples/xinerama/main.go index 896bb63..a7e1531 100644 --- a/examples/xinerama/main.go +++ b/examples/xinerama/main.go @@ -5,8 +5,8 @@ import ( "fmt" "log" - "github.com/BurntSushi/xgb" - "github.com/BurntSushi/xgb/xinerama" + "github.com/jezek/xgb" + "github.com/jezek/xgb/xinerama" ) func main() { @@ -4,9 +4,9 @@ package ge // This file is automatically generated from ge.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the Generic Event Extension extension. @@ -4,9 +4,9 @@ package glx // This file is automatically generated from glx.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the GLX extension. diff --git a/randr/randr.go b/randr/randr.go index 021c011..bc62d73 100644 --- a/randr/randr.go +++ b/randr/randr.go @@ -4,10 +4,10 @@ package randr // This file is automatically generated from randr.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/render" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/render" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the RANDR extension. diff --git a/record/record.go b/record/record.go index 5469170..419587f 100644 --- a/record/record.go +++ b/record/record.go @@ -4,9 +4,9 @@ package record // This file is automatically generated from record.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the RECORD extension. diff --git a/render/render.go b/render/render.go index e15bd67..223162a 100644 --- a/render/render.go +++ b/render/render.go @@ -4,9 +4,9 @@ package render // This file is automatically generated from render.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the RENDER extension. @@ -4,9 +4,9 @@ package res // This file is automatically generated from res.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the X-Resource extension. diff --git a/screensaver/screensaver.go b/screensaver/screensaver.go index 418576c..6854505 100644 --- a/screensaver/screensaver.go +++ b/screensaver/screensaver.go @@ -4,9 +4,9 @@ package screensaver // This file is automatically generated from screensaver.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the MIT-SCREEN-SAVER extension. diff --git a/shape/shape.go b/shape/shape.go index 7069f7e..42b3f9f 100644 --- a/shape/shape.go +++ b/shape/shape.go @@ -4,9 +4,9 @@ package shape // This file is automatically generated from shape.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the SHAPE extension. @@ -4,9 +4,9 @@ package shm // This file is automatically generated from shm.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the MIT-SHM extension. diff --git a/xcmisc/xcmisc.go b/xcmisc/xcmisc.go index 1778057..93dd20f 100644 --- a/xcmisc/xcmisc.go +++ b/xcmisc/xcmisc.go @@ -4,9 +4,9 @@ package xcmisc // This file is automatically generated from xc_misc.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the XC-MISC extension. diff --git a/xevie/xevie.go b/xevie/xevie.go index 180312b..f0ddd31 100644 --- a/xevie/xevie.go +++ b/xevie/xevie.go @@ -4,9 +4,9 @@ package xevie // This file is automatically generated from xevie.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the XEVIE extension. diff --git a/xf86dri/xf86dri.go b/xf86dri/xf86dri.go index 51c9322..bc67e9b 100644 --- a/xf86dri/xf86dri.go +++ b/xf86dri/xf86dri.go @@ -4,9 +4,9 @@ package xf86dri // This file is automatically generated from xf86dri.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the XFree86-DRI extension. diff --git a/xf86vidmode/xf86vidmode.go b/xf86vidmode/xf86vidmode.go index 2829fd6..6bd3232 100644 --- a/xf86vidmode/xf86vidmode.go +++ b/xf86vidmode/xf86vidmode.go @@ -4,9 +4,9 @@ package xf86vidmode // This file is automatically generated from xf86vidmode.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the XFree86-VidModeExtension extension. diff --git a/xfixes/xfixes.go b/xfixes/xfixes.go index 0f9e4b0..5751527 100644 --- a/xfixes/xfixes.go +++ b/xfixes/xfixes.go @@ -4,11 +4,11 @@ package xfixes // This file is automatically generated from xfixes.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/render" - "github.com/BurntSushi/xgb/shape" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/render" + "github.com/jezek/xgb/shape" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the XFIXES extension. @@ -60,7 +60,8 @@ type Conn struct { xidChan chan xid seqChan chan uint16 reqChan chan *request - closing chan chan struct{} + doneSend chan struct{} + doneRead chan struct{} // ExtLock is a lock used whenever new extensions are initialized. // It should not be used. It is exported for use in the extension @@ -75,11 +76,13 @@ type Conn struct { // NewConn creates a new connection instance. It initializes locks, data // structures, and performs the initial handshake. (The code for the handshake // has been relegated to conn.go.) +// It is up to user to close connection with Close() method to finish all unfinished requests and clean up spawned goroutines. +// If the connection unexpectedly closes itself and WaitForEvent() returns "nil, nil", everything is cleaned by that moment, but nothing bad happens if you call Close() after. func NewConn() (*Conn, error) { return NewConnDisplay("") } -// NewConnDisplay is just like NewConn, but allows a specific DISPLAY +// NewConnDisplay is just like NewConn (see closing instructions), but allows a specific DISPLAY // string to be used. // If 'display' is empty it will be taken from os.Getenv("DISPLAY"). // @@ -89,55 +92,60 @@ func NewConn() (*Conn, error) { // NewConn("hostname:2.1") -> net.Dial("tcp", "", "hostname:6002") // NewConn("tcp/hostname:1.0") -> net.Dial("tcp", "", "hostname:6001") func NewConnDisplay(display string) (*Conn, error) { - conn := &Conn{} + c := &Conn{} // First connect. This reads authority, checks DISPLAY environment // variable, and loads the initial Setup info. - err := conn.connect(display) + err := c.connect(display) if err != nil { return nil, err } - return postNewConn(conn) + return postNewConn(c) } -// NewConnDisplay is just like NewConn, but allows a specific net.Conn +// NewConnNet is just like NewConn (see closing instructions), but allows a specific net.Conn // to be used. func NewConnNet(netConn net.Conn) (*Conn, error) { - conn := &Conn{} + c := &Conn{} // First connect. This reads authority, checks DISPLAY environment // variable, and loads the initial Setup info. - err := conn.connectNet(netConn) + err := c.connectNet(netConn) if err != nil { return nil, err } - return postNewConn(conn) + return postNewConn(c) } -func postNewConn(conn *Conn) (*Conn, error) { - conn.Extensions = make(map[string]byte) +func postNewConn(c *Conn) (*Conn, error) { + c.Extensions = make(map[string]byte) - conn.cookieChan = make(chan *Cookie, cookieBuffer) - conn.xidChan = make(chan xid, xidBuffer) - conn.seqChan = make(chan uint16, seqBuffer) - conn.reqChan = make(chan *request, reqBuffer) - conn.eventChan = make(chan eventOrError, eventBuffer) - conn.closing = make(chan chan struct{}, 1) + c.cookieChan = make(chan *Cookie, cookieBuffer) + c.xidChan = make(chan xid, xidBuffer) + c.seqChan = make(chan uint16, seqBuffer) + c.reqChan = make(chan *request, reqBuffer) + c.eventChan = make(chan eventOrError, eventBuffer) + c.doneSend = make(chan struct{}) + c.doneRead = make(chan struct{}) - go conn.generateXIds() - go conn.generateSeqIds() - go conn.sendRequests() - go conn.readResponses() + go c.generateXIds() + go c.generateSeqIds() + go c.sendRequests() + go c.readResponses() - return conn, nil + return c, nil } // Close gracefully closes the connection to the X server. +// When everything is cleaned up, the WaitForEvent method will return (nil, nil) func (c *Conn) Close() { - close(c.reqChan) + select { + case c.reqChan <- nil: + case <-c.doneSend: + } } // Event is an interface that can contain any of the events returned by the @@ -196,8 +204,12 @@ type eventOrError interface{} // If you need identifiers, use the appropriate constructor. // e.g., For a window id, use xproto.NewWindowId. For // a new pixmap id, use xproto.NewPixmapId. And so on. +// Returns (0, io.EOF) when the connection is closed. func (c *Conn) NewId() (uint32, error) { - xid := <-c.xidChan + xid, ok := <-c.xidChan + if !ok { + return 0, io.EOF + } if xid.err != nil { return 0, xid.err } @@ -217,8 +229,8 @@ type xid struct { // This needs to be updated to use the XC Misc extension once we run out of // new ids. // Thanks to libxcb/src/xcb_xid.c. This code is greatly inspired by it. -func (conn *Conn) generateXIds() { - defer close(conn.xidChan) +func (c *Conn) generateXIds() { + defer close(c.xidChan) // This requires some explanation. From the horse's mouth: // "The resource-id-mask contains a single contiguous set of bits (at least @@ -236,23 +248,30 @@ func (conn *Conn) generateXIds() { // 00111000 & 11001000 = 00001000. // And we use that value to increment the last resource id to get a new one. // (And then, of course, we OR it with resource-id-base.) - inc := conn.setupResourceIdMask & -conn.setupResourceIdMask - max := conn.setupResourceIdMask + inc := c.setupResourceIdMask & -c.setupResourceIdMask + max := c.setupResourceIdMask last := uint32(0) for { - // TODO: Use the XC Misc extension to look for released ids. + id := xid{} if last > 0 && last >= max-inc+1 { - conn.xidChan <- xid{ - id: 0, - err: errors.New("There are no more available resource" + - "identifiers."), + // TODO: Use the XC Misc extension to look for released ids. + id = xid{ + id: 0, + err: errors.New("There are no more available resource identifiers."), + } + } else { + last += inc + id = xid{ + id: last | c.setupResourceIdBase, + err: nil, } } - last += inc - conn.xidChan <- xid{ - id: last | conn.setupResourceIdBase, - err: nil, + select { + case c.xidChan <- id: + case <-c.doneSend: + // c.sendRequests is down and since this id is used by requests, we don't need this goroutine running anymore. + return } } } @@ -275,11 +294,16 @@ func (c *Conn) generateSeqIds() { seqid := uint16(1) for { - c.seqChan <- seqid - if seqid == uint16((1<<16)-1) { - seqid = 0 - } else { - seqid++ + select { + case c.seqChan <- seqid: + if seqid == uint16((1<<16)-1) { + seqid = 0 + } else { + seqid++ + } + case <-c.doneSend: + // c.sendRequests is down and since only that function uses sequence ids (via newSequenceId method), we don't need this goroutine running anymore. + return } } } @@ -315,8 +339,19 @@ type request struct { // edits the generated code for the request you want to issue. func (c *Conn) NewRequest(buf []byte, cookie *Cookie) { seq := make(chan struct{}) - c.reqChan <- &request{buf: buf, cookie: cookie, seq: seq} - <-seq + select { + case c.reqChan <- &request{buf: buf, cookie: cookie, seq: seq}: + // request is in buffer + // wait until request is processed or connection is closed + select { + case <-seq: + // request was successfully sent to X server + case <-c.doneSend: + // c.sendRequests is down, your request was not handled + } + case <-c.doneSend: + // c.sendRequests is down, nobody is listening to your requests + } } // sendRequests is run as a single goroutine that takes requests and writes @@ -324,28 +359,45 @@ func (c *Conn) NewRequest(buf []byte, cookie *Cookie) { // It is meant to be run as its own goroutine. func (c *Conn) sendRequests() { defer close(c.cookieChan) + defer c.conn.Close() + defer close(c.doneSend) - for req := range c.reqChan { - // ho there! if the cookie channel is nearly full, force a round - // trip to clear out the cookie buffer. - // Note that we circumvent the request channel, because we're *in* - // the request channel. - if len(c.cookieChan) == cookieBuffer-1 { - if err := c.noop(); err != nil { - // Shut everything down. - break + for { + select { + case req := <-c.reqChan: + if req == nil { + // a request by c.Close() to gracefully exit + // Flush the response reading goroutine. + if err := c.noop(); err != nil { + c.conn.Close() + <-c.doneRead + } + return + } + // ho there! if the cookie channel is nearly full, force a round + // trip to clear out the cookie buffer. + // Note that we circumvent the request channel, because we're *in* + // the request channel. + if len(c.cookieChan) == cookieBuffer-1 { + if err := c.noop(); err != nil { + // Shut everything down. + c.conn.Close() + <-c.doneRead + return + } + } + req.cookie.Sequence = c.newSequenceId() + c.cookieChan <- req.cookie + if err := c.writeBuffer(req.buf); err != nil { + c.conn.Close() + <-c.doneRead + return } + close(req.seq) + case <-c.doneRead: + return } - req.cookie.Sequence = c.newSequenceId() - c.cookieChan <- req.cookie - c.writeBuffer(req.buf) - close(req.seq) } - response := make(chan struct{}) - c.closing <- response - c.noop() // Flush the response reading goroutine, ignore error. - <-response - c.conn.Close() } // noop circumvents the usual request sending goroutines and forces a round @@ -366,9 +418,8 @@ func (c *Conn) writeBuffer(buf []byte) error { if _, err := c.conn.Write(buf); err != nil { Logger.Printf("A write error is unrecoverable: %s", err) return err - } else { - return nil } + return nil } // readResponses is a goroutine that reads events, errors and @@ -382,6 +433,8 @@ func (c *Conn) writeBuffer(buf []byte) error { // Finally, cookies that came "before" this reply are always cleaned up. func (c *Conn) readResponses() { defer close(c.eventChan) + defer c.conn.Close() + defer close(c.doneRead) var ( err Error @@ -390,20 +443,18 @@ func (c *Conn) readResponses() { ) for { - select { - case respond := <-c.closing: - respond <- struct{}{} - return - default: - } - buf := make([]byte, 32) err, seq = nil, 0 if _, err := io.ReadFull(c.conn, buf); err != nil { + select { + case <-c.doneSend: + // gracefully closing + return + default: + } Logger.Printf("A read error is unrecoverable: %s", err) c.eventChan <- err - c.Close() - continue + return } switch buf[0] { case 0: // This is an error @@ -432,8 +483,7 @@ func (c *Conn) readResponses() { if _, err := io.ReadFull(c.conn, biggerBuf[32:]); err != nil { Logger.Printf("A read error is unrecoverable: %s", err) c.eventChan <- err - c.Close() - continue + return } replyBytes = biggerBuf } else { @@ -522,10 +572,14 @@ func processEventOrError(everr eventOrError) (Event, Error) { return ee, nil case Error: return nil, ee + case error: + // c.conn read error + case nil: + // c.eventChan is closed default: Logger.Printf("Invalid event/error type: %T", everr) - return nil, nil } + return nil, nil } // WaitForEvent returns the next event from the server. diff --git a/xgbgen/context.go b/xgbgen/context.go index f18fd67..755cf6e 100644 --- a/xgbgen/context.go +++ b/xgbgen/context.go @@ -64,10 +64,10 @@ func (c *Context) Morph(xmlBytes []byte) { // Write imports. We always need to import at least xgb. // We also need to import xproto if it's an extension. c.Putln("import (") - c.Putln("\"github.com/BurntSushi/xgb\"") + c.Putln("\"github.com/jezek/xgb\"") c.Putln("") if c.protocol.isExt() { - c.Putln("\"github.com/BurntSushi/xgb/xproto\"") + c.Putln("\"github.com/jezek/xgb/xproto\"") } sort.Sort(Protocols(c.protocol.Imports)) @@ -76,7 +76,7 @@ func (c *Context) Morph(xmlBytes []byte) { if imp.Name == "xproto" { continue } - c.Putln("\"github.com/BurntSushi/xgb/%s\"", imp.Name) + c.Putln("\"github.com/jezek/xgb/%s\"", imp.Name) } c.Putln(")") c.Putln("") diff --git a/xinerama/xinerama.go b/xinerama/xinerama.go index ec97406..580387c 100644 --- a/xinerama/xinerama.go +++ b/xinerama/xinerama.go @@ -4,9 +4,9 @@ package xinerama // This file is automatically generated from xinerama.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the XINERAMA extension. diff --git a/xprint/xprint.go b/xprint/xprint.go index d692aed..97e06e1 100644 --- a/xprint/xprint.go +++ b/xprint/xprint.go @@ -4,9 +4,9 @@ package xprint // This file is automatically generated from xprint.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the XpExtension extension. diff --git a/xproto/xproto.go b/xproto/xproto.go index 716c49b..8d7e51b 100644 --- a/xproto/xproto.go +++ b/xproto/xproto.go @@ -4,7 +4,7 @@ package xproto // This file is automatically generated from xproto.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" ) // Setup parses the setup bytes retrieved when diff --git a/xproto/xproto_test.go b/xproto/xproto_test.go index a5bec71..f8080bf 100644 --- a/xproto/xproto_test.go +++ b/xproto/xproto_test.go @@ -26,7 +26,7 @@ import ( "testing" "time" - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" ) // The X connection used throughout testing. diff --git a/xselinux/xselinux.go b/xselinux/xselinux.go index 1afcc10..68d55ea 100644 --- a/xselinux/xselinux.go +++ b/xselinux/xselinux.go @@ -4,9 +4,9 @@ package xselinux // This file is automatically generated from xselinux.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the SELinux extension. diff --git a/xtest/xtest.go b/xtest/xtest.go index 182760e..c11cfc6 100644 --- a/xtest/xtest.go +++ b/xtest/xtest.go @@ -4,9 +4,9 @@ package xtest // This file is automatically generated from xtest.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the XTEST extension. @@ -4,10 +4,10 @@ package xv // This file is automatically generated from xv.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/shm" - "github.com/BurntSushi/xgb/xproto" + "github.com/jezek/xgb/shm" + "github.com/jezek/xgb/xproto" ) // Init must be called before using the XVideo extension. diff --git a/xvmc/xvmc.go b/xvmc/xvmc.go index b943fa0..3f61416 100644 --- a/xvmc/xvmc.go +++ b/xvmc/xvmc.go @@ -4,10 +4,10 @@ package xvmc // This file is automatically generated from xvmc.xml. Edit at your peril! import ( - "github.com/BurntSushi/xgb" + "github.com/jezek/xgb" - "github.com/BurntSushi/xgb/xproto" - "github.com/BurntSushi/xgb/xv" + "github.com/jezek/xgb/xproto" + "github.com/jezek/xgb/xv" ) // Init must be called before using the XVideo-MotionCompensation extension. |
