update dep pkg

This commit is contained in:
vcaesar 2018-07-10 20:16:43 +08:00
parent 186df36c2c
commit 2a6299df59
61 changed files with 22384 additions and 73 deletions

28
Gopkg.lock generated
View File

@ -1,6 +1,28 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
branch = "master"
name = "github.com/BurntSushi/xgb"
packages = [
".",
"shape",
"xinerama",
"xproto"
]
revision = "27f122750802c950b2c869a5b63dafcf590ced95"
[[projects]]
branch = "master"
name = "github.com/BurntSushi/xgbutil"
packages = [
".",
"ewmh",
"xevent",
"xprop"
]
revision = "f7c97cef3b4e6c88280a5a7091c3314e815ca243"
[[projects]]
name = "github.com/StackExchange/wmi"
packages = ["."]
@ -51,7 +73,7 @@
branch = "master"
name = "golang.org/x/image"
packages = ["bmp"]
revision = "cc896f830cedae125428bc9fe1b0362aa91b3fb1"
revision = "c73c2afc3b812cdd6385de5a50616511c4a3d458"
[[projects]]
branch = "master"
@ -60,11 +82,11 @@
"unix",
"windows"
]
revision = "151529c776cdc58ddbe7963ba9af779f3577b419"
revision = "1b2967e3c290b7c545b3db0deeda16e9be4f98a2"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "b0823ba26a4b2c75bed4b3f87b65fcf3b8f7dcbe253b3f5449e7d39546493625"
inputs-digest = "f6de864b2bfc793263e5bb920647127b4fbbca0daac0da4f8951f5844570f035"
solver-name = "gps-cdcl"
solver-version = 1

2
vendor/github.com/BurntSushi/xgb/.gitignore generated vendored Normal file
View File

@ -0,0 +1,2 @@
xgbgen/xgbgen
.*.swp

18
vendor/github.com/BurntSushi/xgb/AUTHORS generated vendored Normal file
View File

@ -0,0 +1,18 @@
Andrew Gallant is the maintainer of this fork. What follows is the original
list of authors for the x-go-binding.
# This is the official list of XGB authors for copyright purposes.
# This file is distinct from the CONTRIBUTORS files.
# See the latter for an explanation.
# Names should be added to this file as
# Name or Organization <email address>
# The email address is not required for organizations.
# Please keep the list sorted.
Anthony Martin <ality@pbrane.org>
Firmansyah Adiputra <frm.adiputra@gmail.com>
Google Inc.
Scott Lawrence <bytbox@gmail.com>
Tor Andersson <tor.andersson@gmail.com>

39
vendor/github.com/BurntSushi/xgb/CONTRIBUTORS generated vendored Normal file
View File

@ -0,0 +1,39 @@
Andrew Gallant is the maintainer of this fork. What follows is the original
list of contributors for the x-go-binding.
# This is the official list of people who can contribute
# (and typically have contributed) code to the XGB repository.
# The AUTHORS file lists the copyright holders; this file
# lists people. For example, Google employees are listed here
# but not in AUTHORS, because Google holds the copyright.
#
# The submission process automatically checks to make sure
# that people submitting code are listed in this file (by email address).
#
# Names should be added to this file only after verifying that
# the individual or the individual's organization has agreed to
# the appropriate Contributor License Agreement, found here:
#
# http://code.google.com/legal/individual-cla-v1.0.html
# http://code.google.com/legal/corporate-cla-v1.0.html
#
# The agreement for individuals can be filled out on the web.
#
# When adding J Random Contributor's name to this file,
# either J's name or J's organization's name should be
# added to the AUTHORS file, depending on whether the
# individual or corporate CLA was used.
# Names should be added to this file like so:
# Name <email address>
# Please keep the list sorted.
Anthony Martin <ality@pbrane.org>
Firmansyah Adiputra <frm.adiputra@gmail.com>
Ian Lance Taylor <iant@golang.org>
Nigel Tao <nigeltao@golang.org>
Robert Griesemer <gri@golang.org>
Russ Cox <rsc@golang.org>
Scott Lawrence <bytbox@gmail.com>
Tor Andersson <tor.andersson@gmail.com>

42
vendor/github.com/BurntSushi/xgb/LICENSE generated vendored Normal file
View File

@ -0,0 +1,42 @@
// Copyright (c) 2009 The XGB Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Subject to the terms and conditions of this License, Google hereby
// grants to You a perpetual, worldwide, non-exclusive, no-charge,
// royalty-free, irrevocable (except as stated in this section) patent
// license to make, have made, use, offer to sell, sell, import, and
// otherwise transfer this implementation of XGB, where such license
// applies only to those patent claims licensable by Google that are
// necessarily infringed by use of this implementation of XGB. If You
// institute patent litigation against any entity (including a
// cross-claim or counterclaim in a lawsuit) alleging that this
// implementation of XGB or a Contribution incorporated within this
// implementation of XGB constitutes direct or contributory patent
// infringement, then any patent licenses granted to You under this
// License for this implementation of XGB shall terminate as of the date
// such litigation is filed.

78
vendor/github.com/BurntSushi/xgb/Makefile generated vendored Normal file
View File

@ -0,0 +1,78 @@
# This Makefile is used by the developer. It is not needed in any way to build
# a checkout of the XGB repository.
# It will be useful, however, if you are hacking at the code generator.
# i.e., after making a change to the code generator, run 'make' in the
# xgb directory. This will build xgbgen and regenerate each sub-package.
# 'make test' will then run any appropriate tests (just tests xproto right now).
# 'make bench' will test a couple of benchmarks.
# 'make build-all' will then try to build each extension. This isn't strictly
# necessary, but it's a good idea to make sure each sub-package is a valid
# Go package.
# My path to the X protocol XML descriptions.
XPROTO=/usr/share/xcb
# 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
# extension.
all: build-xgbgen \
bigreq.xml composite.xml damage.xml dpms.xml dri2.xml \
ge.xml glx.xml randr.xml record.xml render.xml res.xml \
screensaver.xml shape.xml shm.xml xc_misc.xml \
xevie.xml xf86dri.xml xf86vidmode.xml xfixes.xml xinerama.xml \
xprint.xml xproto.xml xselinux.xml xtest.xml \
xvmc.xml xv.xml
build-xgbgen:
(cd xgbgen && go build)
# Builds each individual sub-package to make sure its valid Go code.
build-all: bigreq.b composite.b damage.b dpms.b dri2.b ge.b glx.b randr.b \
record.b render.b res.b screensaver.b shape.b shm.b xcmisc.b \
xevie.b xf86dri.b xf86vidmode.b xfixes.b xinerama.b \
xprint.b xproto.b xselinux.b xtest.b xv.b xvmc.b
%.b:
(cd $* ; go build)
# Installs each individual sub-package.
install: bigreq.i composite.i damage.i dpms.i dri2.i ge.i glx.i randr.i \
record.i render.i res.i screensaver.i shape.i shm.i xcmisc.i \
xevie.i xf86dri.i xf86vidmode.i xfixes.i xinerama.i \
xprint.i xproto.i xselinux.i xtest.i xv.i xvmc.i
go install
%.i:
(cd $* ; go install)
# xc_misc is special because it has an underscore.
# There's probably a way to do this better, but Makefiles aren't my strong suit.
xc_misc.xml: build-xgbgen
mkdir -p xcmisc
xgbgen/xgbgen --proto-path $(XPROTO) $(XPROTO)/xc_misc.xml > xcmisc/xcmisc.go
%.xml: build-xgbgen
mkdir -p $*
xgbgen/xgbgen --proto-path $(XPROTO) $(XPROTO)/$*.xml > $*/$*.go
# Just test the xproto core protocol for now.
test:
(cd xproto ; go test)
# Force all xproto benchmarks to run and no tests.
bench:
(cd xproto ; go test -run 'nomatch' -bench '.*' -cpu 1,2,3,6)
# gofmt all non-auto-generated code.
# (auto-generated code is already gofmt'd.)
# Also do a column check (80 cols) after a gofmt.
# But don't check columns on auto-generated code, since I don't care if they
# break 80 cols.
gofmt:
gofmt -w *.go xgbgen/*.go examples/*.go examples/*/*.go xproto/xproto_test.go
colcheck *.go xgbgen/*.go examples/*.go examples/*/*.go xproto/xproto_test.go
push:
git push origin master
git push github master

54
vendor/github.com/BurntSushi/xgb/README generated vendored Normal file
View File

@ -0,0 +1,54 @@
XGB is the X Go Binding, which is a low-level API to communicate with the
core X protocol and many of the X extensions. It is closely modeled after
XCB and xpyb.
It is thread safe and gets immediate improvement from parallelism when
GOMAXPROCS > 1. (See the benchmarks in xproto/xproto_test.go for evidence.)
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.
Quick Usage
===========
go get github.com/BurntSushi/xgb
go run go/path/src/github.com/BurntSushi/xgb/examples/create-window/main.go
BurntSushi's Fork
=================
I've forked the XGB repository from Google Code due to inactivty upstream.
Godoc documentation can be found here:
http://godoc.burntsushi.net/pkg/github.com/BurntSushi/xgb/
Much of the code has been rewritten in an effort to support thread safety
and multiple extensions. Namely, go_client.py has been thrown away in favor
of an xgbgen package.
The biggest parts that *haven't* been rewritten by me are the connection and
authentication handshakes. They're inherently messy, and there's really no
reason to re-work them. The rest of XGB has been completely rewritten.
I like to release my code under the WTFPL, but since I'm starting with someone
else's work, I'm leaving the original license/contributor/author information
in tact.
I suppose I can legitimately release xgbgen under the WTFPL. To be fair, it is
at least as complex as XGB itself. *sigh*
What follows is the original README:
XGB README
==========
XGB is the X protocol Go language Binding.
It is the Go equivalent of XCB, the X protocol C-language Binding
(http://xcb.freedesktop.org/).
Unless otherwise noted, the XGB source files are distributed
under the BSD-style license found in the LICENSE file.
Contributions should follow the same procedure as for the Go project:
http://golang.org/doc/contribute.html

29
vendor/github.com/BurntSushi/xgb/STYLE generated vendored Normal file
View File

@ -0,0 +1,29 @@
I like to keep all my code to 80 columns or less. I have plenty of screen real
estate, but enjoy 80 columns so that I can have multiple code windows open side
to side and not be plagued by the ugly auto-wrapping of a text editor.
If you don't oblige me, I will fix any patch you submit to abide 80 columns.
Note that this style restriction does not preclude gofmt, but introduces a few
peculiarities. The first is that gofmt will occasionally add spacing (typically
to comments) that ends up going over 80 columns. Either shorten the comment or
put it on its own line.
The second and more common hiccup is when a function definition extends beyond
80 columns. If one adds line breaks to keep it below 80 columns, gofmt will
indent all subsequent lines in a function definition to the same indentation
level of the function body. This results in a less-than-ideal separation
between function definition and function body. To remedy this, simply add a
line break like so:
func RestackWindowExtra(xu *xgbutil.XUtil, win xproto.Window, stackMode int,
sibling xproto.Window, source int) error {
return ClientEvent(xu, win, "_NET_RESTACK_WINDOW", source, int(sibling),
stackMode)
}
Something similar should also be applied to long 'if' or 'for' conditionals,
although it would probably be preferrable to break up the conditional to
smaller chunks with a few helper variables.

110
vendor/github.com/BurntSushi/xgb/auth.go generated vendored Normal file
View File

@ -0,0 +1,110 @@
package xgb
/*
auth.go contains functions to facilitate the parsing of .Xauthority files.
It is largely unmodified from the original XGB package that I forked.
*/
import (
"encoding/binary"
"errors"
"io"
"os"
)
// readAuthority reads the X authority file for the DISPLAY.
// If hostname == "" or hostname == "localhost",
// 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).
b := make([]byte, 256)
// As per /usr/include/X11/Xauth.h.
const familyLocal = 256
const familyWild = 65535
if len(hostname) == 0 || hostname == "localhost" {
hostname, err = os.Hostname()
if err != nil {
return "", nil, err
}
}
fname := os.Getenv("XAUTHORITY")
if len(fname) == 0 {
home := os.Getenv("HOME")
if len(home) == 0 {
err = errors.New("Xauthority not found: $XAUTHORITY, $HOME not set")
return "", nil, err
}
fname = home + "/.Xauthority"
}
r, err := os.Open(fname)
if err != nil {
return "", nil, err
}
defer r.Close()
for {
var family uint16
if err := binary.Read(r, binary.BigEndian, &family); err != nil {
return "", nil, err
}
addr, err := getString(r, b)
if err != nil {
return "", nil, err
}
disp, err := getString(r, b)
if err != nil {
return "", nil, err
}
name0, err := getString(r, b)
if err != nil {
return "", nil, err
}
data0, err := getBytes(r, b)
if err != nil {
return "", nil, err
}
addrmatch := (family == familyWild) ||
(family == familyLocal && addr == hostname)
dispmatch := (disp == "") || (disp == display)
if addrmatch && dispmatch {
return name0, data0, nil
}
}
panic("unreachable")
}
func getBytes(r io.Reader, b []byte) ([]byte, error) {
var n uint16
if err := binary.Read(r, binary.BigEndian, &n); err != nil {
return nil, err
} else if n > uint16(len(b)) {
return nil, errors.New("bytes too long for buffer")
}
if _, err := io.ReadFull(r, b[0:n]); err != nil {
return nil, err
}
return b[0:n], nil
}
func getString(r io.Reader, b []byte) (string, error) {
b, err := getBytes(r, b)
if err != nil {
return "", err
}
return string(b), nil
}

185
vendor/github.com/BurntSushi/xgb/conn.go generated vendored Normal file
View File

@ -0,0 +1,185 @@
package xgb
/*
conn.go contains a couple of functions that do some real dirty work related
to the initial connection handshake with X.
This code is largely unmodified from the original XGB package that I forked.
*/
import (
"errors"
"fmt"
"io"
"net"
"os"
"strconv"
"strings"
)
// connect connects to the X server given in the 'display' string,
// and does all the necessary setup handshaking.
// 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
}
return c.postConnect()
}
// connect init from to the net.Conn,
func (c *Conn) connectNet(netConn net.Conn) error {
c.conn = netConn
return c.postConnect()
}
// do the postConnect action after Conn get it's underly net.Conn
func (c *Conn) postConnect() error {
// Get authentication data
authName, authData, err := readAuthority(c.host, c.display)
noauth := false
if err != nil {
Logger.Printf("Could not get authority info: %v", err)
Logger.Println("Trying connection without authority info...")
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 fmt.Errorf("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 fmt.Errorf("x protocol authentication refused: %s",
string(reason))
}
// Unfortunately, it isn't really feasible to read the setup bytes here,
// since the code to do so is in a different package.
// Users must call 'xproto.Setup(X)' to get the setup info.
c.SetupBytes = buf
// But also read stuff that we *need* to get started.
c.setupResourceIdBase = Get32(buf[12:])
c.setupResourceIdMask = Get32(buf[16:])
return nil
}
// dial initializes the actual net connection with X.
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:]
}
var err error
c.DisplayNumber, err = strconv.Atoi(c.display)
if err != nil || c.DisplayNumber < 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+c.DisplayNumber))
} 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
}

165
vendor/github.com/BurntSushi/xgb/cookie.go generated vendored Normal file
View File

@ -0,0 +1,165 @@
package xgb
import (
"errors"
)
// Cookie is the internal representation of a cookie, where one is generated
// for *every* request sent by XGB.
// 'cookie' is most frequently used by embedding it into a more specific
// kind of cookie, i.e., 'GetInputFocusCookie'.
type Cookie struct {
conn *Conn
Sequence uint16
replyChan chan []byte
errorChan chan error
pingChan chan bool
}
// NewCookie creates a new cookie with the correct channels initialized
// depending upon the values of 'checked' and 'reply'. Together, there are
// four different kinds of cookies. (See more detailed comments in the
// function for more info on those.)
// Note that a sequence number is not set until just before the request
// corresponding to this cookie is sent over the wire.
//
// Unless you're building requests from bytes by hand, this method should
// not be used.
func (c *Conn) NewCookie(checked, reply bool) *Cookie {
cookie := &Cookie{
conn: c,
Sequence: 0, // we add the sequence id just before sending a request
replyChan: nil,
errorChan: nil,
pingChan: nil,
}
// There are four different kinds of cookies:
// Checked requests with replies get a reply channel and an error channel.
// Unchecked requests with replies get a reply channel and a ping channel.
// Checked requests w/o replies get a ping channel and an error channel.
// Unchecked requests w/o replies get no channels.
// The reply channel is used to send reply data.
// The error channel is used to send error data.
// The ping channel is used when one of the 'reply' or 'error' channels
// is missing but the other is present. The ping channel is way to force
// the blocking to stop and basically say "the error has been received
// in the main event loop" (when the ping channel is coupled with a reply
// channel) or "the request you made that has no reply was successful"
// (when the ping channel is coupled with an error channel).
if checked {
cookie.errorChan = make(chan error, 1)
if !reply {
cookie.pingChan = make(chan bool, 1)
}
}
if reply {
cookie.replyChan = make(chan []byte, 1)
if !checked {
cookie.pingChan = make(chan bool, 1)
}
}
return cookie
}
// Reply detects whether this is a checked or unchecked cookie, and calls
// 'replyChecked' or 'replyUnchecked' appropriately.
//
// Unless you're building requests from bytes by hand, this method should
// not be used.
func (c Cookie) Reply() ([]byte, error) {
// checked
if c.errorChan != nil {
return c.replyChecked()
}
return c.replyUnchecked()
}
// replyChecked waits for a response on either the replyChan or errorChan
// 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.
//
// Unless you're building requests from bytes by hand, this method should
// not be used.
func (c Cookie) replyChecked() ([]byte, error) {
if c.replyChan == nil {
return nil, errors.New("Cannot call 'replyChecked' on a cookie that " +
"is not expecting a *reply* or an error.")
}
if c.errorChan == nil {
return nil, errors.New("Cannot call 'replyChecked' on a cookie that " +
"is not expecting a reply or an *error*.")
}
select {
case reply := <-c.replyChan:
return reply, nil
case err := <-c.errorChan:
return nil, err
}
}
// replyUnchecked waits for a response on either the replyChan or pingChan
// channels. If the former arrives, the bytes are returned with a nil 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.)
// In all honesty, you *probably* don't want to use this method.
//
// Unless you're building requests from bytes by hand, this method should
// not be used.
func (c Cookie) replyUnchecked() ([]byte, error) {
if c.replyChan == nil {
return nil, errors.New("Cannot call 'replyUnchecked' on a cookie " +
"that is not expecting a *reply*.")
}
select {
case reply := <-c.replyChan:
return reply, nil
case <-c.pingChan:
return nil, nil
}
}
// Check is used for checked requests that have no replies. It is a mechanism
// by which to report "success" or "error" in a synchronous fashion. (Therefore,
// unchecked requests without replies cannot use this method.)
// If the request causes an error, it is sent to this cookie's errorChan.
// If the request was successful, there is no response from the server.
// 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.
//
// Unless you're building requests from bytes by hand, this method should
// not be used.
func (c Cookie) Check() error {
if c.replyChan != nil {
return errors.New("Cannot call 'Check' on a cookie that is " +
"expecting a *reply*. Use 'Reply' instead.")
}
if c.errorChan == nil {
return errors.New("Cannot call 'Check' on a cookie that is " +
"not expecting a possible *error*.")
}
// First do a quick non-blocking check to see if we've been pinged.
select {
case err := <-c.errorChan:
return err
case <-c.pingChan:
return nil
default:
}
// Now force a round trip and try again, but block this time.
c.conn.Sync()
select {
case err := <-c.errorChan:
return err
case <-c.pingChan:
return nil
}
}

146
vendor/github.com/BurntSushi/xgb/doc.go generated vendored Normal file
View File

@ -0,0 +1,146 @@
/*
Package XGB provides the X Go Binding, which is a low-level API to communicate
with the core X protocol and many of the X extensions.
It is *very* closely modeled on XCB, so that experience with XCB (or xpyb) is
easily translatable to XGB. That is, it uses the same cookie/reply model
and is thread safe. There are otherwise no major differences (in the API).
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
Example
This is an extremely terse example that demonstrates how to connect to X,
create a window, listen to StructureNotify events and Key{Press,Release}
events, map the window, and print out all events received. An example with
accompanying documentation can be found in examples/create-window.
package main
import (
"fmt"
"github.com/BurntSushi/xgb"
"github.com/BurntSushi/xgb/xproto"
)
func main() {
X, err := xgb.NewConn()
if err != nil {
fmt.Println(err)
return
}
wid, _ := xproto.NewWindowId(X)
screen := xproto.Setup(X).DefaultScreen(X)
xproto.CreateWindow(X, screen.RootDepth, wid, screen.Root,
0, 0, 500, 500, 0,
xproto.WindowClassInputOutput, screen.RootVisual,
xproto.CwBackPixel | xproto.CwEventMask,
[]uint32{ // values must be in the order defined by the protocol
0xffffffff,
xproto.EventMaskStructureNotify |
xproto.EventMaskKeyPress |
xproto.EventMaskKeyRelease})
xproto.MapWindow(X, wid)
for {
ev, xerr := X.WaitForEvent()
if ev == nil && xerr == nil {
fmt.Println("Both event and error are nil. Exiting...")
return
}
if ev != nil {
fmt.Printf("Event: %s\n", ev)
}
if xerr != nil {
fmt.Printf("Error: %s\n", xerr)
}
}
}
Xinerama Example
This is another small example that shows how to query Xinerama for geometry
information of each active head. Accompanying documentation for this example
can be found in examples/xinerama.
package main
import (
"fmt"
"log"
"github.com/BurntSushi/xgb"
"github.com/BurntSushi/xgb/xinerama"
)
func main() {
X, err := xgb.NewConn()
if err != nil {
log.Fatal(err)
}
// Initialize the Xinerama extension.
// The appropriate 'Init' function must be run for *every*
// extension before any of its requests can be used.
err = xinerama.Init(X)
if err != nil {
log.Fatal(err)
}
reply, err := xinerama.QueryScreens(X).Reply()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Number of heads: %d\n", reply.Number)
for i, screen := range reply.ScreenInfo {
fmt.Printf("%d :: X: %d, Y: %d, Width: %d, Height: %d\n",
i, screen.XOrg, screen.YOrg, screen.Width, screen.Height)
}
}
Parallelism
XGB can benefit greatly from parallelism due to its concurrent design. For
evidence of this claim, please see the benchmarks in xproto/xproto_test.go.
Tests
xproto/xproto_test.go contains a number of contrived tests that stress
particular corners of XGB that I presume could be problem areas. Namely:
requests with no replies, requests with replies, checked errors, unchecked
errors, sequence number wrapping, cookie buffer flushing (i.e., forcing a round
trip every N requests made that don't have a reply), getting/setting properties
and creating a window and listening to StructureNotify events.
Code Generator
Both XCB and xpyb use the same Python module (xcbgen) for a code generator. XGB
(before this fork) used the same code generator as well, but in my attempt to
add support for more extensions, I found the code generator extremely difficult
to work with. Therefore, I re-wrote the code generator in Go. It can be found
in its own sub-package, xgbgen, of xgb. My design of xgbgen includes a rough
consideration that it could be used for other languages.
What works
I am reasonably confident that the core X protocol is in full working form. I've
also tested the Xinerama and RandR extensions sparingly. Many of the other
existing extensions have Go source generated (and are compilable) and are
included in this package, but I am currently unsure of their status. They
*should* work.
What does not work
XKB is the only extension that intentionally does not work, although I suspect
that GLX also does not work (however, there is Go source code for GLX that
compiles, unlike XKB). I don't currently have any intention of getting XKB
working, due to its complexity and my current mental incapacity to test it.
*/
package xgb

105
vendor/github.com/BurntSushi/xgb/help.go generated vendored Normal file
View File

@ -0,0 +1,105 @@
package xgb
/*
help.go is meant to contain a rough hodge podge of functions that are mainly
used in the auto generated code. Indeed, several functions here are simple
wrappers so that the sub-packages don't need to be smart about which stdlib
packages to import.
Also, the 'Get..' and 'Put..' functions are used through the core xgb package
too. (xgbutil uses them too.)
*/
import (
"fmt"
"strings"
)
// StringsJoin is an alias to strings.Join. It allows us to avoid having to
// import 'strings' in each of the generated Go files.
func StringsJoin(ss []string, sep string) string {
return strings.Join(ss, sep)
}
// Sprintf is so we don't need to import 'fmt' in the generated Go files.
func Sprintf(format string, v ...interface{}) string {
return fmt.Sprintf(format, v...)
}
// Errorf is just a wrapper for fmt.Errorf. Exists for the same reason
// that 'stringsJoin' and 'sprintf' exists.
func Errorf(format string, v ...interface{}) error {
return fmt.Errorf(format, v...)
}
// Pad a length to align on 4 bytes.
func Pad(n int) int {
return (n + 3) & ^3
}
// PopCount counts the number of bits set in a value list mask.
func PopCount(mask0 int) int {
mask := uint32(mask0)
n := 0
for i := uint32(0); i < 32; i++ {
if mask&(1<<i) != 0 {
n++
}
}
return n
}
// Put16 takes a 16 bit integer and copies it into a byte slice.
func Put16(buf []byte, v uint16) {
buf[0] = byte(v)
buf[1] = byte(v >> 8)
}
// Put32 takes a 32 bit integer and copies it into a byte slice.
func Put32(buf []byte, v uint32) {
buf[0] = byte(v)
buf[1] = byte(v >> 8)
buf[2] = byte(v >> 16)
buf[3] = byte(v >> 24)
}
// Put64 takes a 64 bit integer and copies it into a byte slice.
func Put64(buf []byte, v uint64) {
buf[0] = byte(v)
buf[1] = byte(v >> 8)
buf[2] = byte(v >> 16)
buf[3] = byte(v >> 24)
buf[4] = byte(v >> 32)
buf[5] = byte(v >> 40)
buf[6] = byte(v >> 48)
buf[7] = byte(v >> 56)
}
// Get16 constructs a 16 bit integer from the beginning of a byte slice.
func Get16(buf []byte) uint16 {
v := uint16(buf[0])
v |= uint16(buf[1]) << 8
return v
}
// Get32 constructs a 32 bit integer from the beginning of a byte slice.
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
}
// Get64 constructs a 64 bit integer from the beginning of a byte slice.
func Get64(buf []byte) uint64 {
v := uint64(buf[0])
v |= uint64(buf[1]) << 8
v |= uint64(buf[2]) << 16
v |= uint64(buf[3]) << 24
v |= uint64(buf[4]) << 32
v |= uint64(buf[5]) << 40
v |= uint64(buf[6]) << 48
v |= uint64(buf[7]) << 56
return v
}

1025
vendor/github.com/BurntSushi/xgb/shape/shape.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

29
vendor/github.com/BurntSushi/xgb/sync.go generated vendored Normal file
View File

@ -0,0 +1,29 @@
package xgb
// Sync sends a round trip request and waits for the response.
// This forces all pending cookies to be dealt with.
// You actually shouldn't need to use this like you might with Xlib. Namely,
// buffers are automatically flushed using Go's channels and round trip requests
// are forced where appropriate automatically.
func (c *Conn) Sync() {
cookie := c.NewCookie(true, true)
c.NewRequest(c.getInputFocusRequest(), cookie)
cookie.Reply() // wait for the buffer to clear
}
// getInputFocusRequest writes the raw bytes to a buffer.
// It is duplicated from xproto/xproto.go.
func (c *Conn) getInputFocusRequest() []byte {
size := 4
b := 0
buf := make([]byte, size)
buf[b] = 43 // request opcode
b += 1
b += 1 // padding
Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units
b += 2
return buf
}

554
vendor/github.com/BurntSushi/xgb/xgb.go generated vendored Normal file
View File

@ -0,0 +1,554 @@
package xgb
import (
"errors"
"io"
"log"
"net"
"os"
"sync"
)
var (
// Where to log error-messages. Defaults to stderr.
// To disable logging, just set this to log.New(ioutil.Discard, "", 0)
Logger = log.New(os.Stderr, "XGB: ", log.Lshortfile)
)
const (
// cookieBuffer represents the queue size of cookies existing at any
// point in time. The size of the buffer is really only important when
// there are many requests without replies made in sequence. Once the
// buffer fills, a round trip request is made to clear the buffer.
cookieBuffer = 1000
// xidBuffer represents the queue size of the xid channel.
// I don't think this value matters much, since xid generation is not
// that expensive.
xidBuffer = 5
// seqBuffer represents the queue size of the sequence number channel.
// I don't think this value matters much, since sequence number generation
// is not that expensive.
seqBuffer = 5
// reqBuffer represents the queue size of the number of requests that
// can be made until new ones block. This value seems OK.
reqBuffer = 100
// eventBuffer represents the queue size of the number of events or errors
// that can be loaded off the wire and not grabbed with WaitForEvent
// until reading an event blocks. This value should be big enough to handle
// bursts of events.
eventBuffer = 5000
)
// A Conn represents a connection to an X server.
type Conn struct {
host string
conn net.Conn
display string
DisplayNumber int
DefaultScreen int
SetupBytes []byte
setupResourceIdBase uint32
setupResourceIdMask uint32
eventChan chan eventOrError
cookieChan chan *Cookie
xidChan chan xid
seqChan chan uint16
reqChan chan *request
closing chan 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
// sub-packages.
ExtLock sync.RWMutex
// Extensions is a map from extension name to major opcode. It should
// not be used. It is exported for use in the extension sub-packages.
Extensions map[string]byte
}
// 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.)
func NewConn() (*Conn, error) {
return NewConnDisplay("")
}
// NewConnDisplay is just like NewConn, but allows a specific DISPLAY
// string to be used.
// If 'display' is empty it will be taken from os.Getenv("DISPLAY").
//
// Examples:
// NewConn(":1") -> net.Dial("unix", "", "/tmp/.X11-unix/X1")
// NewConn("/tmp/launch-12/:0") -> net.Dial("unix", "", "/tmp/launch-12/:0")
// 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{}
// First connect. This reads authority, checks DISPLAY environment
// variable, and loads the initial Setup info.
err := conn.connect(display)
if err != nil {
return nil, err
}
return postNewConn(conn)
}
// NewConnDisplay is just like NewConn, but allows a specific net.Conn
// to be used.
func NewConnNet(netConn net.Conn) (*Conn, error) {
conn := &Conn{}
// First connect. This reads authority, checks DISPLAY environment
// variable, and loads the initial Setup info.
err := conn.connectNet(netConn)
if err != nil {
return nil, err
}
return postNewConn(conn)
}
func postNewConn(conn *Conn) (*Conn, error) {
conn.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)
go conn.generateXIds()
go conn.generateSeqIds()
go conn.sendRequests()
go conn.readResponses()
return conn, nil
}
// Close gracefully closes the connection to the X server.
func (c *Conn) Close() {
close(c.reqChan)
}
// Event is an interface that can contain any of the events returned by the
// server. Use a type assertion switch to extract the Event structs.
type Event interface {
Bytes() []byte
String() string
}
// NewEventFun is the type of function use to construct events from raw bytes.
// It should not be used. It is exported for use in the extension sub-packages.
type NewEventFun func(buf []byte) Event
// NewEventFuncs is a map from event numbers to functions that create
// the corresponding event. It should not be used. It is exported for use
// in the extension sub-packages.
var NewEventFuncs = make(map[int]NewEventFun)
// NewExtEventFuncs is a temporary map that stores event constructor functions
// for each extension. When an extension is initialized, each event for that
// extension is added to the 'NewEventFuncs' map. It should not be used. It is
// exported for use in the extension sub-packages.
var NewExtEventFuncs = make(map[string]map[int]NewEventFun)
// Error is an interface that can contain any of the errors returned by
// the server. Use a type assertion switch to extract the Error structs.
type Error interface {
SequenceId() uint16
BadId() uint32
Error() string
}
// NewErrorFun is the type of function use to construct errors from raw bytes.
// It should not be used. It is exported for use in the extension sub-packages.
type NewErrorFun func(buf []byte) Error
// NewErrorFuncs is a map from error numbers to functions that create
// the corresponding error. It should not be used. It is exported for use in
// the extension sub-packages.
var NewErrorFuncs = make(map[int]NewErrorFun)
// NewExtErrorFuncs is a temporary map that stores error constructor functions
// for each extension. When an extension is initialized, each error for that
// extension is added to the 'NewErrorFuncs' map. It should not be used. It is
// exported for use in the extension sub-packages.
var NewExtErrorFuncs = make(map[string]map[int]NewErrorFun)
// eventOrError corresponds to values that can be either an event or an
// error.
type eventOrError interface{}
// NewId generates a new unused ID for use with requests like CreateWindow.
// If no new ids can be generated, the id returned is 0 and error is non-nil.
// This shouldn't be used directly, and is exported for use in the extension
// sub-packages.
// 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.
func (c *Conn) NewId() (uint32, error) {
xid := <-c.xidChan
if xid.err != nil {
return 0, xid.err
}
return xid.id, nil
}
// xid encapsulates a resource identifier being sent over the Conn.xidChan
// channel. If no new resource id can be generated, id is set to 0 and a
// non-nil error is set in xid.err.
type xid struct {
id uint32
err error
}
// generateXids sends new Ids down the channel for NewId to use.
// generateXids should be run in its own goroutine.
// 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)
// This requires some explanation. From the horse's mouth:
// "The resource-id-mask contains a single contiguous set of bits (at least
// 18). The client allocates resource IDs for types WINDOW, PIXMAP,
// CURSOR, FONT, GCONTEXT, and COLORMAP by choosing a value with only some
// subset of these bits set and ORing it with resource-id-base. Only values
// constructed in this way can be used to name newly created resources over
// this connection."
// So for example (using 8 bit integers), the mask might look like:
// 00111000
// So that valid values would be 00101000, 00110000, 00001000, and so on.
// Thus, the idea is to increment it by the place of the last least
// significant '1'. In this case, that value would be 00001000. To get
// that value, we can AND the original mask with its two's complement:
// 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
last := uint32(0)
for {
// TODO: Use the XC Misc extension to look for released ids.
if last > 0 && last >= max-inc+1 {
conn.xidChan <- xid{
id: 0,
err: errors.New("There are no more available resource" +
"identifiers."),
}
}
last += inc
conn.xidChan <- xid{
id: last | conn.setupResourceIdBase,
err: nil,
}
}
}
// newSeqId fetches the next sequence id from the Conn.seqChan channel.
func (c *Conn) newSequenceId() uint16 {
return <-c.seqChan
}
// generateSeqIds returns new sequence ids. It is meant to be run in its
// own goroutine.
// A sequence id is generated for *every* request. It's the identifier used
// to match up replies with requests.
// Since sequence ids can only be 16 bit integers we start over at zero when it
// comes time to wrap.
// N.B. As long as the cookie buffer is less than 2^16, there are no limitations
// on the number (or kind) of requests made in sequence.
func (c *Conn) generateSeqIds() {
defer close(c.seqChan)
seqid := uint16(1)
for {
c.seqChan <- seqid
if seqid == uint16((1<<16)-1) {
seqid = 0
} else {
seqid++
}
}
}
// request encapsulates a buffer of raw bytes (containing the request data)
// and a cookie, which when combined represents a single request.
// The cookie is used to match up the reply/error.
type request struct {
buf []byte
cookie *Cookie
// seq is closed when the request (cookie) has been sequenced by the Conn.
seq chan struct{}
}
// NewRequest takes the bytes and a cookie of a particular request, constructs
// a request type, and sends it over the Conn.reqChan channel.
// Note that the sequence number is added to the cookie after it is sent
// over the request channel, but before it is sent to X.
//
// Note that you may safely use NewRequest to send arbitrary byte requests
// to X. The resulting cookie can be used just like any normal cookie and
// abides by the same rules, except that for replies, you'll get back the
// raw byte data. This may be useful for performance critical sections where
// every allocation counts, since all X requests in XGB allocate a new byte
// slice. In contrast, NewRequest allocates one small request struct and
// nothing else. (Except when the cookie buffer is full and has to be flushed.)
//
// If you're using NewRequest manually, you'll need to use NewCookie to create
// a new cookie.
//
// In all likelihood, you should be able to copy and paste with some minor
// 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
}
// sendRequests is run as a single goroutine that takes requests and writes
// the bytes to the wire and adds the cookie to the cookie queue.
// It is meant to be run as its own goroutine.
func (c *Conn) sendRequests() {
defer close(c.cookieChan)
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
}
}
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
// trip request manually.
func (c *Conn) noop() error {
cookie := c.NewCookie(true, true)
cookie.Sequence = c.newSequenceId()
c.cookieChan <- cookie
if err := c.writeBuffer(c.getInputFocusRequest()); err != nil {
return err
}
cookie.Reply() // wait for the buffer to clear
return nil
}
// writeBuffer is a convenience function for writing a byte slice to the wire.
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
}
}
// readResponses is a goroutine that reads events, errors and
// replies off the wire.
// When an event is read, it is always added to the event channel.
// When an error is read, if it corresponds to an existing checked cookie,
// it is sent to that cookie's error channel. Otherwise it is added to the
// event channel.
// When a reply is read, it is added to the corresponding cookie's reply
// channel. (It is an error if no such cookie exists in this case.)
// Finally, cookies that came "before" this reply are always cleaned up.
func (c *Conn) readResponses() {
defer close(c.eventChan)
var (
err Error
seq uint16
replyBytes []byte
)
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 {
Logger.Printf("A read error is unrecoverable: %s", err)
c.eventChan <- err
c.Close()
continue
}
switch buf[0] {
case 0: // This is an error
// Use the constructor function for this error (that is auto
// generated) by looking it up by the error number.
newErrFun, ok := NewErrorFuncs[int(buf[1])]
if !ok {
Logger.Printf("BUG: Could not find error constructor function "+
"for error with number %d.", buf[1])
continue
}
err = newErrFun(buf)
seq = err.SequenceId()
// This error is either sent to the event channel or a specific
// cookie's error channel below.
case 1: // This is a reply
seq = Get16(buf[2:])
// check to see if this reply has more bytes to be read
size := Get32(buf[4:])
if size > 0 {
byteCount := 32 + size*4
biggerBuf := make([]byte, byteCount)
copy(biggerBuf[:32], buf)
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
}
replyBytes = biggerBuf
} else {
replyBytes = buf
}
// This reply is sent to its corresponding cookie below.
default: // This is an event
// Use the constructor function for this event (like for errors,
// and is also auto generated) by looking it up by the event number.
// Note that we AND the event number with 127 so that we ignore
// the most significant bit (which is set when it was sent from
// a SendEvent request).
evNum := int(buf[0] & 127)
newEventFun, ok := NewEventFuncs[evNum]
if !ok {
Logger.Printf("BUG: Could not find event construct function "+
"for event with number %d.", evNum)
continue
}
c.eventChan <- newEventFun(buf)
continue
}
// At this point, we have a sequence number and we're either
// processing an error or a reply, which are both responses to
// requests. So all we have to do is find the cookie corresponding
// to this error/reply, and send the appropriate data to it.
// In doing so, we make sure that any cookies that came before it
// are marked as successful if they are void and checked.
// If there's a cookie that requires a reply that is before this
// reply, then something is wrong.
for cookie := range c.cookieChan {
// This is the cookie we're looking for. Process and break.
if cookie.Sequence == seq {
if err != nil { // this is an error to a request
// synchronous processing
if cookie.errorChan != nil {
cookie.errorChan <- err
} else { // asynchronous processing
c.eventChan <- err
// if this is an unchecked reply, ping the cookie too
if cookie.pingChan != nil {
cookie.pingChan <- true
}
}
} else { // this is a reply
if cookie.replyChan == nil {
Logger.Printf("Reply with sequence id %d does not "+
"have a cookie with a valid reply channel.", seq)
continue
} else {
cookie.replyChan <- replyBytes
}
}
break
}
switch {
// Checked requests with replies
case cookie.replyChan != nil && cookie.errorChan != nil:
Logger.Printf("Found cookie with sequence id %d that is "+
"expecting a reply but will never get it. Currently "+
"on sequence number %d", cookie.Sequence, seq)
// Unchecked requests with replies
case cookie.replyChan != nil && cookie.pingChan != nil:
Logger.Printf("Found cookie with sequence id %d that is "+
"expecting a reply (and not an error) but will never "+
"get it. Currently on sequence number %d",
cookie.Sequence, seq)
// Checked requests without replies
case cookie.pingChan != nil && cookie.errorChan != nil:
cookie.pingChan <- true
// Unchecked requests without replies don't have any channels,
// so we can't do anything with them except let them pass by.
}
}
}
}
// processEventOrError takes an eventOrError, type switches on it,
// and returns it in Go idiomatic style.
func processEventOrError(everr eventOrError) (Event, Error) {
switch ee := everr.(type) {
case Event:
return ee, nil
case Error:
return nil, ee
default:
Logger.Printf("Invalid event/error type: %T", everr)
return nil, nil
}
}
// WaitForEvent returns the next event from the server.
// It will block until an event is available.
// WaitForEvent returns either an Event or an Error. (Returning both
// is a bug.) Note than an Error here is an X error and not an XGB error. That
// is, X errors are sometimes completely expected (and you may want to ignore
// them in some cases).
//
// If both the event and error are nil, then the connection has been closed.
func (c *Conn) WaitForEvent() (Event, Error) {
return processEventOrError(<-c.eventChan)
}
// PollForEvent returns the next event from the server if one is available in
// the internal queue without blocking. Note that unlike WaitForEvent, both
// Event and Error could be nil. Indeed, they are both nil when the event queue
// is empty.
func (c *Conn) PollForEvent() (Event, Error) {
select {
case everr := <-c.eventChan:
return processEventOrError(everr)
default:
return nil, nil
}
}

13
vendor/github.com/BurntSushi/xgb/xgbgen/COPYING generated vendored Normal file
View File

@ -0,0 +1,13 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

718
vendor/github.com/BurntSushi/xgb/xinerama/xinerama.go generated vendored Normal file
View File

@ -0,0 +1,718 @@
// Package xinerama is the X client API for the XINERAMA extension.
package xinerama
// This file is automatically generated from xinerama.xml. Edit at your peril!
import (
"github.com/BurntSushi/xgb"
"github.com/BurntSushi/xgb/xproto"
)
// Init must be called before using the XINERAMA extension.
func Init(c *xgb.Conn) error {
reply, err := xproto.QueryExtension(c, 8, "XINERAMA").Reply()
switch {
case err != nil:
return err
case !reply.Present:
return xgb.Errorf("No extension named XINERAMA could be found on on the server.")
}
c.ExtLock.Lock()
c.Extensions["XINERAMA"] = reply.MajorOpcode
c.ExtLock.Unlock()
for evNum, fun := range xgb.NewExtEventFuncs["XINERAMA"] {
xgb.NewEventFuncs[int(reply.FirstEvent)+evNum] = fun
}
for errNum, fun := range xgb.NewExtErrorFuncs["XINERAMA"] {
xgb.NewErrorFuncs[int(reply.FirstError)+errNum] = fun
}
return nil
}
func init() {
xgb.NewExtEventFuncs["XINERAMA"] = make(map[int]xgb.NewEventFun)
xgb.NewExtErrorFuncs["XINERAMA"] = make(map[int]xgb.NewErrorFun)
}
type ScreenInfo struct {
XOrg int16
YOrg int16
Width uint16
Height uint16
}
// ScreenInfoRead reads a byte slice into a ScreenInfo value.
func ScreenInfoRead(buf []byte, v *ScreenInfo) int {
b := 0
v.XOrg = int16(xgb.Get16(buf[b:]))
b += 2
v.YOrg = int16(xgb.Get16(buf[b:]))
b += 2
v.Width = xgb.Get16(buf[b:])
b += 2
v.Height = xgb.Get16(buf[b:])
b += 2
return b
}
// ScreenInfoReadList reads a byte slice into a list of ScreenInfo values.
func ScreenInfoReadList(buf []byte, dest []ScreenInfo) int {
b := 0
for i := 0; i < len(dest); i++ {
dest[i] = ScreenInfo{}
b += ScreenInfoRead(buf[b:], &dest[i])
}
return xgb.Pad(b)
}
// Bytes writes a ScreenInfo value to a byte slice.
func (v ScreenInfo) Bytes() []byte {
buf := make([]byte, 8)
b := 0
xgb.Put16(buf[b:], uint16(v.XOrg))
b += 2
xgb.Put16(buf[b:], uint16(v.YOrg))
b += 2
xgb.Put16(buf[b:], v.Width)
b += 2
xgb.Put16(buf[b:], v.Height)
b += 2
return buf[:b]
}
// ScreenInfoListBytes writes a list of ScreenInfo values to a byte slice.
func ScreenInfoListBytes(buf []byte, list []ScreenInfo) int {
b := 0
var structBytes []byte
for _, item := range list {
structBytes = item.Bytes()
copy(buf[b:], structBytes)
b += len(structBytes)
}
return xgb.Pad(b)
}
// Skipping definition for base type 'Bool'
// Skipping definition for base type 'Byte'
// Skipping definition for base type 'Card8'
// Skipping definition for base type 'Char'
// Skipping definition for base type 'Void'
// Skipping definition for base type 'Double'
// Skipping definition for base type 'Float'
// Skipping definition for base type 'Int16'
// Skipping definition for base type 'Int32'
// Skipping definition for base type 'Int8'
// Skipping definition for base type 'Card16'
// Skipping definition for base type 'Card32'
// GetScreenCountCookie is a cookie used only for GetScreenCount requests.
type GetScreenCountCookie struct {
*xgb.Cookie
}
// GetScreenCount sends a checked request.
// If an error occurs, it will be returned with the reply by calling GetScreenCountCookie.Reply()
func GetScreenCount(c *xgb.Conn, Window xproto.Window) GetScreenCountCookie {
c.ExtLock.RLock()
defer c.ExtLock.RUnlock()
if _, ok := c.Extensions["XINERAMA"]; !ok {
panic("Cannot issue request 'GetScreenCount' using the uninitialized extension 'XINERAMA'. xinerama.Init(connObj) must be called first.")
}
cookie := c.NewCookie(true, true)
c.NewRequest(getScreenCountRequest(c, Window), cookie)
return GetScreenCountCookie{cookie}
}
// GetScreenCountUnchecked sends an unchecked request.
// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent.
func GetScreenCountUnchecked(c *xgb.Conn, Window xproto.Window) GetScreenCountCookie {
c.ExtLock.RLock()
defer c.ExtLock.RUnlock()
if _, ok := c.Extensions["XINERAMA"]; !ok {
panic("Cannot issue request 'GetScreenCount' using the uninitialized extension 'XINERAMA'. xinerama.Init(connObj) must be called first.")
}
cookie := c.NewCookie(false, true)
c.NewRequest(getScreenCountRequest(c, Window), cookie)
return GetScreenCountCookie{cookie}
}
// GetScreenCountReply represents the data returned from a GetScreenCount request.
type GetScreenCountReply struct {
Sequence uint16 // sequence number of the request for this reply
Length uint32 // number of bytes in this reply
ScreenCount byte
Window xproto.Window
}
// Reply blocks and returns the reply data for a GetScreenCount request.
func (cook GetScreenCountCookie) Reply() (*GetScreenCountReply, error) {
buf, err := cook.Cookie.Reply()
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return getScreenCountReply(buf), nil
}
// getScreenCountReply reads a byte slice into a GetScreenCountReply value.
func getScreenCountReply(buf []byte) *GetScreenCountReply {
v := new(GetScreenCountReply)
b := 1 // skip reply determinant
v.ScreenCount = buf[b]
b += 1
v.Sequence = xgb.Get16(buf[b:])
b += 2
v.Length = xgb.Get32(buf[b:]) // 4-byte units
b += 4
v.Window = xproto.Window(xgb.Get32(buf[b:]))
b += 4
return v
}
// Write request to wire for GetScreenCount
// getScreenCountRequest writes a GetScreenCount request to a byte slice.
func getScreenCountRequest(c *xgb.Conn, Window xproto.Window) []byte {
size := 8
b := 0
buf := make([]byte, size)
c.ExtLock.RLock()
buf[b] = c.Extensions["XINERAMA"]
c.ExtLock.RUnlock()
b += 1
buf[b] = 2 // 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
return buf
}
// GetScreenSizeCookie is a cookie used only for GetScreenSize requests.
type GetScreenSizeCookie struct {
*xgb.Cookie
}
// GetScreenSize sends a checked request.
// If an error occurs, it will be returned with the reply by calling GetScreenSizeCookie.Reply()
func GetScreenSize(c *xgb.Conn, Window xproto.Window, Screen uint32) GetScreenSizeCookie {
c.ExtLock.RLock()
defer c.ExtLock.RUnlock()
if _, ok := c.Extensions["XINERAMA"]; !ok {
panic("Cannot issue request 'GetScreenSize' using the uninitialized extension 'XINERAMA'. xinerama.Init(connObj) must be called first.")
}
cookie := c.NewCookie(true, true)
c.NewRequest(getScreenSizeRequest(c, Window, Screen), cookie)
return GetScreenSizeCookie{cookie}
}
// GetScreenSizeUnchecked sends an unchecked request.
// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent.
func GetScreenSizeUnchecked(c *xgb.Conn, Window xproto.Window, Screen uint32) GetScreenSizeCookie {
c.ExtLock.RLock()
defer c.ExtLock.RUnlock()
if _, ok := c.Extensions["XINERAMA"]; !ok {
panic("Cannot issue request 'GetScreenSize' using the uninitialized extension 'XINERAMA'. xinerama.Init(connObj) must be called first.")
}
cookie := c.NewCookie(false, true)
c.NewRequest(getScreenSizeRequest(c, Window, Screen), cookie)
return GetScreenSizeCookie{cookie}
}
// GetScreenSizeReply represents the data returned from a GetScreenSize request.
type GetScreenSizeReply struct {
Sequence uint16 // sequence number of the request for this reply
Length uint32 // number of bytes in this reply
// padding: 1 bytes
Width uint32
Height uint32
Window xproto.Window
Screen uint32
}
// Reply blocks and returns the reply data for a GetScreenSize request.
func (cook GetScreenSizeCookie) Reply() (*GetScreenSizeReply, error) {
buf, err := cook.Cookie.Reply()
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return getScreenSizeReply(buf), nil
}
// getScreenSizeReply reads a byte slice into a GetScreenSizeReply value.
func getScreenSizeReply(buf []byte) *GetScreenSizeReply {
v := new(GetScreenSizeReply)
b := 1 // skip reply determinant
b += 1 // padding
v.Sequence = xgb.Get16(buf[b:])
b += 2
v.Length = xgb.Get32(buf[b:]) // 4-byte units
b += 4
v.Width = xgb.Get32(buf[b:])
b += 4
v.Height = xgb.Get32(buf[b:])
b += 4
v.Window = xproto.Window(xgb.Get32(buf[b:]))
b += 4
v.Screen = xgb.Get32(buf[b:])
b += 4
return v
}
// Write request to wire for GetScreenSize
// getScreenSizeRequest writes a GetScreenSize request to a byte slice.
func getScreenSizeRequest(c *xgb.Conn, Window xproto.Window, Screen uint32) []byte {
size := 12
b := 0
buf := make([]byte, size)
c.ExtLock.RLock()
buf[b] = c.Extensions["XINERAMA"]
c.ExtLock.RUnlock()
b += 1
buf[b] = 3 // 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:], Screen)
b += 4
return buf
}
// GetStateCookie is a cookie used only for GetState requests.
type GetStateCookie struct {
*xgb.Cookie
}
// GetState sends a checked request.
// If an error occurs, it will be returned with the reply by calling GetStateCookie.Reply()
func GetState(c *xgb.Conn, Window xproto.Window) GetStateCookie {
c.ExtLock.RLock()
defer c.ExtLock.RUnlock()
if _, ok := c.Extensions["XINERAMA"]; !ok {
panic("Cannot issue request 'GetState' using the uninitialized extension 'XINERAMA'. xinerama.Init(connObj) must be called first.")
}
cookie := c.NewCookie(true, true)
c.NewRequest(getStateRequest(c, Window), cookie)
return GetStateCookie{cookie}
}
// GetStateUnchecked sends an unchecked request.
// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent.
func GetStateUnchecked(c *xgb.Conn, Window xproto.Window) GetStateCookie {
c.ExtLock.RLock()
defer c.ExtLock.RUnlock()
if _, ok := c.Extensions["XINERAMA"]; !ok {
panic("Cannot issue request 'GetState' using the uninitialized extension 'XINERAMA'. xinerama.Init(connObj) must be called first.")
}
cookie := c.NewCookie(false, true)
c.NewRequest(getStateRequest(c, Window), cookie)
return GetStateCookie{cookie}
}
// GetStateReply represents the data returned from a GetState request.
type GetStateReply struct {
Sequence uint16 // sequence number of the request for this reply
Length uint32 // number of bytes in this reply
State byte
Window xproto.Window
}
// Reply blocks and returns the reply data for a GetState request.
func (cook GetStateCookie) Reply() (*GetStateReply, error) {
buf, err := cook.Cookie.Reply()
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return getStateReply(buf), nil
}
// getStateReply reads a byte slice into a GetStateReply value.
func getStateReply(buf []byte) *GetStateReply {
v := new(GetStateReply)
b := 1 // skip reply determinant
v.State = buf[b]
b += 1
v.Sequence = xgb.Get16(buf[b:])
b += 2
v.Length = xgb.Get32(buf[b:]) // 4-byte units
b += 4
v.Window = xproto.Window(xgb.Get32(buf[b:]))
b += 4
return v
}
// Write request to wire for GetState
// getStateRequest writes a GetState request to a byte slice.
func getStateRequest(c *xgb.Conn, Window xproto.Window) []byte {
size := 8
b := 0
buf := make([]byte, size)
c.ExtLock.RLock()
buf[b] = c.Extensions["XINERAMA"]
c.ExtLock.RUnlock()
b += 1
buf[b] = 1 // 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
return buf
}
// IsActiveCookie is a cookie used only for IsActive requests.
type IsActiveCookie struct {
*xgb.Cookie
}
// IsActive sends a checked request.
// If an error occurs, it will be returned with the reply by calling IsActiveCookie.Reply()
func IsActive(c *xgb.Conn) IsActiveCookie {
c.ExtLock.RLock()
defer c.ExtLock.RUnlock()
if _, ok := c.Extensions["XINERAMA"]; !ok {
panic("Cannot issue request 'IsActive' using the uninitialized extension 'XINERAMA'. xinerama.Init(connObj) must be called first.")
}
cookie := c.NewCookie(true, true)
c.NewRequest(isActiveRequest(c), cookie)
return IsActiveCookie{cookie}
}
// IsActiveUnchecked sends an unchecked request.
// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent.
func IsActiveUnchecked(c *xgb.Conn) IsActiveCookie {
c.ExtLock.RLock()
defer c.ExtLock.RUnlock()
if _, ok := c.Extensions["XINERAMA"]; !ok {
panic("Cannot issue request 'IsActive' using the uninitialized extension 'XINERAMA'. xinerama.Init(connObj) must be called first.")
}
cookie := c.NewCookie(false, true)
c.NewRequest(isActiveRequest(c), cookie)
return IsActiveCookie{cookie}
}
// IsActiveReply represents the data returned from a IsActive request.
type IsActiveReply struct {
Sequence uint16 // sequence number of the request for this reply
Length uint32 // number of bytes in this reply
// padding: 1 bytes
State uint32
}
// Reply blocks and returns the reply data for a IsActive request.
func (cook IsActiveCookie) Reply() (*IsActiveReply, error) {
buf, err := cook.Cookie.Reply()
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return isActiveReply(buf), nil
}
// isActiveReply reads a byte slice into a IsActiveReply value.
func isActiveReply(buf []byte) *IsActiveReply {
v := new(IsActiveReply)
b := 1 // skip reply determinant
b += 1 // padding
v.Sequence = xgb.Get16(buf[b:])
b += 2
v.Length = xgb.Get32(buf[b:]) // 4-byte units
b += 4
v.State = xgb.Get32(buf[b:])
b += 4
return v
}
// Write request to wire for IsActive
// isActiveRequest writes a IsActive request to a byte slice.
func isActiveRequest(c *xgb.Conn) []byte {
size := 4
b := 0
buf := make([]byte, size)
c.ExtLock.RLock()
buf[b] = c.Extensions["XINERAMA"]
c.ExtLock.RUnlock()
b += 1
buf[b] = 4 // request opcode
b += 1
xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units
b += 2
return buf
}
// QueryScreensCookie is a cookie used only for QueryScreens requests.
type QueryScreensCookie struct {
*xgb.Cookie
}
// QueryScreens sends a checked request.
// If an error occurs, it will be returned with the reply by calling QueryScreensCookie.Reply()
func QueryScreens(c *xgb.Conn) QueryScreensCookie {
c.ExtLock.RLock()
defer c.ExtLock.RUnlock()
if _, ok := c.Extensions["XINERAMA"]; !ok {
panic("Cannot issue request 'QueryScreens' using the uninitialized extension 'XINERAMA'. xinerama.Init(connObj) must be called first.")
}
cookie := c.NewCookie(true, true)
c.NewRequest(queryScreensRequest(c), cookie)
return QueryScreensCookie{cookie}
}
// QueryScreensUnchecked sends an unchecked request.
// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent.
func QueryScreensUnchecked(c *xgb.Conn) QueryScreensCookie {
c.ExtLock.RLock()
defer c.ExtLock.RUnlock()
if _, ok := c.Extensions["XINERAMA"]; !ok {
panic("Cannot issue request 'QueryScreens' using the uninitialized extension 'XINERAMA'. xinerama.Init(connObj) must be called first.")
}
cookie := c.NewCookie(false, true)
c.NewRequest(queryScreensRequest(c), cookie)
return QueryScreensCookie{cookie}
}
// QueryScreensReply represents the data returned from a QueryScreens request.
type QueryScreensReply struct {
Sequence uint16 // sequence number of the request for this reply
Length uint32 // number of bytes in this reply
// padding: 1 bytes
Number uint32
// padding: 20 bytes
ScreenInfo []ScreenInfo // size: xgb.Pad((int(Number) * 8))
}
// Reply blocks and returns the reply data for a QueryScreens request.
func (cook QueryScreensCookie) Reply() (*QueryScreensReply, error) {
buf, err := cook.Cookie.Reply()
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return queryScreensReply(buf), nil
}
// queryScreensReply reads a byte slice into a QueryScreensReply value.
func queryScreensReply(buf []byte) *QueryScreensReply {
v := new(QueryScreensReply)
b := 1 // skip reply determinant
b += 1 // padding
v.Sequence = xgb.Get16(buf[b:])
b += 2
v.Length = xgb.Get32(buf[b:]) // 4-byte units
b += 4
v.Number = xgb.Get32(buf[b:])
b += 4
b += 20 // padding
v.ScreenInfo = make([]ScreenInfo, v.Number)
b += ScreenInfoReadList(buf[b:], v.ScreenInfo)
return v
}
// Write request to wire for QueryScreens
// queryScreensRequest writes a QueryScreens request to a byte slice.
func queryScreensRequest(c *xgb.Conn) []byte {
size := 4
b := 0
buf := make([]byte, size)
c.ExtLock.RLock()
buf[b] = c.Extensions["XINERAMA"]
c.ExtLock.RUnlock()
b += 1
buf[b] = 5 // request opcode
b += 1
xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units
b += 2
return buf
}
// QueryVersionCookie is a cookie used only for QueryVersion requests.
type QueryVersionCookie struct {
*xgb.Cookie
}
// QueryVersion sends a checked request.
// If an error occurs, it will be returned with the reply by calling QueryVersionCookie.Reply()
func QueryVersion(c *xgb.Conn, Major byte, Minor byte) QueryVersionCookie {
c.ExtLock.RLock()
defer c.ExtLock.RUnlock()
if _, ok := c.Extensions["XINERAMA"]; !ok {
panic("Cannot issue request 'QueryVersion' using the uninitialized extension 'XINERAMA'. xinerama.Init(connObj) must be called first.")
}
cookie := c.NewCookie(true, true)
c.NewRequest(queryVersionRequest(c, Major, Minor), cookie)
return QueryVersionCookie{cookie}
}
// QueryVersionUnchecked sends an unchecked request.
// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent.
func QueryVersionUnchecked(c *xgb.Conn, Major byte, Minor byte) QueryVersionCookie {
c.ExtLock.RLock()
defer c.ExtLock.RUnlock()
if _, ok := c.Extensions["XINERAMA"]; !ok {
panic("Cannot issue request 'QueryVersion' using the uninitialized extension 'XINERAMA'. xinerama.Init(connObj) must be called first.")
}
cookie := c.NewCookie(false, true)
c.NewRequest(queryVersionRequest(c, Major, Minor), cookie)
return QueryVersionCookie{cookie}
}
// QueryVersionReply represents the data returned from a QueryVersion request.
type QueryVersionReply struct {
Sequence uint16 // sequence number of the request for this reply
Length uint32 // number of bytes in this reply
// padding: 1 bytes
Major uint16
Minor uint16
}
// Reply blocks and returns the reply data for a QueryVersion request.
func (cook QueryVersionCookie) Reply() (*QueryVersionReply, error) {
buf, err := cook.Cookie.Reply()
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return queryVersionReply(buf), nil
}
// queryVersionReply reads a byte slice into a QueryVersionReply value.
func queryVersionReply(buf []byte) *QueryVersionReply {
v := new(QueryVersionReply)
b := 1 // skip reply determinant
b += 1 // padding
v.Sequence = xgb.Get16(buf[b:])
b += 2
v.Length = xgb.Get32(buf[b:]) // 4-byte units
b += 4
v.Major = xgb.Get16(buf[b:])
b += 2
v.Minor = xgb.Get16(buf[b:])
b += 2
return v
}
// Write request to wire for QueryVersion
// queryVersionRequest writes a QueryVersion request to a byte slice.
func queryVersionRequest(c *xgb.Conn, Major byte, Minor byte) []byte {
size := 8
b := 0
buf := make([]byte, size)
c.ExtLock.RLock()
buf[b] = c.Extensions["XINERAMA"]
c.ExtLock.RUnlock()
b += 1
buf[b] = 0 // request opcode
b += 1
xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units
b += 2
buf[b] = Major
b += 1
buf[b] = Minor
b += 1
return buf
}

14910
vendor/github.com/BurntSushi/xgb/xproto/xproto.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

6
vendor/github.com/BurntSushi/xgbutil/.gitignore generated vendored Normal file
View File

@ -0,0 +1,6 @@
*.swp
*.png
tst_first
tst_graphics
TAGS

13
vendor/github.com/BurntSushi/xgbutil/COPYING generated vendored Normal file
View File

@ -0,0 +1,13 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

36
vendor/github.com/BurntSushi/xgbutil/Makefile generated vendored Normal file
View File

@ -0,0 +1,36 @@
all: callback.go types_auto.go gofmt
install:
go install -p 6 . ./ewmh ./gopher ./icccm ./keybind ./motif ./mousebind \
./xcursor ./xevent ./xgraphics ./xinerama ./xprop ./xrect ./xwindow
push:
git push origin master
git push github master
build-ex:
find ./_examples/ -type d -wholename './_examples/[a-z]*' -print0 \
| xargs -0 go build -p 6
gofmt:
gofmt -w *.go */*.go _examples/*/*.go
colcheck *.go */*.go _examples/*/*.go
callback.go:
scripts/write-events callbacks > xevent/callback.go
types_auto.go:
scripts/write-events evtypes > xevent/types_auto.go
tags:
find ./ \( -name '*.go' -and -not -wholename './tests/*' -and -not -wholename './_examples/*' \) -print0 | xargs -0 gotags > TAGS
loc:
find ./ -name '*.go' -and -not -wholename './tests*' -and -not -name '*keysymdef.go' -and -not -name '*gopher.go' -print | sort | xargs wc -l
ex-%:
go run _examples/$*/main.go
gopherimg:
go-bindata -f GopherPng -p gopher -i gopher/gophercolor-small.png -o gopher/gopher.go

60
vendor/github.com/BurntSushi/xgbutil/README generated vendored Normal file
View File

@ -0,0 +1,60 @@
xgbutil is a utility library designed to work with the X Go Binding. This
project's main goal is to make various X related tasks easier. For example,
binding keys, using the EWMH or ICCCM specs with the window manager,
moving/resizing windows, assigning function callbacks to particular events,
drawing images to a window, etc.
xgbutil attempts to be thread safe, but it has not been completely tested in
this regard. In general, the X event loop implemented in the xevent package is
sequential. The idea is to be sequential by default, and let the user spawn
concurrent code at their discretion. (i.e., the complexity of making the main
event loop generally concurrent is vast.)
You may sleep safely at night by assuming that XGB is thread safe, though.
To start using xgbutil, you should have at least a passing familiarity with X.
Your first stop should be the examples directory.
Installation
============
go get github.com/BurntSushi/xgbutil
Dependencies
============
XGB is the main dependency. Use of the xgraphics packages requires graphics-go
and freetype-go.
XGB project URL: https://github.com/BurntSushi/xgb
Quick Example
=============
go get github.com/BurntSushi/xgbutil/_examples/window-name-sizes
"$GOPATH"/bin/window-name-sizes
The output will be a list of names of all top-level windows and their geometry
including window manager decorations. (Assuming your window manager supports
some basic EWMH properties.)
Documentation
=============
gopkgdoc is well-suited to provide documentation for xgbutil. Its cross-package
hyperlinking on types is also extremely useful, since much of xgbutil relies on
XGB.
With that said, documentation is also hosted here:
http://godoc.burntsushi.net/pkg/github.com/BurntSushi/xgbutil/
Examples
========
There are several examples in the examples directory covering common use cases.
They are heavily documented and should run out of the box.
Python
======
An older project of mine, xpybutil, served as inspiration for xgbutil. If you
want to use Python, xpybutil should help quite a bit. Please note though, that
at this point, xgbutil provides a lot more functionality and is much better
documented.
xpybutil project URL: https://github.com/BurntSushi/xpybutil

29
vendor/github.com/BurntSushi/xgbutil/STYLE generated vendored Normal file
View File

@ -0,0 +1,29 @@
I like to keep all my code to 80 columns or less. I have plenty of screen real
estate, but enjoy 80 columns so that I can have multiple code windows open side
to side and not be plagued by the ugly auto-wrapping of a text editor.
If you don't oblige me, I will fix any patch you submit to abide 80 columns.
Note that this style restriction does not preclude gofmt, but introduces a few
peculiarities. The first is that gofmt will occasionally add spacing (typically
to comments) that ends up going over 80 columns. Either shorten the comment or
put it on its own line.
The second and more common hiccup is when a function definition extends beyond
80 columns. If one adds line breaks to keep it below 80 columns, gofmt will
indent all subsequent lines in a function definition to the same indentation
level of the function body. This results in a less-than-ideal separation
between function definition and function body. To remedy this, simply add a
line break like so:
func RestackWindowExtra(xu *xgbutil.XUtil, win xproto.Window, stackMode int,
sibling xproto.Window, source int) error {
return ClientEvent(xu, win, "_NET_RESTACK_WINDOW", source, int(sibling),
stackMode)
}
Something similar should also be applied to long 'if' or 'for' conditionals,
although it would probably be preferrable to break up the conditional to
smaller chunks with a few helper variables.

67
vendor/github.com/BurntSushi/xgbutil/doc.go generated vendored Normal file
View File

@ -0,0 +1,67 @@
/*
Package xgbutil is a utility library designed to make common tasks with the X
server easier. The central design choice that has driven development is to hide
the complexity of X wherever possible but expose it when necessary.
For example, the xevent package provides an implementation of an X event loop
that acts as a dispatcher to event handlers set up with the xevent, keybind and
mousebind packages. At the same time, the event queue is exposed and can be
modified using xevent.Peek and xevent.DequeueAt.
Sub-packages
The xgbutil package is considerably small, and only contains some type
definitions and the initial setup for an X connection. Much of the
functionality of xgbutil comes from its sub-packages. Each sub-package is
appropriately documented.
Installation
xgbutil is go-gettable:
go get github.com/BurntSushi/xgbutil
Dependencies
XGB is the main dependency, and is required for all packages inside xgbutil.
graphics-go and freetype-go are also required if using the xgraphics package.
Quick Example
A quick example to demonstrate that xgbutil is working correctly:
go get github.com/BurntSushi/xgbutil/examples/window-name-sizes
GO/PATH/bin/window-name-sizes
The output will be a list of names of all top-level windows and their geometry
including window manager decorations. (Assuming your window manager supports
some basic EWMH properties.)
Examples
The examples directory contains a sizable number of examples demonstrating
common tasks with X. They are intended to demonstrate a single thing each,
although a few that require setup are necessarily long. Each example is
heavily documented.
The examples directory should be your first stop when learning how to use
xgbutil.
xgbutil is also used heavily throughout my window manager, Wingo. It may be
useful reference material.
Wingo project page: https://github.com/BurntSushi/wingo
Thread Safety
While I am fairly confident that XGB is thread safe, I am only somewhat
confident that xgbutil is thread safe. It simply has not been tested enough for
my confidence to be higher.
Note that the xevent package's X event loop is not concurrent. Namely,
designing a generally concurrent X event loop is extremely complex. Instead,
the onus is on you, the user, to design concurrent callback functions if
concurrency is desired.
*/
package xgbutil

56
vendor/github.com/BurntSushi/xgbutil/ewmh/doc.go generated vendored Normal file
View File

@ -0,0 +1,56 @@
/*
Package ewmh provides a comprehensive API to get and set properties specified
by the EWMH spec, as well as perform actions specified by the EWMH spec.
Since there are so many functions and they adhere to an existing spec,
this package file does not contain much documentation. Indeed, each
method has only a single comment associated with it: the EWMH property name.
The idea is to
provide a consistent interface to use all facilities described in the EWMH
spec: http://standards.freedesktop.org/wm-spec/wm-spec-latest.html.
Naming scheme
Using "_NET_ACTIVE_WINDOW" as an example,
functions "ActiveWindowGet" and "ActiveWindowSet" get and set the
property, respectively. Both of these functions exist for most EWMH
properties. Additionally, some EWMH properties support sending a client
message event to request the window manager to perform some action. In the
case of "_NET_ACTIVE_WINDOW", this request is used to set the active
window.
These sorts of functions end in "Req". So for "_NET_ACTIVE_WINDOW",
the method name is "ActiveWindowReq". Moreover, most requests include
various parameters that don't need to be changed often (like the source
indication). Thus, by default, functions ending in "Req" force these to
sensible defaults. If you need access to all of the parameters, use the
corresponding "ReqExtra" method. So for "_NET_ACTIVE_WINDOW", that would
be "ActiveWindowReqExtra". (If no "ReqExtra" method exists, then the
"Req" method covers all available parameters.)
This naming scheme has one exception: if a property's only use is through
sending an event (like "_NET_CLOSE_WINDOW"), then the name will be
"CloseWindow" for the short-hand version and "CloseWindowExtra"
for access to all of the parameters. (Since there is no "_NET_CLOSE_WINDOW"
property, there is no need for "CloseWindowGet" and "CloseWindowSet"
functions.)
For properties that store more than just a simple integer, name or list
of integers, structs have been created and exposed to organize the
information returned in a sensible manner. For example, the
"_NET_DESKTOP_GEOMETRY" property would typically return a slice of integers
of length 2, where the first integer is the width and the second is the
height. Xgbutil will wrap this in a struct with the obvious members. These
structs are documented.
Finally, functions ending in "*Set" are typically only used when setting
properties on clients *you've* created or when the window manager sets
properties. Thus, it's unlikely that you should use them unless you're
creating a top-level client or building a window manager.
Functions ending in "Get" or "Req[Extra]" are commonly used.
N.B. Not all properties have "*Req" functions.
*/
package ewmh

1159
vendor/github.com/BurntSushi/xgbutil/ewmh/ewmh.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

31
vendor/github.com/BurntSushi/xgbutil/ewmh/winman.go generated vendored Normal file
View File

@ -0,0 +1,31 @@
package ewmh
import (
"fmt"
"github.com/BurntSushi/xgbutil"
)
// GetEwmhWM uses the EWMH spec to find if a conforming window manager
// is currently running or not. If it is, then its name will be returned.
// Otherwise, an error will be returned explaining why one couldn't be found.
func GetEwmhWM(xu *xgbutil.XUtil) (string, error) {
childCheck, err := SupportingWmCheckGet(xu, xu.RootWin())
if err != nil {
return "", fmt.Errorf("GetEwmhWM: Failed because: %s", err)
}
childCheck2, err := SupportingWmCheckGet(xu, childCheck)
if err != nil {
return "", fmt.Errorf("GetEwmhWM: Failed because: %s", err)
}
if childCheck != childCheck2 {
return "", fmt.Errorf(
"GetEwmhWM: _NET_SUPPORTING_WM_CHECK value on the root window "+
"(%x) does not match _NET_SUPPORTING_WM_CHECK value "+
"on the child window (%x).", childCheck, childCheck2)
}
return WmNameGet(xu, childCheck)
}

1
vendor/github.com/BurntSushi/xgbutil/session.vim generated vendored Normal file
View File

@ -0,0 +1 @@
au BufWritePost *.go silent!make tags > /dev/null 2>&1

167
vendor/github.com/BurntSushi/xgbutil/types.go generated vendored Normal file
View File

@ -0,0 +1,167 @@
package xgbutil
/*
types.go contains several types used in the XUtil structure. In an ideal world,
they would be defined in their appropriate packages, but must be defined here
(and exported) for use in some sub-packages. (Namely, xevent, keybind and
mousebind.)
*/
import (
"github.com/BurntSushi/xgb"
"github.com/BurntSushi/xgb/xproto"
)
// Callback is an interface that should be implemented by event callback
// functions. Namely, to assign a function to a particular event/window
// combination, simply define a function with type 'SomeEventFun' (pre-defined
// in xevent/callback.go), and call the 'Connect' method.
// The 'Run' method is used inside the Main event loop, and shouldn't be used
// by the user.
// Also, it is perfectly legitimate to connect to events that don't specify
// a window (like MappingNotify and KeymapNotify). In this case, simply
// use 'xgbutil.NoWindow' as the window id.
//
// Example to respond to ConfigureNotify events on window 0x1
//
// xevent.ConfigureNotifyFun(
// func(X *xgbutil.XUtil, e xevent.ConfigureNotifyEvent) {
// fmt.Printf("(%d, %d) %dx%d\n", e.X, e.Y, e.Width, e.Height)
// }).Connect(X, 0x1)
type Callback interface {
// Connect modifies XUtil's state to attach an event handler to a
// particular event.
Connect(xu *XUtil, win xproto.Window)
// Run is exported for use in the xevent package but should not be
// used by the user. (It is used to run the callback function in the
// main event loop.)
Run(xu *XUtil, ev interface{})
}
// CallbackHook works similarly to the more general Callback, but it is
// for hooks into the main xevent loop. As such it does not get attached
// to a window.
type CallbackHook interface {
// Connect connects this hook to the main loop of the passed XUtil
// instance.
Connect(xu *XUtil)
// Run is exported for use in the xevent package, but should not be
// used by the user. It should return true if it's ok to process
// the event as usual, or false if it should be suppressed.
Run(xu *XUtil, ev interface{}) bool
}
// CallbackKey works similarly to the more general Callback, but it adds
// parameters specific to key bindings.
type CallbackKey interface {
// Connect modifies XUtil's state to attach an event handler to a
// particular key press. If grab is true, connect will request a passive
// grab.
Connect(xu *XUtil, win xproto.Window, keyStr string, grab bool) error
// Run is exported for use in the keybind package but should not be
// used by the user. (It is used to run the callback function in the
// main event loop.
Run(xu *XUtil, ev interface{})
}
// CallbackMouse works similarly to the more general Callback, but it adds
// parameters specific to mouse bindings.
type CallbackMouse interface {
// Connect modifies XUtil's state to attach an event handler to a
// particular button press.
// If sync is true, the grab will be synchronous. (This will require a
// call to xproto.AllowEvents in response, otherwise no further events
// will be processed and your program will lock.)
// If grab is true, connect will request a passive grab.
Connect(xu *XUtil, win xproto.Window, buttonStr string,
sync bool, grab bool) error
// Run is exported for use in the mousebind package but should not be
// used by the user. (It is used to run the callback function in the
// main event loop.)
Run(xu *XUtil, ev interface{})
}
// KeyKey is the type of the key in the map of keybindings.
// It essentially represents the tuple
// (event type, window id, modifier, keycode).
// It is exported for use in the keybind package. It should not be used.
type KeyKey struct {
Evtype int
Win xproto.Window
Mod uint16
Code xproto.Keycode
}
// KeyString is the type of a key binding string used to connect to particular
// key combinations. A list of all such key strings is maintained in order to
// rebind keys when the keyboard mapping has been changed.
type KeyString struct {
Str string
Callback CallbackKey
Evtype int
Win xproto.Window
Grab bool
}
// MouseKey is the type of the key in the map of mouse bindings.
// It essentially represents the tuple
// (event type, window id, modifier, button).
// It is exported for use in the mousebind package. It should not be used.
type MouseKey struct {
Evtype int
Win xproto.Window
Mod uint16
Button xproto.Button
}
// KeyboardMapping embeds a keyboard mapping reply from XGB.
// It should be retrieved using keybind.KeyMapGet, if necessary.
// xgbutil tries quite hard to absolve you from ever having to use this.
// A keyboard mapping is a table that maps keycodes to one or more keysyms.
type KeyboardMapping struct {
*xproto.GetKeyboardMappingReply
}
// ModifierMapping embeds a modifier mapping reply from XGB.
// It should be retrieved using keybind.ModMapGet, if necessary.
// xgbutil tries quite hard to absolve you from ever having to use this.
// A modifier mapping is a table that maps modifiers to one or more keycodes.
type ModifierMapping struct {
*xproto.GetModifierMappingReply
}
// ErrorHandlerFun is the type of function required to handle errors that
// come in through the main event loop.
// For example, to set a new error handler, use:
//
// xevent.ErrorHandlerSet(xgbutil.ErrorHandlerFun(
// func(err xgb.Error) {
// // do something with err
// }))
type ErrorHandlerFun func(err xgb.Error)
// EventOrError is a struct that contains either an event value or an error
// value. It is an error to contain both. Containing neither indicates an
// error too.
// This is exported for use in the xevent package. You shouldn't have any
// direct contact with values of this type, unless you need to inspect the
// queue directly with xevent.Peek.
type EventOrError struct {
Event xgb.Event
Err xgb.Error
}
// MouseDragFun is the kind of function used on each dragging step
// and at the end of a drag.
type MouseDragFun func(xu *XUtil, rootX, rootY, eventX, eventY int)
// MouseDragBeginFun is the kind of function used to initialize a drag.
// The difference between this and MouseDragFun is that the begin function
// returns a bool (of whether or not to cancel the drag) and an X resource
// identifier corresponding to a cursor.
type MouseDragBeginFun func(xu *XUtil, rootX, rootY,
eventX, eventY int) (bool, xproto.Cursor)

389
vendor/github.com/BurntSushi/xgbutil/xevent/callback.go generated vendored Normal file
View File

@ -0,0 +1,389 @@
package xevent
/*
Does all the plumbing to allow a simple callback interface for users.
This file is automatically generated using `scripts/write-events callbacks`.
Edit it at your peril.
*/
import (
"github.com/BurntSushi/xgb/xproto"
"github.com/BurntSushi/xgbutil"
)
type KeyPressFun func(xu *xgbutil.XUtil, event KeyPressEvent)
func (callback KeyPressFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, KeyPress, win, callback)
}
func (callback KeyPressFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(KeyPressEvent))
}
type KeyReleaseFun func(xu *xgbutil.XUtil, event KeyReleaseEvent)
func (callback KeyReleaseFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, KeyRelease, win, callback)
}
func (callback KeyReleaseFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(KeyReleaseEvent))
}
type ButtonPressFun func(xu *xgbutil.XUtil, event ButtonPressEvent)
func (callback ButtonPressFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, ButtonPress, win, callback)
}
func (callback ButtonPressFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(ButtonPressEvent))
}
type ButtonReleaseFun func(xu *xgbutil.XUtil, event ButtonReleaseEvent)
func (callback ButtonReleaseFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, ButtonRelease, win, callback)
}
func (callback ButtonReleaseFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(ButtonReleaseEvent))
}
type MotionNotifyFun func(xu *xgbutil.XUtil, event MotionNotifyEvent)
func (callback MotionNotifyFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, MotionNotify, win, callback)
}
func (callback MotionNotifyFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(MotionNotifyEvent))
}
type EnterNotifyFun func(xu *xgbutil.XUtil, event EnterNotifyEvent)
func (callback EnterNotifyFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, EnterNotify, win, callback)
}
func (callback EnterNotifyFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(EnterNotifyEvent))
}
type LeaveNotifyFun func(xu *xgbutil.XUtil, event LeaveNotifyEvent)
func (callback LeaveNotifyFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, LeaveNotify, win, callback)
}
func (callback LeaveNotifyFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(LeaveNotifyEvent))
}
type FocusInFun func(xu *xgbutil.XUtil, event FocusInEvent)
func (callback FocusInFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, FocusIn, win, callback)
}
func (callback FocusInFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(FocusInEvent))
}
type FocusOutFun func(xu *xgbutil.XUtil, event FocusOutEvent)
func (callback FocusOutFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, FocusOut, win, callback)
}
func (callback FocusOutFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(FocusOutEvent))
}
type KeymapNotifyFun func(xu *xgbutil.XUtil, event KeymapNotifyEvent)
func (callback KeymapNotifyFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, KeymapNotify, win, callback)
}
func (callback KeymapNotifyFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(KeymapNotifyEvent))
}
type ExposeFun func(xu *xgbutil.XUtil, event ExposeEvent)
func (callback ExposeFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, Expose, win, callback)
}
func (callback ExposeFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(ExposeEvent))
}
type GraphicsExposureFun func(xu *xgbutil.XUtil, event GraphicsExposureEvent)
func (callback GraphicsExposureFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, GraphicsExposure, win, callback)
}
func (callback GraphicsExposureFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(GraphicsExposureEvent))
}
type NoExposureFun func(xu *xgbutil.XUtil, event NoExposureEvent)
func (callback NoExposureFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, NoExposure, win, callback)
}
func (callback NoExposureFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(NoExposureEvent))
}
type VisibilityNotifyFun func(xu *xgbutil.XUtil, event VisibilityNotifyEvent)
func (callback VisibilityNotifyFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, VisibilityNotify, win, callback)
}
func (callback VisibilityNotifyFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(VisibilityNotifyEvent))
}
type CreateNotifyFun func(xu *xgbutil.XUtil, event CreateNotifyEvent)
func (callback CreateNotifyFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, CreateNotify, win, callback)
}
func (callback CreateNotifyFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(CreateNotifyEvent))
}
type DestroyNotifyFun func(xu *xgbutil.XUtil, event DestroyNotifyEvent)
func (callback DestroyNotifyFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, DestroyNotify, win, callback)
}
func (callback DestroyNotifyFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(DestroyNotifyEvent))
}
type UnmapNotifyFun func(xu *xgbutil.XUtil, event UnmapNotifyEvent)
func (callback UnmapNotifyFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, UnmapNotify, win, callback)
}
func (callback UnmapNotifyFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(UnmapNotifyEvent))
}
type MapNotifyFun func(xu *xgbutil.XUtil, event MapNotifyEvent)
func (callback MapNotifyFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, MapNotify, win, callback)
}
func (callback MapNotifyFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(MapNotifyEvent))
}
type MapRequestFun func(xu *xgbutil.XUtil, event MapRequestEvent)
func (callback MapRequestFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, MapRequest, win, callback)
}
func (callback MapRequestFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(MapRequestEvent))
}
type ReparentNotifyFun func(xu *xgbutil.XUtil, event ReparentNotifyEvent)
func (callback ReparentNotifyFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, ReparentNotify, win, callback)
}
func (callback ReparentNotifyFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(ReparentNotifyEvent))
}
type ConfigureNotifyFun func(xu *xgbutil.XUtil, event ConfigureNotifyEvent)
func (callback ConfigureNotifyFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, ConfigureNotify, win, callback)
}
func (callback ConfigureNotifyFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(ConfigureNotifyEvent))
}
type ConfigureRequestFun func(xu *xgbutil.XUtil, event ConfigureRequestEvent)
func (callback ConfigureRequestFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, ConfigureRequest, win, callback)
}
func (callback ConfigureRequestFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(ConfigureRequestEvent))
}
type GravityNotifyFun func(xu *xgbutil.XUtil, event GravityNotifyEvent)
func (callback GravityNotifyFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, GravityNotify, win, callback)
}
func (callback GravityNotifyFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(GravityNotifyEvent))
}
type ResizeRequestFun func(xu *xgbutil.XUtil, event ResizeRequestEvent)
func (callback ResizeRequestFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, ResizeRequest, win, callback)
}
func (callback ResizeRequestFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(ResizeRequestEvent))
}
type CirculateNotifyFun func(xu *xgbutil.XUtil, event CirculateNotifyEvent)
func (callback CirculateNotifyFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, CirculateNotify, win, callback)
}
func (callback CirculateNotifyFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(CirculateNotifyEvent))
}
type CirculateRequestFun func(xu *xgbutil.XUtil, event CirculateRequestEvent)
func (callback CirculateRequestFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, CirculateRequest, win, callback)
}
func (callback CirculateRequestFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(CirculateRequestEvent))
}
type PropertyNotifyFun func(xu *xgbutil.XUtil, event PropertyNotifyEvent)
func (callback PropertyNotifyFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, PropertyNotify, win, callback)
}
func (callback PropertyNotifyFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(PropertyNotifyEvent))
}
type SelectionClearFun func(xu *xgbutil.XUtil, event SelectionClearEvent)
func (callback SelectionClearFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, SelectionClear, win, callback)
}
func (callback SelectionClearFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(SelectionClearEvent))
}
type SelectionRequestFun func(xu *xgbutil.XUtil, event SelectionRequestEvent)
func (callback SelectionRequestFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, SelectionRequest, win, callback)
}
func (callback SelectionRequestFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(SelectionRequestEvent))
}
type SelectionNotifyFun func(xu *xgbutil.XUtil, event SelectionNotifyEvent)
func (callback SelectionNotifyFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, SelectionNotify, win, callback)
}
func (callback SelectionNotifyFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(SelectionNotifyEvent))
}
type ColormapNotifyFun func(xu *xgbutil.XUtil, event ColormapNotifyEvent)
func (callback ColormapNotifyFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, ColormapNotify, win, callback)
}
func (callback ColormapNotifyFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(ColormapNotifyEvent))
}
type ClientMessageFun func(xu *xgbutil.XUtil, event ClientMessageEvent)
func (callback ClientMessageFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, ClientMessage, win, callback)
}
func (callback ClientMessageFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(ClientMessageEvent))
}
type MappingNotifyFun func(xu *xgbutil.XUtil, event MappingNotifyEvent)
func (callback MappingNotifyFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, MappingNotify, win, callback)
}
func (callback MappingNotifyFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(MappingNotifyEvent))
}
type ShapeNotifyFun func(xu *xgbutil.XUtil, event ShapeNotifyEvent)
func (callback ShapeNotifyFun) Connect(xu *xgbutil.XUtil,
win xproto.Window) {
attachCallback(xu, ShapeNotify, win, callback)
}
func (callback ShapeNotifyFun) Run(xu *xgbutil.XUtil, event interface{}) {
callback(xu, event.(ShapeNotifyEvent))
}

76
vendor/github.com/BurntSushi/xgbutil/xevent/doc.go generated vendored Normal file
View File

@ -0,0 +1,76 @@
/*
Package xevent provides an event handler interface for attaching callback
functions to X events, and an implementation of an X event loop.
The X event loop
One of the biggest conveniences offered by xgbutil is its event handler system.
That is, the ability to attach an arbitrary callback function to any X event.
In order for such things to work, xgbutil needs to control the main X event
loop and act as a dispatcher for all event handlers created by you.
To run the X event loop, use xevent.Main or xevent.MainPing. The former
runs a normal event loop in the current goroutine and processes events. The
latter runs the event loop in a new goroutine and returns a pingBefore and
a pingAfter channel. The pingBefore channel is sent a benign value right before
an event is dequeued, and the pingAfter channel is sent a benign value right
after after all callbacks for that event have finished execution. These
synchronization points in the main event loop can be combined with a 'select'
statement to process data from other input sources. An example of this is given
in the documentation for the MainPing function. A complete example called
multiple-source-event-loop can also be found in the examples directory of the
xgbutil package.
To quit the main event loop, you may use xevent.Quit, but there is nothing
inherently wrong with stopping dead using os.Exit. xevent.Quit is provided for
your convenience should you need to run any clean-up code after the main event
loop returns.
The X event queue
xgbutil's event queue contains values that are either events or errors. (Never
both and never neither.) Namely, errors are received in the event loop from
unchecked requests. (Errors generated by checked requests are guaranteed to be
returned to the caller and are never received in the event loop.) Also, a
default error handler function can be set with xevent.ErrorHandlerSet.
To this end, xgbutil's event queue can be inspected. This is advantageous when
information about what events will be processed in the future could be helpful
(i.e., if there is an UnmapNotify event waiting to be processed.) The event
queue can also be manipulated to facilitate event compression. (Two events that
are common candidates for compression are ConfigureNotify and MotionNotify.)
Detach events
Whenever a window can no longer receive events (i.e., when it is destroyed),
all event handlers related to that window should be detached. (If this is
omitted, then Go's garbage collector will not be able to reuse memory occupied
by the now-unused event handlers for that window.) Moreover, its possible that
a window id can be reused after it has been discarded, which could result in
odd behavior in your application.
To detach a window from all event handlers in the xevent package, use
xevent.Detach. If you're also using the keybind and mousebind packages, you'll
need to call keybind.Detach and mousebind.Detach too. So to detach your window
from all possible event handlers in xgbutil, use something like:
xevent.Detach(XUtilValue, your-window-id)
keybind.Detach(XUtilValue, your-window-id)
mousebind.Detach(XUtilValue, your-window-id)
Quick example
A small example that shows how to respond to ConfigureNotify events sent to
your-window-id.
xevent.ConfigureNotifyFun(
func(X *xgbutil.XUtil, e xevent.ConfigureNotifyEvent) {
fmt.Printf("(%d, %d) %dx%d\n", e.X, e.Y, e.Width, e.Height)
}).Connect(XUtilValue, your-window-id)
More examples
The xevent package is used in several of the examples in the examples directory
in the xgbutil package.
*/
package xevent

View File

@ -0,0 +1,291 @@
package xevent
/*
xevent/eventloop.go contains code that implements a main X event loop.
Namely, it provides facilities to read new events into xevent's event queue,
run a normal main event loop and run a main event loop that pings a channel
each time an event is about to be dequeued. The latter facility allows one to
easily include other input sources for processing in a program's main event
loop.
*/
import (
"github.com/BurntSushi/xgb/shape"
"github.com/BurntSushi/xgb/xproto"
"github.com/BurntSushi/xgbutil"
)
// Read reads one or more events and queues them in XUtil.
// If 'block' is True, then call 'WaitForEvent' before sucking up
// all events that have been queued by XGB.
func Read(xu *xgbutil.XUtil, block bool) {
if block {
ev, err := xu.Conn().WaitForEvent()
if ev == nil && err == nil {
xgbutil.Logger.Fatal("BUG: Could not read an event or an error.")
}
Enqueue(xu, ev, err)
}
// Clean up anything that's in the queue
for {
ev, err := xu.Conn().PollForEvent()
// No events left...
if ev == nil && err == nil {
break
}
// We're good, queue it up
Enqueue(xu, ev, err)
}
}
// Main starts the main X event loop. It will read events and call appropriate
// callback functions.
// N.B. If you have multiple X connections in the same program, you should be
// able to run this in different goroutines concurrently. However, only
// *one* of these should run for *each* connection.
func Main(xu *xgbutil.XUtil) {
mainEventLoop(xu, nil, nil, nil)
}
// MainPing starts the main X event loop, and returns three "ping" channels:
// the first is pinged before an event is dequeued, the second is pinged
// after all callbacks for a particular event have been called and the last
// is pinged when the event loop stops (e.g., after a call to xevent.Quit).
// pingAfter channel.
//
// This is useful if your event loop needs to draw from other sources. e.g.,
//
// pingBefore, pingAfter, pingQuit := xevent.MainPing()
// for {
// select {
// case <-pingBefore:
// // Wait for event processing to finish.
// <-pingAfter
// case val <- someOtherChannel:
// // do some work with val
// case <-pingQuit:
// fmt.Printf("xevent loop has quit")
// return
// }
// }
//
// Note that an unbuffered channel is returned, which implies that any work
// done with 'val' will delay further X event processing.
//
// A complete example using MainPing can be found in the examples directory in
// the xgbutil package under the name multiple-source-event-loop.
func MainPing(xu *xgbutil.XUtil) (chan struct{}, chan struct{}, chan struct{}) {
pingBefore := make(chan struct{}, 0)
pingAfter := make(chan struct{}, 0)
pingQuit := make(chan struct{}, 0)
go func() {
mainEventLoop(xu, pingBefore, pingAfter, pingQuit)
}()
return pingBefore, pingAfter, pingQuit
}
// mainEventLoop runs the main event loop with an optional ping channel.
func mainEventLoop(xu *xgbutil.XUtil,
pingBefore, pingAfter, pingQuit chan struct{}) {
for {
if Quitting(xu) {
if pingQuit != nil {
pingQuit <- struct{}{}
}
break
}
// Gobble up as many events as possible (into the queue).
// If there are no events, we block.
Read(xu, true)
// Now process every event/error in the queue.
processEventQueue(xu, pingBefore, pingAfter)
}
}
// processEventQueue processes every item in the event/error queue.
func processEventQueue(xu *xgbutil.XUtil, pingBefore, pingAfter chan struct{}) {
for !Empty(xu) {
if Quitting(xu) {
return
}
// We send the ping *before* the next event is dequeued.
// This is so the queue doesn't present a misrepresentation of which
// events haven't been processed yet.
if pingBefore != nil && pingAfter != nil {
pingBefore <- struct{}{}
}
ev, err := Dequeue(xu)
// If we gobbled up an error, send it to the error event handler
// and move on the next event/error.
if err != nil {
ErrorHandlerGet(xu)(err)
if pingBefore != nil && pingAfter != nil {
pingAfter <- struct{}{}
}
continue
}
// We know there isn't an error. If there isn't an event either,
// then there's a bug somewhere.
if ev == nil {
xgbutil.Logger.Fatal("BUG: Expected an event but got nil.")
}
hooks := getHooks(xu)
for _, hook := range hooks {
if !hook.Run(xu, ev) {
goto END
}
}
switch event := ev.(type) {
case xproto.KeyPressEvent:
e := KeyPressEvent{&event}
// If we're redirecting key events, this is the place to do it!
if wid := RedirectKeyGet(xu); wid > 0 {
e.Event = wid
}
xu.TimeSet(e.Time)
runCallbacks(xu, e, KeyPress, e.Event)
case xproto.KeyReleaseEvent:
e := KeyReleaseEvent{&event}
// If we're redirecting key events, this is the place to do it!
if wid := RedirectKeyGet(xu); wid > 0 {
e.Event = wid
}
xu.TimeSet(e.Time)
runCallbacks(xu, e, KeyRelease, e.Event)
case xproto.ButtonPressEvent:
e := ButtonPressEvent{&event}
xu.TimeSet(e.Time)
runCallbacks(xu, e, ButtonPress, e.Event)
case xproto.ButtonReleaseEvent:
e := ButtonReleaseEvent{&event}
xu.TimeSet(e.Time)
runCallbacks(xu, e, ButtonRelease, e.Event)
case xproto.MotionNotifyEvent:
e := MotionNotifyEvent{&event}
xu.TimeSet(e.Time)
runCallbacks(xu, e, MotionNotify, e.Event)
case xproto.EnterNotifyEvent:
e := EnterNotifyEvent{&event}
xu.TimeSet(e.Time)
runCallbacks(xu, e, EnterNotify, e.Event)
case xproto.LeaveNotifyEvent:
e := LeaveNotifyEvent{&event}
xu.TimeSet(e.Time)
runCallbacks(xu, e, LeaveNotify, e.Event)
case xproto.FocusInEvent:
e := FocusInEvent{&event}
runCallbacks(xu, e, FocusIn, e.Event)
case xproto.FocusOutEvent:
e := FocusOutEvent{&event}
runCallbacks(xu, e, FocusOut, e.Event)
case xproto.KeymapNotifyEvent:
e := KeymapNotifyEvent{&event}
runCallbacks(xu, e, KeymapNotify, NoWindow)
case xproto.ExposeEvent:
e := ExposeEvent{&event}
runCallbacks(xu, e, Expose, e.Window)
case xproto.GraphicsExposureEvent:
e := GraphicsExposureEvent{&event}
runCallbacks(xu, e, GraphicsExposure, xproto.Window(e.Drawable))
case xproto.NoExposureEvent:
e := NoExposureEvent{&event}
runCallbacks(xu, e, NoExposure, xproto.Window(e.Drawable))
case xproto.VisibilityNotifyEvent:
e := VisibilityNotifyEvent{&event}
runCallbacks(xu, e, VisibilityNotify, e.Window)
case xproto.CreateNotifyEvent:
e := CreateNotifyEvent{&event}
runCallbacks(xu, e, CreateNotify, e.Parent)
case xproto.DestroyNotifyEvent:
e := DestroyNotifyEvent{&event}
runCallbacks(xu, e, DestroyNotify, e.Window)
case xproto.UnmapNotifyEvent:
e := UnmapNotifyEvent{&event}
runCallbacks(xu, e, UnmapNotify, e.Window)
case xproto.MapNotifyEvent:
e := MapNotifyEvent{&event}
runCallbacks(xu, e, MapNotify, e.Event)
case xproto.MapRequestEvent:
e := MapRequestEvent{&event}
runCallbacks(xu, e, MapRequest, e.Window)
runCallbacks(xu, e, MapRequest, e.Parent)
case xproto.ReparentNotifyEvent:
e := ReparentNotifyEvent{&event}
runCallbacks(xu, e, ReparentNotify, e.Window)
case xproto.ConfigureNotifyEvent:
e := ConfigureNotifyEvent{&event}
runCallbacks(xu, e, ConfigureNotify, e.Window)
case xproto.ConfigureRequestEvent:
e := ConfigureRequestEvent{&event}
runCallbacks(xu, e, ConfigureRequest, e.Window)
runCallbacks(xu, e, ConfigureRequest, e.Parent)
case xproto.GravityNotifyEvent:
e := GravityNotifyEvent{&event}
runCallbacks(xu, e, GravityNotify, e.Window)
case xproto.ResizeRequestEvent:
e := ResizeRequestEvent{&event}
runCallbacks(xu, e, ResizeRequest, e.Window)
case xproto.CirculateNotifyEvent:
e := CirculateNotifyEvent{&event}
runCallbacks(xu, e, CirculateNotify, e.Window)
case xproto.CirculateRequestEvent:
e := CirculateRequestEvent{&event}
runCallbacks(xu, e, CirculateRequest, e.Window)
case xproto.PropertyNotifyEvent:
e := PropertyNotifyEvent{&event}
xu.TimeSet(e.Time)
runCallbacks(xu, e, PropertyNotify, e.Window)
case xproto.SelectionClearEvent:
e := SelectionClearEvent{&event}
xu.TimeSet(e.Time)
runCallbacks(xu, e, SelectionClear, e.Owner)
case xproto.SelectionRequestEvent:
e := SelectionRequestEvent{&event}
xu.TimeSet(e.Time)
runCallbacks(xu, e, SelectionRequest, e.Requestor)
case xproto.SelectionNotifyEvent:
e := SelectionNotifyEvent{&event}
xu.TimeSet(e.Time)
runCallbacks(xu, e, SelectionNotify, e.Requestor)
case xproto.ColormapNotifyEvent:
e := ColormapNotifyEvent{&event}
runCallbacks(xu, e, ColormapNotify, e.Window)
case xproto.ClientMessageEvent:
e := ClientMessageEvent{&event}
runCallbacks(xu, e, ClientMessage, e.Window)
case xproto.MappingNotifyEvent:
e := MappingNotifyEvent{&event}
runCallbacks(xu, e, MappingNotify, NoWindow)
case shape.NotifyEvent:
e := ShapeNotifyEvent{&event}
runCallbacks(xu, e, ShapeNotify, e.AffectedWindow)
default:
if event != nil {
xgbutil.Logger.Printf("ERROR: UNSUPPORTED EVENT TYPE: %T",
event)
}
}
END:
if pingBefore != nil && pingAfter != nil {
pingAfter <- struct{}{}
}
}
}

View File

@ -0,0 +1,336 @@
package xevent
/*
Defines event types and their associated methods automatically.
This file is automatically generated using `scripts/write-events evtypes`.
Edit it at your peril.
*/
import (
"fmt"
"github.com/BurntSushi/xgb/shape"
"github.com/BurntSushi/xgb/xproto"
)
type KeyPressEvent struct {
*xproto.KeyPressEvent
}
const KeyPress = xproto.KeyPress
func (ev KeyPressEvent) String() string {
return fmt.Sprintf("%v", ev.KeyPressEvent)
}
type KeyReleaseEvent struct {
*xproto.KeyReleaseEvent
}
const KeyRelease = xproto.KeyRelease
func (ev KeyReleaseEvent) String() string {
return fmt.Sprintf("%v", ev.KeyReleaseEvent)
}
type ButtonPressEvent struct {
*xproto.ButtonPressEvent
}
const ButtonPress = xproto.ButtonPress
func (ev ButtonPressEvent) String() string {
return fmt.Sprintf("%v", ev.ButtonPressEvent)
}
type ButtonReleaseEvent struct {
*xproto.ButtonReleaseEvent
}
const ButtonRelease = xproto.ButtonRelease
func (ev ButtonReleaseEvent) String() string {
return fmt.Sprintf("%v", ev.ButtonReleaseEvent)
}
type MotionNotifyEvent struct {
*xproto.MotionNotifyEvent
}
const MotionNotify = xproto.MotionNotify
func (ev MotionNotifyEvent) String() string {
return fmt.Sprintf("%v", ev.MotionNotifyEvent)
}
type EnterNotifyEvent struct {
*xproto.EnterNotifyEvent
}
const EnterNotify = xproto.EnterNotify
func (ev EnterNotifyEvent) String() string {
return fmt.Sprintf("%v", ev.EnterNotifyEvent)
}
type LeaveNotifyEvent struct {
*xproto.LeaveNotifyEvent
}
const LeaveNotify = xproto.LeaveNotify
func (ev LeaveNotifyEvent) String() string {
return fmt.Sprintf("%v", ev.LeaveNotifyEvent)
}
type FocusInEvent struct {
*xproto.FocusInEvent
}
const FocusIn = xproto.FocusIn
func (ev FocusInEvent) String() string {
return fmt.Sprintf("%v", ev.FocusInEvent)
}
type FocusOutEvent struct {
*xproto.FocusOutEvent
}
const FocusOut = xproto.FocusOut
func (ev FocusOutEvent) String() string {
return fmt.Sprintf("%v", ev.FocusOutEvent)
}
type KeymapNotifyEvent struct {
*xproto.KeymapNotifyEvent
}
const KeymapNotify = xproto.KeymapNotify
func (ev KeymapNotifyEvent) String() string {
return fmt.Sprintf("%v", ev.KeymapNotifyEvent)
}
type ExposeEvent struct {
*xproto.ExposeEvent
}
const Expose = xproto.Expose
func (ev ExposeEvent) String() string {
return fmt.Sprintf("%v", ev.ExposeEvent)
}
type GraphicsExposureEvent struct {
*xproto.GraphicsExposureEvent
}
const GraphicsExposure = xproto.GraphicsExposure
func (ev GraphicsExposureEvent) String() string {
return fmt.Sprintf("%v", ev.GraphicsExposureEvent)
}
type NoExposureEvent struct {
*xproto.NoExposureEvent
}
const NoExposure = xproto.NoExposure
func (ev NoExposureEvent) String() string {
return fmt.Sprintf("%v", ev.NoExposureEvent)
}
type VisibilityNotifyEvent struct {
*xproto.VisibilityNotifyEvent
}
const VisibilityNotify = xproto.VisibilityNotify
func (ev VisibilityNotifyEvent) String() string {
return fmt.Sprintf("%v", ev.VisibilityNotifyEvent)
}
type CreateNotifyEvent struct {
*xproto.CreateNotifyEvent
}
const CreateNotify = xproto.CreateNotify
func (ev CreateNotifyEvent) String() string {
return fmt.Sprintf("%v", ev.CreateNotifyEvent)
}
type DestroyNotifyEvent struct {
*xproto.DestroyNotifyEvent
}
const DestroyNotify = xproto.DestroyNotify
func (ev DestroyNotifyEvent) String() string {
return fmt.Sprintf("%v", ev.DestroyNotifyEvent)
}
type UnmapNotifyEvent struct {
*xproto.UnmapNotifyEvent
}
const UnmapNotify = xproto.UnmapNotify
func (ev UnmapNotifyEvent) String() string {
return fmt.Sprintf("%v", ev.UnmapNotifyEvent)
}
type MapNotifyEvent struct {
*xproto.MapNotifyEvent
}
const MapNotify = xproto.MapNotify
func (ev MapNotifyEvent) String() string {
return fmt.Sprintf("%v", ev.MapNotifyEvent)
}
type MapRequestEvent struct {
*xproto.MapRequestEvent
}
const MapRequest = xproto.MapRequest
func (ev MapRequestEvent) String() string {
return fmt.Sprintf("%v", ev.MapRequestEvent)
}
type ReparentNotifyEvent struct {
*xproto.ReparentNotifyEvent
}
const ReparentNotify = xproto.ReparentNotify
func (ev ReparentNotifyEvent) String() string {
return fmt.Sprintf("%v", ev.ReparentNotifyEvent)
}
type ConfigureRequestEvent struct {
*xproto.ConfigureRequestEvent
}
const ConfigureRequest = xproto.ConfigureRequest
func (ev ConfigureRequestEvent) String() string {
return fmt.Sprintf("%v", ev.ConfigureRequestEvent)
}
type GravityNotifyEvent struct {
*xproto.GravityNotifyEvent
}
const GravityNotify = xproto.GravityNotify
func (ev GravityNotifyEvent) String() string {
return fmt.Sprintf("%v", ev.GravityNotifyEvent)
}
type ResizeRequestEvent struct {
*xproto.ResizeRequestEvent
}
const ResizeRequest = xproto.ResizeRequest
func (ev ResizeRequestEvent) String() string {
return fmt.Sprintf("%v", ev.ResizeRequestEvent)
}
type CirculateNotifyEvent struct {
*xproto.CirculateNotifyEvent
}
const CirculateNotify = xproto.CirculateNotify
func (ev CirculateNotifyEvent) String() string {
return fmt.Sprintf("%v", ev.CirculateNotifyEvent)
}
type CirculateRequestEvent struct {
*xproto.CirculateRequestEvent
}
const CirculateRequest = xproto.CirculateRequest
func (ev CirculateRequestEvent) String() string {
return fmt.Sprintf("%v", ev.CirculateRequestEvent)
}
type PropertyNotifyEvent struct {
*xproto.PropertyNotifyEvent
}
const PropertyNotify = xproto.PropertyNotify
func (ev PropertyNotifyEvent) String() string {
return fmt.Sprintf("%v", ev.PropertyNotifyEvent)
}
type SelectionClearEvent struct {
*xproto.SelectionClearEvent
}
const SelectionClear = xproto.SelectionClear
func (ev SelectionClearEvent) String() string {
return fmt.Sprintf("%v", ev.SelectionClearEvent)
}
type SelectionRequestEvent struct {
*xproto.SelectionRequestEvent
}
const SelectionRequest = xproto.SelectionRequest
func (ev SelectionRequestEvent) String() string {
return fmt.Sprintf("%v", ev.SelectionRequestEvent)
}
type SelectionNotifyEvent struct {
*xproto.SelectionNotifyEvent
}
const SelectionNotify = xproto.SelectionNotify
func (ev SelectionNotifyEvent) String() string {
return fmt.Sprintf("%v", ev.SelectionNotifyEvent)
}
type ColormapNotifyEvent struct {
*xproto.ColormapNotifyEvent
}
const ColormapNotify = xproto.ColormapNotify
func (ev ColormapNotifyEvent) String() string {
return fmt.Sprintf("%v", ev.ColormapNotifyEvent)
}
type MappingNotifyEvent struct {
*xproto.MappingNotifyEvent
}
const MappingNotify = xproto.MappingNotify
func (ev MappingNotifyEvent) String() string {
return fmt.Sprintf("%v", ev.MappingNotifyEvent)
}
type ShapeNotifyEvent struct {
*shape.NotifyEvent
}
const ShapeNotify = shape.Notify
func (ev ShapeNotifyEvent) String() string {
return fmt.Sprintf("%v", ev.NotifyEvent)
}

View File

@ -0,0 +1,90 @@
package xevent
import (
"fmt"
"github.com/BurntSushi/xgb/xproto"
)
// ClientMessageEvent embeds the struct by the same name from the xgb library.
type ClientMessageEvent struct {
*xproto.ClientMessageEvent
}
const ClientMessage = xproto.ClientMessage
// NewClientMessage takes all arguments required to build a ClientMessageEvent
// struct and hides the messy details.
// The variadic parameters coincide with the "data" part of a client message.
// The type of the variadic parameters depends upon the value of Format.
// If Format is 8, 'data' should have type byte.
// If Format is 16, 'data' should have type int16.
// If Format is 32, 'data' should have type int.
// Any other value of Format returns an error.
func NewClientMessage(Format byte, Window xproto.Window, Type xproto.Atom,
data ...interface{}) (*ClientMessageEvent, error) {
// Create the client data list first
var clientData xproto.ClientMessageDataUnion
// Don't support formats 8 or 16 yet. They aren't used in EWMH anyway.
switch Format {
case 8:
buf := make([]byte, 20)
for i := 0; i < 20; i++ {
if i >= len(data) {
break
}
buf[i] = data[i].(byte)
}
clientData = xproto.ClientMessageDataUnionData8New(buf)
case 16:
buf := make([]uint16, 10)
for i := 0; i < 10; i++ {
if i >= len(data) {
break
}
buf[i] = uint16(data[i].(int16))
}
clientData = xproto.ClientMessageDataUnionData16New(buf)
case 32:
buf := make([]uint32, 5)
for i := 0; i < 5; i++ {
if i >= len(data) {
break
}
buf[i] = uint32(data[i].(int))
}
clientData = xproto.ClientMessageDataUnionData32New(buf)
default:
return nil, fmt.Errorf("NewClientMessage: Unsupported format '%d'.",
Format)
}
return &ClientMessageEvent{&xproto.ClientMessageEvent{
Format: Format,
Window: Window,
Type: Type,
Data: clientData,
}}, nil
}
// ConfigureNotifyEvent embeds the struct by the same name in XGB.
type ConfigureNotifyEvent struct {
*xproto.ConfigureNotifyEvent
}
const ConfigureNotify = xproto.ConfigureNotify
// NewConfigureNotify takes all arguments required to build a
// ConfigureNotifyEvent struct and returns a ConfigureNotifyEvent value.
func NewConfigureNotify(Event, Window, AboveSibling xproto.Window,
X, Y, Width, Height int, BorderWidth uint16,
OverrideRedirect bool) *ConfigureNotifyEvent {
return &ConfigureNotifyEvent{&xproto.ConfigureNotifyEvent{
Event: Event, Window: Window, AboveSibling: AboveSibling,
X: int16(X), Y: int16(Y), Width: uint16(Width), Height: uint16(Height),
BorderWidth: BorderWidth, OverrideRedirect: OverrideRedirect,
}}
}

237
vendor/github.com/BurntSushi/xgbutil/xevent/xevent.go generated vendored Normal file
View File

@ -0,0 +1,237 @@
package xevent
import (
"github.com/BurntSushi/xgb"
"github.com/BurntSushi/xgb/xproto"
"github.com/BurntSushi/xgbutil"
)
// Sometimes we need to specify NO WINDOW when a window is typically
// expected. (Like connecting to MappingNotify or KeymapNotify events.)
// Use this value to do that.
var NoWindow xproto.Window = 0
// IgnoreMods is a list of X modifiers that we don't want interfering
// with our mouse or key bindings. In particular, for each mouse or key binding
// issued, there is a seperate mouse or key binding made for each of the
// modifiers specified.
//
// You may modify this slice to add (or remove) modifiers, but it should be
// done before *any* key or mouse bindings are attached with the keybind and
// mousebind packages. It should not be modified afterwards.
//
// TODO: We're assuming numlock is in the 'mod2' modifier, which is a pretty
// common setup, but by no means guaranteed. This should be modified to actually
// inspect the modifiers table and look for the special Num_Lock keysym.
var IgnoreMods []uint16 = []uint16{
0,
xproto.ModMaskLock, // Caps lock
xproto.ModMask2, // Num lock
xproto.ModMaskLock | xproto.ModMask2, // Caps and Num lock
}
// Enqueue queues up an event read from X.
// Note that an event read may return an error, in which case, this queue
// entry will be an error and not an event.
//
// ev, err := XUtilValue.Conn().WaitForEvent()
// xevent.Enqueue(XUtilValue, ev, err)
//
// You probably shouldn't have to enqueue events yourself. This is done
// automatically if you're using xevent.Main{Ping} and/or xevent.Read.
func Enqueue(xu *xgbutil.XUtil, ev xgb.Event, err xgb.Error) {
xu.EvqueueLck.Lock()
defer xu.EvqueueLck.Unlock()
xu.Evqueue = append(xu.Evqueue, xgbutil.EventOrError{
Event: ev,
Err: err,
})
}
// Dequeue pops an event/error from the queue and returns it.
// The queue item is unwrapped and returned as multiple return values.
// Only one of the return values can be nil.
func Dequeue(xu *xgbutil.XUtil) (xgb.Event, xgb.Error) {
xu.EvqueueLck.Lock()
defer xu.EvqueueLck.Unlock()
everr := xu.Evqueue[0]
xu.Evqueue = xu.Evqueue[1:]
return everr.Event, everr.Err
}
// DequeueAt removes a particular item from the queue.
// This is primarily useful when attempting to compress events.
func DequeueAt(xu *xgbutil.XUtil, i int) {
xu.EvqueueLck.Lock()
defer xu.EvqueueLck.Unlock()
xu.Evqueue = append(xu.Evqueue[:i], xu.Evqueue[i+1:]...)
}
// Empty returns whether the event queue is empty or not.
func Empty(xu *xgbutil.XUtil) bool {
xu.EvqueueLck.RLock()
defer xu.EvqueueLck.RUnlock()
return len(xu.Evqueue) == 0
}
// Peek returns a *copy* of the current queue so we can examine it.
// This can be useful when trying to determine if a particular kind of
// event will be processed in the future.
func Peek(xu *xgbutil.XUtil) []xgbutil.EventOrError {
xu.EvqueueLck.RLock()
defer xu.EvqueueLck.RUnlock()
cpy := make([]xgbutil.EventOrError, len(xu.Evqueue))
copy(cpy, xu.Evqueue)
return cpy
}
// ErrorHandlerSet sets the default error handler for errors that come
// into the main event loop. (This may be removed in the future in favor
// of a particular callback interface like events, but these sorts of errors
// aren't handled often in practice, so maybe not.)
// This is only called for errors returned from unchecked (asynchronous error
// handling) requests.
// The default error handler just emits them to stderr.
func ErrorHandlerSet(xu *xgbutil.XUtil, fun xgbutil.ErrorHandlerFun) {
xu.ErrorHandler = fun
}
// ErrorHandlerGet retrieves the default error handler.
func ErrorHandlerGet(xu *xgbutil.XUtil) xgbutil.ErrorHandlerFun {
return xu.ErrorHandler
}
type HookFun func(xu *xgbutil.XUtil, event interface{}) bool
func (callback HookFun) Connect(xu *xgbutil.XUtil) {
xu.HooksLck.Lock()
defer xu.HooksLck.Unlock()
// COW
newHooks := make([]xgbutil.CallbackHook, len(xu.Hooks))
copy(newHooks, xu.Hooks)
newHooks = append(newHooks, callback)
xu.Hooks = newHooks
}
func (callback HookFun) Run(xu *xgbutil.XUtil, event interface{}) bool {
return callback(xu, event)
}
func getHooks(xu *xgbutil.XUtil) []xgbutil.CallbackHook {
xu.HooksLck.RLock()
defer xu.HooksLck.RUnlock()
return xu.Hooks
}
// RedirectKeyEvents, when set to a window id (greater than 0), will force
// *all* Key{Press,Release} to callbacks attached to the specified window.
// This is close to emulating a Keyboard grab without the racing.
// To stop redirecting key events, use window identifier '0'.
func RedirectKeyEvents(xu *xgbutil.XUtil, wid xproto.Window) {
xu.KeyRedirect = wid
}
// RedirectKeyGet gets the window that key events are being redirected to.
// If 0, then no redirection occurs.
func RedirectKeyGet(xu *xgbutil.XUtil) xproto.Window {
return xu.KeyRedirect
}
// Quit elegantly exits out of the main event loop.
// "Elegantly" in this case means that it finishes processing the current
// event, and breaks out of the loop afterwards.
// There is no particular reason to use this instead of something like os.Exit
// other than you might have code to run after the main event loop exits to
// "clean up."
func Quit(xu *xgbutil.XUtil) {
xu.Quit = true
}
// Quitting returns whether it's time to quit.
// This is only used in the main event loop in xevent.
func Quitting(xu *xgbutil.XUtil) bool {
return xu.Quit
}
// attachCallback associates a (event, window) tuple with an event.
// Use copy on write since we run callbacks *a lot* more than attaching them.
// (The copy on write only applies to the slice of callbacks rather than
// the map itself, since the initial allocation is guaranteed to come before
// any use of it.)
func attachCallback(xu *xgbutil.XUtil, evtype int, win xproto.Window,
fun xgbutil.Callback) {
xu.CallbacksLck.Lock()
defer xu.CallbacksLck.Unlock()
if _, ok := xu.Callbacks[evtype]; !ok {
xu.Callbacks[evtype] = make(map[xproto.Window][]xgbutil.Callback, 20)
}
if _, ok := xu.Callbacks[evtype][win]; !ok {
xu.Callbacks[evtype][win] = make([]xgbutil.Callback, 0)
}
// COW
newCallbacks := make([]xgbutil.Callback, len(xu.Callbacks[evtype][win]))
copy(newCallbacks, xu.Callbacks[evtype][win])
newCallbacks = append(newCallbacks, fun)
xu.Callbacks[evtype][win] = newCallbacks
}
// runCallbacks executes every callback corresponding to a
// particular event/window tuple.
func runCallbacks(xu *xgbutil.XUtil, event interface{}, evtype int,
win xproto.Window) {
// The callback slice for a particular (event type, window) tuple uses
// copy on write. So just take a pointer to whatever is there and use that.
// We can be sure that the slice won't change from underneathe us.
xu.CallbacksLck.RLock()
cbs := xu.Callbacks[evtype][win]
xu.CallbacksLck.RUnlock()
for _, cb := range cbs {
cb.Run(xu, event)
}
}
// Detach removes all callbacks associated with a particular window.
// Note that if you're also using the keybind and mousebind packages, a complete
// detachment should look like:
//
// keybind.Detach(XUtilValue, window-id)
// mousebind.Detach(XUtilValue, window-id)
// xevent.Detach(XUtilValue, window-id)
//
// If a window is no longer receiving events, these methods should be called.
// Otherwise, the memory used to store the handler info for that window will
// never be released.
func Detach(xu *xgbutil.XUtil, win xproto.Window) {
xu.CallbacksLck.Lock()
defer xu.CallbacksLck.Unlock()
for evtype, _ := range xu.Callbacks {
delete(xu.Callbacks[evtype], win)
}
}
// SendRootEvent takes a type implementing the xgb.Event interface, converts it
// to raw X bytes, and sends it to the root window using the SendEvent request.
func SendRootEvent(xu *xgbutil.XUtil, ev xgb.Event, evMask uint32) error {
return xproto.SendEventChecked(xu.Conn(), false, xu.RootWin(), evMask,
string(ev.Bytes())).Check()
}
// ReplayPointer is a quick alias to AllowEvents with 'ReplayPointer' mode.
func ReplayPointer(xu *xgbutil.XUtil) {
xproto.AllowEvents(xu.Conn(), xproto.AllowReplayPointer, 0)
}

348
vendor/github.com/BurntSushi/xgbutil/xgbutil.go generated vendored Normal file
View File

@ -0,0 +1,348 @@
package xgbutil
import (
"log"
"os"
"sync"
"github.com/BurntSushi/xgb"
"github.com/BurntSushi/xgb/xinerama"
"github.com/BurntSushi/xgb/xproto"
)
// Logger is used through xgbutil when messages need to be emitted to stderr.
var Logger = log.New(os.Stderr, "[xgbutil] ", log.Lshortfile)
// The current maximum request size. I think we can expand this with
// BigReq, but it probably isn't worth it at the moment.
const MaxReqSize = (1 << 16) * 4
// An XUtil represents the state of xgbutil. It keeps track of the current
// X connection, the root window, event callbacks, key/mouse bindings, etc.
// Regrettably, many of the members are exported, even though they should not
// be used directly by the user. They are exported for use in sub-packages.
// (Namely, xevent, keybind and mousebind.) In fact, there should *never*
// be a reason to access any members of an XUtil value directly. Any
// interaction with an XUtil value should be through its methods.
type XUtil struct {
// conn is the XGB connection object used to issue protocol requests.
conn *xgb.Conn
// Quit can be set to true, and the main event loop will finish processing
// the current event, and gracefully quit afterwards.
// This is exported for use in the xevent package. Please us xevent.Quit
// to set this value.
Quit bool // when true, the main event loop will stop gracefully
// setup contains all the setup information retrieved at connection time.
setup *xproto.SetupInfo
// screen is a simple alias to the default screen info.
screen *xproto.ScreenInfo
// root is an alias to the default root window.
root xproto.Window
// Atoms is a cache of atom names to resource identifiers. This minimizes
// round trips to the X server, since atom identifiers never change.
// It is exported for use in the xprop package. It should not be used.
Atoms map[string]xproto.Atom
AtomsLck *sync.RWMutex
// AtomNames is a cache just like 'atoms', but in the reverse direction.
// It is exported for use in the xprop package. It should not be used.
AtomNames map[xproto.Atom]string
AtomNamesLck *sync.RWMutex
// Evqueue is the queue that stores the results of xgb.WaitForEvent.
// Namely, each value is either an Event *or* an Error.
// It is exported for use in the xevent package. Do not use it.
// If you need to interact with the event queue, please use the functions
// available in the xevent package: Dequeue, DequeueAt, QueueEmpty
// and QueuePeek.
Evqueue []EventOrError
EvqueueLck *sync.RWMutex
// Callbacks is a map of event numbers to a map of window identifiers
// to callback functions.
// This is the data structure that stores all callback functions, where
// a callback function is always attached to a (event, window) tuple.
// It is exported for use in the xevent package. Do not use it.
Callbacks map[int]map[xproto.Window][]Callback
CallbacksLck *sync.RWMutex
// Hooks are called by the XEvent main loop before processing the event
// itself. These are meant for instances when it's not possible / easy
// to use the normal Hook system. You should not modify this yourself.
Hooks []CallbackHook
HooksLck *sync.RWMutex
// eventTime is the last time recorded by an event. It is automatically
// updated if xgbutil's main event loop is used.
eventTime xproto.Timestamp
// Keymap corresponds to xgbutil's current conception of the keyboard
// mapping. It is automatically kept up-to-date if xgbutil's event loop
// is used.
// It is exported for use in the keybind package. It should not be
// accessed directly. Instead, use keybind.KeyMapGet.
Keymap *KeyboardMapping
// Modmap corresponds to xgbutil's current conception of the modifier key
// mapping. It is automatically kept up-to-date if xgbutil's event loop
// is used.
// It is exported for use in the keybind package. It should not be
// accessed directly. Instead, use keybind.ModMapGet.
Modmap *ModifierMapping
// KeyRedirect corresponds to a window identifier that, when set,
// automatically receives *all* keyboard events. This is a sort-of
// synthetic grab and is helpful in avoiding race conditions.
// It is exported for use in the xevent and keybind packages. Do not use
// it directly. To redirect key events, please use xevent.RedirectKeyEvents.
KeyRedirect xproto.Window
// Keybinds is the data structure storing all callbacks for key bindings.
// This is extremely similar to the general notion of event callbacks,
// but adds extra support to make handling key bindings easier. (Like
// specifying human readable key sequences to bind to.)
// KeyBindKey is a struct representing the 4-tuple
// (event-type, window-id, modifiers, keycode).
// It is exported for use in the keybind package. Do not access it directly.
Keybinds map[KeyKey][]CallbackKey
KeybindsLck *sync.RWMutex
// Keygrabs is a frequency count of the number of callbacks associated
// with a particular KeyBindKey. This is necessary because we can only
// grab a particular key *once*, but we may want to attach several callbacks
// to a single keypress.
// It is exported for use in the keybind package. Do not access it directly.
Keygrabs map[KeyKey]int
// Keystrings is a list of all key strings used to connect keybindings.
// They are used to rebuild key grabs when the keyboard mapping is updated.
// It is exported for use in the keybind package. Do not access it directly.
Keystrings []KeyString
// Mousebinds is the data structure storing all callbacks for mouse
// bindings.This is extremely similar to the general notion of event
// callbacks,but adds extra support to make handling mouse bindings easier.
// (Like specifying human readable mouse sequences to bind to.)
// MouseBindKey is a struct representing the 4-tuple
// (event-type, window-id, modifiers, button).
// It is exported for use in the mousebind package. Do not use it.
Mousebinds map[MouseKey][]CallbackMouse
MousebindsLck *sync.RWMutex
// Mousegrabs is a frequency count of the number of callbacks associated
// with a particular MouseBindKey. This is necessary because we can only
// grab a particular mouse button *once*, but we may want to attach
// several callbacks to a single button press.
// It is exported for use in the mousebind package. Do not use it.
Mousegrabs map[MouseKey]int
// InMouseDrag is true if a drag is currently in progress.
// It is exported for use in the mousebind package. Do not use it.
InMouseDrag bool
// MouseDragStep is the function executed for each step (i.e., pointer
// movement) in the current mouse drag. Note that this is nil when a drag
// is not in progress.
// It is exported for use in the mousebind package. Do not use it.
MouseDragStepFun MouseDragFun
// MouseDragEnd is the function executed at the end of the current
// mouse drag. This is nil when a drag is not in progress.
// It is exported for use in the mousebind package. Do not use it.
MouseDragEndFun MouseDragFun
// gc is a general purpose graphics context; used to paint images.
// Since we don't do any real X drawing, we don't really care about the
// particulars of our graphics context.
gc xproto.Gcontext
// dummy is a dummy window used for mouse/key GRABs.
// Basically, whenever a grab is instituted, mouse and key events are
// redirected to the dummy the window.
dummy xproto.Window
// ErrorHandler is the function that handles errors *in the event loop*.
// By default, it simply emits them to stderr.
// It is exported for use in the xevent package. To set the default error
// handler, please use xevent.ErrorHandlerSet.
ErrorHandler ErrorHandlerFun
}
// NewConn connects to the X server using the DISPLAY environment variable
// and creates a new XUtil. Most environments have the DISPLAY environment
// variable set, so this is probably what you want to use to connect to X.
func NewConn() (*XUtil, error) {
return NewConnDisplay("")
}
// NewConnDisplay connects to the X server and creates a new XUtil.
// If 'display' is empty, the DISPLAY environment variable is used. Otherwise
// there are several different display formats supported:
//
// NewConn(":1") -> net.Dial("unix", "", "/tmp/.X11-unix/X1")
// NewConn("/tmp/launch-12/:0") -> net.Dial("unix", "", "/tmp/launch-12/:0")
// NewConn("hostname:2.1") -> net.Dial("tcp", "", "hostname:6002")
// NewConn("tcp/hostname:1.0") -> net.Dial("tcp", "", "hostname:6001")
func NewConnDisplay(display string) (*XUtil, error) {
c, err := xgb.NewConnDisplay(display)
if err != nil {
return nil, err
}
return NewConnXgb(c)
}
// NewConnXgb use the specific xgb.Conn to create a new XUtil.
//
// NewConn, NewConnDisplay are wrapper of this function.
func NewConnXgb(c *xgb.Conn) (*XUtil, error) {
setup := xproto.Setup(c)
screen := setup.DefaultScreen(c)
// Initialize our central struct that stores everything.
xu := &XUtil{
conn: c,
Quit: false,
Evqueue: make([]EventOrError, 0, 1000),
EvqueueLck: &sync.RWMutex{},
setup: setup,
screen: screen,
root: screen.Root,
eventTime: xproto.Timestamp(0), // last event time
Atoms: make(map[string]xproto.Atom, 50),
AtomsLck: &sync.RWMutex{},
AtomNames: make(map[xproto.Atom]string, 50),
AtomNamesLck: &sync.RWMutex{},
Callbacks: make(map[int]map[xproto.Window][]Callback, 33),
CallbacksLck: &sync.RWMutex{},
Hooks: make([]CallbackHook, 0),
HooksLck: &sync.RWMutex{},
Keymap: nil, // we don't have anything yet
Modmap: nil,
KeyRedirect: 0,
Keybinds: make(map[KeyKey][]CallbackKey, 10),
KeybindsLck: &sync.RWMutex{},
Keygrabs: make(map[KeyKey]int, 10),
Keystrings: make([]KeyString, 0, 10),
Mousebinds: make(map[MouseKey][]CallbackMouse, 10),
MousebindsLck: &sync.RWMutex{},
Mousegrabs: make(map[MouseKey]int, 10),
InMouseDrag: false,
MouseDragStepFun: nil,
MouseDragEndFun: nil,
ErrorHandler: func(err xgb.Error) { Logger.Println(err) },
}
var err error = nil
// Create a general purpose graphics context
xu.gc, err = xproto.NewGcontextId(xu.conn)
if err != nil {
return nil, err
}
xproto.CreateGC(xu.conn, xu.gc, xproto.Drawable(xu.root),
xproto.GcForeground, []uint32{xu.screen.WhitePixel})
// Create a dummy window
xu.dummy, err = xproto.NewWindowId(xu.conn)
if err != nil {
return nil, err
}
xproto.CreateWindow(xu.conn, xu.Screen().RootDepth, xu.dummy, xu.RootWin(),
-1000, -1000, 1, 1, 0,
xproto.WindowClassInputOutput, xu.Screen().RootVisual,
xproto.CwEventMask|xproto.CwOverrideRedirect,
[]uint32{1, xproto.EventMaskPropertyChange})
xproto.MapWindow(xu.conn, xu.dummy)
// Register the Xinerama extension... because it doesn't cost much.
err = xinerama.Init(xu.conn)
// If we can't register Xinerama, that's okay. Output something
// and move on.
if err != nil {
Logger.Printf("WARNING: %s\n", err)
Logger.Printf("MESSAGE: The 'xinerama' package cannot be used " +
"because the XINERAMA extension could not be loaded.")
}
return xu, nil
}
// Conn returns the xgb connection object.
func (xu *XUtil) Conn() *xgb.Conn {
return xu.conn
}
// ExtInitialized returns true if an extension has been initialized.
// This is useful for determining whether an extension is available or not.
func (xu *XUtil) ExtInitialized(extName string) bool {
_, ok := xu.Conn().Extensions[extName]
return ok
}
// Sync forces XGB to catch up with all events/requests and synchronize.
// This is done by issuing a benign round trip request to X.
func (xu *XUtil) Sync() {
xproto.GetInputFocus(xu.Conn()).Reply()
}
// Setup returns the setup information retrieved during connection time.
func (xu *XUtil) Setup() *xproto.SetupInfo {
return xu.setup
}
// Screen returns the default screen
func (xu *XUtil) Screen() *xproto.ScreenInfo {
return xu.screen
}
// RootWin returns the current root window.
func (xu *XUtil) RootWin() xproto.Window {
return xu.root
}
// RootWinSet will change the current root window to the one provided.
// N.B. This probably shouldn't be used unless you're desperately trying
// to support multiple X screens. (This is *not* the same as Xinerama/RandR or
// TwinView. All of those have a single root window.)
func (xu *XUtil) RootWinSet(root xproto.Window) {
xu.root = root
}
// TimeGet gets the most recent time seen by an event.
func (xu *XUtil) TimeGet() xproto.Timestamp {
return xu.eventTime
}
// TimeSet sets the most recent time seen by an event.
func (xu *XUtil) TimeSet(t xproto.Timestamp) {
xu.eventTime = t
}
// GC gets a general purpose graphics context that is typically used to simply
// paint images.
func (xu *XUtil) GC() xproto.Gcontext {
return xu.gc
}
// Dummy gets the id of the dummy window.
func (xu *XUtil) Dummy() xproto.Window {
return xu.dummy
}
// Grabs the server. Everything becomes synchronous.
func (xu *XUtil) Grab() {
xproto.GrabServer(xu.Conn())
}
// Ungrabs the server.
func (xu *XUtil) Ungrab() {
xproto.UngrabServer(xu.Conn())
}

103
vendor/github.com/BurntSushi/xgbutil/xprop/atom.go generated vendored Normal file
View File

@ -0,0 +1,103 @@
package xprop
/*
xprop/atom.go contains functions related to interning atoms and retrieving
atom names from an atom identifier.
It also manages an atom cache so that once an atom is interned from the X
server, all future atom interns use that value. (So that one and only one
request is sent for interning each atom.)
*/
import (
"fmt"
"github.com/BurntSushi/xgb/xproto"
"github.com/BurntSushi/xgbutil"
)
// Atm is a short alias for Atom in the common case of interning an atom.
// Namely, interning the atom always succeeds. (If the atom does not already
// exist, a new one is created.)
func Atm(xu *xgbutil.XUtil, name string) (xproto.Atom, error) {
aid, err := Atom(xu, name, false)
if err != nil {
return 0, err
}
if aid == 0 {
return 0, fmt.Errorf("Atm: '%s' returned an identifier of 0.", name)
}
return aid, err
}
// Atom interns an atom and panics if there is any error.
func Atom(xu *xgbutil.XUtil, name string,
onlyIfExists bool) (xproto.Atom, error) {
// Check the cache first
if aid, ok := atomGet(xu, name); ok {
return aid, nil
}
reply, err := xproto.InternAtom(xu.Conn(), onlyIfExists,
uint16(len(name)), name).Reply()
if err != nil {
return 0, fmt.Errorf("Atom: Error interning atom '%s': %s", name, err)
}
// If we're here, it means we didn't have this atom cached. So cache it!
cacheAtom(xu, name, reply.Atom)
return reply.Atom, nil
}
// AtomName fetches a string representation of an ATOM given its integer id.
func AtomName(xu *xgbutil.XUtil, aid xproto.Atom) (string, error) {
// Check the cache first
if atomName, ok := atomNameGet(xu, aid); ok {
return string(atomName), nil
}
reply, err := xproto.GetAtomName(xu.Conn(), aid).Reply()
if err != nil {
return "", fmt.Errorf("AtomName: Error fetching name for ATOM "+
"id '%d': %s", aid, err)
}
// If we're here, it means we didn't have ths ATOM id cached. So cache it.
atomName := string(reply.Name)
cacheAtom(xu, atomName, aid)
return atomName, nil
}
// atomGet retrieves an atom identifier from a cache if it exists.
func atomGet(xu *xgbutil.XUtil, name string) (xproto.Atom, bool) {
xu.AtomsLck.RLock()
defer xu.AtomsLck.RUnlock()
aid, ok := xu.Atoms[name]
return aid, ok
}
// atomNameGet retrieves an atom name from a cache if it exists.
func atomNameGet(xu *xgbutil.XUtil, aid xproto.Atom) (string, bool) {
xu.AtomNamesLck.RLock()
defer xu.AtomNamesLck.RUnlock()
name, ok := xu.AtomNames[aid]
return name, ok
}
// cacheAtom puts an atom into the cache.
func cacheAtom(xu *xgbutil.XUtil, name string, aid xproto.Atom) {
xu.AtomsLck.Lock()
xu.AtomNamesLck.Lock()
defer xu.AtomsLck.Unlock()
defer xu.AtomNamesLck.Unlock()
xu.Atoms[name] = aid
xu.AtomNames[aid] = name
}

40
vendor/github.com/BurntSushi/xgbutil/xprop/doc.go generated vendored Normal file
View File

@ -0,0 +1,40 @@
/*
Package xprop provides a cache for interning atoms and helper functions for
dealing with GetProperty and ChangeProperty X requests.
Atoms
Atoms in X are interned, meaning that strings are assigned unique integer
identifiers. This minimizes the amount of data transmitted over an X connection.
Once atoms have been interned, they are never changed while the X server is
running. xgbutil takes advantage of this invariant and will only issue an
intern atom request once and cache the result.
To use the xprop package to intern an atom, use Atom:
atom, err := xprop.Atom(XUtilValue, "THE_ATOM_NAME", false)
if err == nil {
println("The atom number: ", atom.Atom)
}
The 'false' parameter corresponds to the 'only_if_exists' parameter of the
X InternAtom request. When it's false, the atom being interned always returns
a non-zero atom number---even if the string being interned hasn't been interned
before. If 'only_if_exists' is true, the atom being interned will return a 0
atom number if it hasn't already been interned.
The typical case is to set 'only_if_exists' to false. To this end, xprop.Atm is
an alias that always sets this value to false.
The reverse can also be done: getting an atom string if you have an atom
number. This can be done with the xprop.AtomName function.
Properties
The other facility of xprop is to help with the use of GetProperty and
ChangeProperty. Please see the source code of the ewmh package for plenty of
examples.
*/
package xprop

270
vendor/github.com/BurntSushi/xgbutil/xprop/xprop.go generated vendored Normal file
View File

@ -0,0 +1,270 @@
package xprop
import (
"fmt"
"github.com/BurntSushi/xgb"
"github.com/BurntSushi/xgb/xproto"
"github.com/BurntSushi/xgbutil"
)
// GetProperty abstracts the messiness of calling xgb.GetProperty.
func GetProperty(xu *xgbutil.XUtil, win xproto.Window, atom string) (
*xproto.GetPropertyReply, error) {
atomId, err := Atm(xu, atom)
if err != nil {
return nil, err
}
reply, err := xproto.GetProperty(xu.Conn(), false, win, atomId,
xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply()
if err != nil {
return nil, fmt.Errorf("GetProperty: Error retrieving property '%s' "+
"on window %x: %s", atom, win, err)
}
if reply.Format == 0 {
return nil, fmt.Errorf("GetProperty: No such property '%s' on "+
"window %x.", atom, win)
}
return reply, nil
}
// ChangeProperty abstracts the semi-nastiness of xgb.ChangeProperty.
func ChangeProp(xu *xgbutil.XUtil, win xproto.Window, format byte, prop string,
typ string, data []byte) error {
propAtom, err := Atm(xu, prop)
if err != nil {
return err
}
typAtom, err := Atm(xu, typ)
if err != nil {
return err
}
return xproto.ChangePropertyChecked(xu.Conn(), xproto.PropModeReplace, win,
propAtom, typAtom, format,
uint32(len(data)/(int(format)/8)), data).Check()
}
// ChangeProperty32 makes changing 32 bit formatted properties easier
// by constructing the raw X data for you.
func ChangeProp32(xu *xgbutil.XUtil, win xproto.Window, prop string, typ string,
data ...uint) error {
buf := make([]byte, len(data)*4)
for i, datum := range data {
xgb.Put32(buf[(i*4):], uint32(datum))
}
return ChangeProp(xu, win, 32, prop, typ, buf)
}
// WindowToUint is a covenience function for converting []xproto.Window
// to []uint.
func WindowToInt(ids []xproto.Window) []uint {
ids32 := make([]uint, len(ids))
for i, v := range ids {
ids32[i] = uint(v)
}
return ids32
}
// AtomToInt is a covenience function for converting []xproto.Atom
// to []uint.
func AtomToUint(ids []xproto.Atom) []uint {
ids32 := make([]uint, len(ids))
for i, v := range ids {
ids32[i] = uint(v)
}
return ids32
}
// StrToAtoms is a convenience function for converting
// []string to []uint32 atoms.
// NOTE: If an atom name in the list doesn't exist, it will be created.
func StrToAtoms(xu *xgbutil.XUtil, atomNames []string) ([]uint, error) {
var err error
atoms := make([]uint, len(atomNames))
for i, atomName := range atomNames {
a, err := Atom(xu, atomName, false)
if err != nil {
return nil, err
}
atoms[i] = uint(a)
}
return atoms, err
}
// PropValAtom transforms a GetPropertyReply struct into an ATOM name.
// The property reply must be in 32 bit format.
func PropValAtom(xu *xgbutil.XUtil, reply *xproto.GetPropertyReply,
err error) (string, error) {
if err != nil {
return "", err
}
if reply.Format != 32 {
return "", fmt.Errorf("PropValAtom: Expected format 32 but got %d",
reply.Format)
}
return AtomName(xu, xproto.Atom(xgb.Get32(reply.Value)))
}
// PropValAtoms is the same as PropValAtom, except that it returns a slice
// of atom names. Also must be 32 bit format.
// This is a method of an XUtil struct, unlike the other 'PropVal...' functions.
func PropValAtoms(xu *xgbutil.XUtil, reply *xproto.GetPropertyReply,
err error) ([]string, error) {
if err != nil {
return nil, err
}
if reply.Format != 32 {
return nil, fmt.Errorf("PropValAtoms: Expected format 32 but got %d",
reply.Format)
}
ids := make([]string, reply.ValueLen)
vals := reply.Value
for i := 0; len(vals) >= 4; i++ {
ids[i], err = AtomName(xu, xproto.Atom(xgb.Get32(vals)))
if err != nil {
return nil, err
}
vals = vals[4:]
}
return ids, nil
}
// PropValWindow transforms a GetPropertyReply struct into an X resource
// window identifier.
// The property reply must be in 32 bit format.
func PropValWindow(reply *xproto.GetPropertyReply,
err error) (xproto.Window, error) {
if err != nil {
return 0, err
}
if reply.Format != 32 {
return 0, fmt.Errorf("PropValId: Expected format 32 but got %d",
reply.Format)
}
return xproto.Window(xgb.Get32(reply.Value)), nil
}
// PropValWindows is the same as PropValWindow, except that it returns a slice
// of identifiers. Also must be 32 bit format.
func PropValWindows(reply *xproto.GetPropertyReply,
err error) ([]xproto.Window, error) {
if err != nil {
return nil, err
}
if reply.Format != 32 {
return nil, fmt.Errorf("PropValIds: Expected format 32 but got %d",
reply.Format)
}
ids := make([]xproto.Window, reply.ValueLen)
vals := reply.Value
for i := 0; len(vals) >= 4; i++ {
ids[i] = xproto.Window(xgb.Get32(vals))
vals = vals[4:]
}
return ids, nil
}
// PropValNum transforms a GetPropertyReply struct into an unsigned
// integer. Useful when the property value is a single integer.
func PropValNum(reply *xproto.GetPropertyReply, err error) (uint, error) {
if err != nil {
return 0, err
}
if reply.Format != 32 {
return 0, fmt.Errorf("PropValNum: Expected format 32 but got %d",
reply.Format)
}
return uint(xgb.Get32(reply.Value)), nil
}
// PropValNums is the same as PropValNum, except that it returns a slice
// of integers. Also must be 32 bit format.
func PropValNums(reply *xproto.GetPropertyReply, err error) ([]uint, error) {
if err != nil {
return nil, err
}
if reply.Format != 32 {
return nil, fmt.Errorf("PropValIds: Expected format 32 but got %d",
reply.Format)
}
nums := make([]uint, reply.ValueLen)
vals := reply.Value
for i := 0; len(vals) >= 4; i++ {
nums[i] = uint(xgb.Get32(vals))
vals = vals[4:]
}
return nums, nil
}
// PropValNum64 transforms a GetPropertyReply struct into a 64 bit
// integer. Useful when the property value is a single integer.
func PropValNum64(reply *xproto.GetPropertyReply, err error) (int64, error) {
if err != nil {
return 0, err
}
if reply.Format != 32 {
return 0, fmt.Errorf("PropValNum: Expected format 32 but got %d",
reply.Format)
}
return int64(xgb.Get32(reply.Value)), nil
}
// PropValStr transforms a GetPropertyReply struct into a string.
// Useful when the property value is a null terminated string represented
// by integers. Also must be 8 bit format.
func PropValStr(reply *xproto.GetPropertyReply, err error) (string, error) {
if err != nil {
return "", err
}
if reply.Format != 8 {
return "", fmt.Errorf("PropValStr: Expected format 8 but got %d",
reply.Format)
}
return string(reply.Value), nil
}
// PropValStrs is the same as PropValStr, except that it returns a slice
// of strings. The raw byte string is a sequence of null terminated strings,
// which is translated into a slice of strings.
func PropValStrs(reply *xproto.GetPropertyReply, err error) ([]string, error) {
if err != nil {
return nil, err
}
if reply.Format != 8 {
return nil, fmt.Errorf("PropValStrs: Expected format 8 but got %d",
reply.Format)
}
var strs []string
sstart := 0
for i, c := range reply.Value {
if c == 0 {
strs = append(strs, string(reply.Value[sstart:i]))
sstart = i + 1
}
}
if sstart < int(reply.ValueLen) {
strs = append(strs, string(reply.Value[sstart:]))
}
return strs, nil
}

View File

@ -49,20 +49,91 @@ func encodePaletted(w io.Writer, pix []uint8, dx, dy, stride, step int) error {
return nil
}
func encodeRGBA(w io.Writer, pix []uint8, dx, dy, stride, step int) error {
func encodeRGBA(w io.Writer, pix []uint8, dx, dy, stride, step int, opaque bool) error {
buf := make([]byte, step)
for y := dy - 1; y >= 0; y-- {
min := y*stride + 0
max := y*stride + dx*4
off := 0
for i := min; i < max; i += 4 {
buf[off+2] = pix[i+0]
buf[off+1] = pix[i+1]
buf[off+0] = pix[i+2]
off += 3
if opaque {
for y := dy - 1; y >= 0; y-- {
min := y*stride + 0
max := y*stride + dx*4
off := 0
for i := min; i < max; i += 4 {
buf[off+2] = pix[i+0]
buf[off+1] = pix[i+1]
buf[off+0] = pix[i+2]
off += 3
}
if _, err := w.Write(buf); err != nil {
return err
}
}
if _, err := w.Write(buf); err != nil {
return err
} else {
for y := dy - 1; y >= 0; y-- {
min := y*stride + 0
max := y*stride + dx*4
off := 0
for i := min; i < max; i += 4 {
a := uint32(pix[i+3])
if a == 0 {
buf[off+2] = 0
buf[off+1] = 0
buf[off+0] = 0
buf[off+3] = 0
off += 4
continue
} else if a == 0xff {
buf[off+2] = pix[i+0]
buf[off+1] = pix[i+1]
buf[off+0] = pix[i+2]
buf[off+3] = 0xff
off += 4
continue
}
buf[off+2] = uint8(((uint32(pix[i+0]) * 0xffff) / a) >> 8)
buf[off+1] = uint8(((uint32(pix[i+1]) * 0xffff) / a) >> 8)
buf[off+0] = uint8(((uint32(pix[i+2]) * 0xffff) / a) >> 8)
buf[off+3] = uint8(a)
off += 4
}
if _, err := w.Write(buf); err != nil {
return err
}
}
}
return nil
}
func encodeNRGBA(w io.Writer, pix []uint8, dx, dy, stride, step int, opaque bool) error {
buf := make([]byte, step)
if opaque {
for y := dy - 1; y >= 0; y-- {
min := y*stride + 0
max := y*stride + dx*4
off := 0
for i := min; i < max; i += 4 {
buf[off+2] = pix[i+0]
buf[off+1] = pix[i+1]
buf[off+0] = pix[i+2]
off += 3
}
if _, err := w.Write(buf); err != nil {
return err
}
}
} else {
for y := dy - 1; y >= 0; y-- {
min := y*stride + 0
max := y*stride + dx*4
off := 0
for i := min; i < max; i += 4 {
buf[off+2] = pix[i+0]
buf[off+1] = pix[i+1]
buf[off+0] = pix[i+2]
buf[off+3] = pix[i+3]
off += 4
}
if _, err := w.Write(buf); err != nil {
return err
}
}
}
return nil
@ -105,6 +176,7 @@ func Encode(w io.Writer, m image.Image) error {
var step int
var palette []byte
var opaque bool
switch m := m.(type) {
case *image.Gray:
step = (d.X + 3) &^ 3
@ -134,6 +206,28 @@ func Encode(w io.Writer, m image.Image) error {
h.fileSize += uint32(len(palette)) + h.imageSize
h.pixOffset += uint32(len(palette))
h.bpp = 8
case *image.RGBA:
opaque = m.Opaque()
if opaque {
step = (3*d.X + 3) &^ 3
h.bpp = 24
} else {
step = 4 * d.X
h.bpp = 32
}
h.imageSize = uint32(d.Y * step)
h.fileSize += h.imageSize
case *image.NRGBA:
opaque = m.Opaque()
if opaque {
step = (3*d.X + 3) &^ 3
h.bpp = 24
} else {
step = 4 * d.X
h.bpp = 32
}
h.imageSize = uint32(d.Y * step)
h.fileSize += h.imageSize
default:
step = (3*d.X + 3) &^ 3
h.imageSize = uint32(d.Y * step)
@ -160,7 +254,9 @@ func Encode(w io.Writer, m image.Image) error {
case *image.Paletted:
return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step)
case *image.RGBA:
return encodeRGBA(w, m.Pix, d.X, d.Y, m.Stride, step)
return encodeRGBA(w, m.Pix, d.X, d.Y, m.Stride, step, opaque)
case *image.NRGBA:
return encodeNRGBA(w, m.Pix, d.X, d.Y, m.Stride, step, opaque)
}
return encode(w, m, step)
}

View File

@ -206,7 +206,7 @@ func (sa *SockaddrDatalink) sockaddr() (unsafe.Pointer, _Socklen, error) {
return unsafe.Pointer(&sa.raw), SizeofSockaddrDatalink, nil
}
func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
switch rsa.Addr.Family {
case AF_LINK:
pp := (*RawSockaddrDatalink)(unsafe.Pointer(rsa))
@ -286,7 +286,7 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) {
Close(nfd)
return 0, nil, ECONNABORTED
}
sa, err = anyToSockaddr(&rsa)
sa, err = anyToSockaddr(fd, &rsa)
if err != nil {
Close(nfd)
nfd = 0
@ -306,7 +306,7 @@ func Getsockname(fd int) (sa Sockaddr, err error) {
rsa.Addr.Family = AF_UNIX
rsa.Addr.Len = SizeofSockaddrUnix
}
return anyToSockaddr(&rsa)
return anyToSockaddr(fd, &rsa)
}
//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
@ -356,7 +356,7 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from
recvflags = int(msg.Flags)
// source address is only specified if the socket is unconnected
if rsa.Addr.Family != AF_UNSPEC {
from, err = anyToSockaddr(&rsa)
from, err = anyToSockaddr(fd, &rsa)
}
return
}

View File

@ -87,7 +87,7 @@ func Accept4(fd, flags int) (nfd int, sa Sockaddr, err error) {
if len > SizeofSockaddrAny {
panic("RawSockaddrAny too small")
}
sa, err = anyToSockaddr(&rsa)
sa, err = anyToSockaddr(fd, &rsa)
if err != nil {
Close(nfd)
nfd = 0

View File

@ -89,7 +89,7 @@ func Accept4(fd, flags int) (nfd int, sa Sockaddr, err error) {
if len > SizeofSockaddrAny {
panic("RawSockaddrAny too small")
}
sa, err = anyToSockaddr(&rsa)
sa, err = anyToSockaddr(fd, &rsa)
if err != nil {
Close(nfd)
nfd = 0

View File

@ -489,6 +489,47 @@ func (sa *SockaddrL2) sockaddr() (unsafe.Pointer, _Socklen, error) {
return unsafe.Pointer(&sa.raw), SizeofSockaddrL2, nil
}
// SockaddrRFCOMM implements the Sockaddr interface for AF_BLUETOOTH type sockets
// using the RFCOMM protocol.
//
// Server example:
//
// fd, _ := Socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)
// _ = unix.Bind(fd, &unix.SockaddrRFCOMM{
// Channel: 1,
// Addr: [6]uint8{0, 0, 0, 0, 0, 0}, // BDADDR_ANY or 00:00:00:00:00:00
// })
// _ = Listen(fd, 1)
// nfd, sa, _ := Accept(fd)
// fmt.Printf("conn addr=%v fd=%d", sa.(*unix.SockaddrRFCOMM).Addr, nfd)
// Read(nfd, buf)
//
// Client example:
//
// fd, _ := Socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)
// _ = Connect(fd, &SockaddrRFCOMM{
// Channel: 1,
// Addr: [6]byte{0x11, 0x22, 0x33, 0xaa, 0xbb, 0xcc}, // CC:BB:AA:33:22:11
// })
// Write(fd, []byte(`hello`))
type SockaddrRFCOMM struct {
// Addr represents a bluetooth address, byte ordering is little-endian.
Addr [6]uint8
// Channel is a designated bluetooth channel, only 1-30 are available for use.
// Since Linux 2.6.7 and further zero value is the first available channel.
Channel uint8
raw RawSockaddrRFCOMM
}
func (sa *SockaddrRFCOMM) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Family = AF_BLUETOOTH
sa.raw.Channel = sa.Channel
sa.raw.Bdaddr = sa.Addr
return unsafe.Pointer(&sa.raw), SizeofSockaddrRFCOMM, nil
}
// SockaddrCAN implements the Sockaddr interface for AF_CAN type sockets.
// The RxID and TxID fields are used for transport protocol addressing in
// (CAN_TP16, CAN_TP20, CAN_MCNET, and CAN_ISOTP), they can be left with
@ -651,7 +692,7 @@ func (sa *SockaddrVM) sockaddr() (unsafe.Pointer, _Socklen, error) {
return unsafe.Pointer(&sa.raw), SizeofSockaddrVM, nil
}
func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
switch rsa.Addr.Family {
case AF_NETLINK:
pp := (*RawSockaddrNetlink)(unsafe.Pointer(rsa))
@ -728,6 +769,30 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
Port: pp.Port,
}
return sa, nil
case AF_BLUETOOTH:
proto, err := GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL)
if err != nil {
return nil, err
}
// only BTPROTO_L2CAP and BTPROTO_RFCOMM can accept connections
switch proto {
case BTPROTO_L2CAP:
pp := (*RawSockaddrL2)(unsafe.Pointer(rsa))
sa := &SockaddrL2{
PSM: pp.Psm,
CID: pp.Cid,
Addr: pp.Bdaddr,
AddrType: pp.Bdaddr_type,
}
return sa, nil
case BTPROTO_RFCOMM:
pp := (*RawSockaddrRFCOMM)(unsafe.Pointer(rsa))
sa := &SockaddrRFCOMM{
Channel: pp.Channel,
Addr: pp.Bdaddr,
}
return sa, nil
}
}
return nil, EAFNOSUPPORT
}
@ -739,7 +804,7 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) {
if err != nil {
return
}
sa, err = anyToSockaddr(&rsa)
sa, err = anyToSockaddr(fd, &rsa)
if err != nil {
Close(nfd)
nfd = 0
@ -757,7 +822,7 @@ func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) {
if len > SizeofSockaddrAny {
panic("RawSockaddrAny too small")
}
sa, err = anyToSockaddr(&rsa)
sa, err = anyToSockaddr(fd, &rsa)
if err != nil {
Close(nfd)
nfd = 0
@ -771,7 +836,7 @@ func Getsockname(fd int) (sa Sockaddr, err error) {
if err = getsockname(fd, &rsa, &len); err != nil {
return
}
return anyToSockaddr(&rsa)
return anyToSockaddr(fd, &rsa)
}
func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) {
@ -960,7 +1025,7 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from
recvflags = int(msg.Flags)
// source address is only specified if the socket is unconnected
if rsa.Addr.Family != AF_UNSPEC {
from, err = anyToSockaddr(&rsa)
from, err = anyToSockaddr(fd, &rsa)
}
return
}

View File

@ -112,7 +112,7 @@ func Getsockname(fd int) (sa Sockaddr, err error) {
if err = getsockname(fd, &rsa, &len); err != nil {
return
}
return anyToSockaddr(&rsa)
return anyToSockaddr(fd, &rsa)
}
// GetsockoptString returns the string value of the socket option opt for the
@ -360,7 +360,7 @@ func Futimes(fd int, tv []Timeval) error {
return futimesat(fd, nil, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
}
func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
switch rsa.Addr.Family {
case AF_UNIX:
pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
@ -411,7 +411,7 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) {
if nfd == -1 {
return
}
sa, err = anyToSockaddr(&rsa)
sa, err = anyToSockaddr(fd, &rsa)
if err != nil {
Close(nfd)
nfd = 0
@ -448,7 +448,7 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from
oobn = int(msg.Accrightslen)
// source address is only specified if the socket is unconnected
if rsa.Addr.Family != AF_UNSPEC {
from, err = anyToSockaddr(&rsa)
from, err = anyToSockaddr(fd, &rsa)
}
return
}

View File

@ -219,7 +219,7 @@ func Getpeername(fd int) (sa Sockaddr, err error) {
if err = getpeername(fd, &rsa, &len); err != nil {
return
}
return anyToSockaddr(&rsa)
return anyToSockaddr(fd, &rsa)
}
func GetsockoptByte(fd, level, opt int) (value byte, err error) {
@ -291,7 +291,7 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
return
}
if rsa.Addr.Family != AF_UNSPEC {
from, err = anyToSockaddr(&rsa)
from, err = anyToSockaddr(fd, &rsa)
}
return
}

View File

@ -1474,6 +1474,21 @@ func Munlockall() (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func faccessat(dirfd int, path string, mode uint32) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Dup2(oldfd int, newfd int) (err error) {
_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
if e1 != 0 {
@ -1495,21 +1510,6 @@ func EpollCreate(size int) (fd int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func faccessat(dirfd int, path string, mode uint32) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
var _p0 unsafe.Pointer
if len(events) > 0 {

View File

@ -1474,6 +1474,21 @@ func Munlockall() (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func faccessat(dirfd int, path string, mode uint32) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Dup2(oldfd int, newfd int) (err error) {
_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
if e1 != 0 {
@ -1495,21 +1510,6 @@ func EpollCreate(size int) (fd int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func faccessat(dirfd int, path string, mode uint32) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
var _p0 unsafe.Pointer
if len(events) > 0 {

View File

@ -248,6 +248,13 @@ type RawSockaddrL2 struct {
_ [1]byte
}
type RawSockaddrRFCOMM struct {
Family uint16
Bdaddr [6]uint8
Channel uint8
_ [1]byte
}
type RawSockaddrCAN struct {
Family uint16
_ [2]byte
@ -401,6 +408,7 @@ const (
SizeofSockaddrNetlink = 0xc
SizeofSockaddrHCI = 0x6
SizeofSockaddrL2 = 0xe
SizeofSockaddrRFCOMM = 0xa
SizeofSockaddrCAN = 0x10
SizeofSockaddrALG = 0x58
SizeofSockaddrVM = 0x10

View File

@ -250,6 +250,13 @@ type RawSockaddrL2 struct {
_ [1]byte
}
type RawSockaddrRFCOMM struct {
Family uint16
Bdaddr [6]uint8
Channel uint8
_ [1]byte
}
type RawSockaddrCAN struct {
Family uint16
_ [2]byte
@ -405,6 +412,7 @@ const (
SizeofSockaddrNetlink = 0xc
SizeofSockaddrHCI = 0x6
SizeofSockaddrL2 = 0xe
SizeofSockaddrRFCOMM = 0xa
SizeofSockaddrCAN = 0x10
SizeofSockaddrALG = 0x58
SizeofSockaddrVM = 0x10

View File

@ -251,6 +251,13 @@ type RawSockaddrL2 struct {
_ [1]byte
}
type RawSockaddrRFCOMM struct {
Family uint16
Bdaddr [6]uint8
Channel uint8
_ [1]byte
}
type RawSockaddrCAN struct {
Family uint16
_ [2]byte
@ -404,6 +411,7 @@ const (
SizeofSockaddrNetlink = 0xc
SizeofSockaddrHCI = 0x6
SizeofSockaddrL2 = 0xe
SizeofSockaddrRFCOMM = 0xa
SizeofSockaddrCAN = 0x10
SizeofSockaddrALG = 0x58
SizeofSockaddrVM = 0x10

View File

@ -251,6 +251,13 @@ type RawSockaddrL2 struct {
_ [1]byte
}
type RawSockaddrRFCOMM struct {
Family uint16
Bdaddr [6]uint8
Channel uint8
_ [1]byte
}
type RawSockaddrCAN struct {
Family uint16
_ [2]byte
@ -406,6 +413,7 @@ const (
SizeofSockaddrNetlink = 0xc
SizeofSockaddrHCI = 0x6
SizeofSockaddrL2 = 0xe
SizeofSockaddrRFCOMM = 0xa
SizeofSockaddrCAN = 0x10
SizeofSockaddrALG = 0x58
SizeofSockaddrVM = 0x10

View File

@ -249,6 +249,13 @@ type RawSockaddrL2 struct {
_ [1]byte
}
type RawSockaddrRFCOMM struct {
Family uint16
Bdaddr [6]uint8
Channel uint8
_ [1]byte
}
type RawSockaddrCAN struct {
Family uint16
_ [2]byte
@ -402,6 +409,7 @@ const (
SizeofSockaddrNetlink = 0xc
SizeofSockaddrHCI = 0x6
SizeofSockaddrL2 = 0xe
SizeofSockaddrRFCOMM = 0xa
SizeofSockaddrCAN = 0x10
SizeofSockaddrALG = 0x58
SizeofSockaddrVM = 0x10

View File

@ -251,6 +251,13 @@ type RawSockaddrL2 struct {
_ [1]byte
}
type RawSockaddrRFCOMM struct {
Family uint16
Bdaddr [6]uint8
Channel uint8
_ [1]byte
}
type RawSockaddrCAN struct {
Family uint16
_ [2]byte
@ -406,6 +413,7 @@ const (
SizeofSockaddrNetlink = 0xc
SizeofSockaddrHCI = 0x6
SizeofSockaddrL2 = 0xe
SizeofSockaddrRFCOMM = 0xa
SizeofSockaddrCAN = 0x10
SizeofSockaddrALG = 0x58
SizeofSockaddrVM = 0x10

View File

@ -251,6 +251,13 @@ type RawSockaddrL2 struct {
_ [1]byte
}
type RawSockaddrRFCOMM struct {
Family uint16
Bdaddr [6]uint8
Channel uint8
_ [1]byte
}
type RawSockaddrCAN struct {
Family uint16
_ [2]byte
@ -406,6 +413,7 @@ const (
SizeofSockaddrNetlink = 0xc
SizeofSockaddrHCI = 0x6
SizeofSockaddrL2 = 0xe
SizeofSockaddrRFCOMM = 0xa
SizeofSockaddrCAN = 0x10
SizeofSockaddrALG = 0x58
SizeofSockaddrVM = 0x10

View File

@ -249,6 +249,13 @@ type RawSockaddrL2 struct {
_ [1]byte
}
type RawSockaddrRFCOMM struct {
Family uint16
Bdaddr [6]uint8
Channel uint8
_ [1]byte
}
type RawSockaddrCAN struct {
Family uint16
_ [2]byte
@ -402,6 +409,7 @@ const (
SizeofSockaddrNetlink = 0xc
SizeofSockaddrHCI = 0x6
SizeofSockaddrL2 = 0xe
SizeofSockaddrRFCOMM = 0xa
SizeofSockaddrCAN = 0x10
SizeofSockaddrALG = 0x58
SizeofSockaddrVM = 0x10

View File

@ -252,6 +252,13 @@ type RawSockaddrL2 struct {
_ [1]byte
}
type RawSockaddrRFCOMM struct {
Family uint16
Bdaddr [6]uint8
Channel uint8
_ [1]byte
}
type RawSockaddrCAN struct {
Family uint16
_ [2]byte
@ -407,6 +414,7 @@ const (
SizeofSockaddrNetlink = 0xc
SizeofSockaddrHCI = 0x6
SizeofSockaddrL2 = 0xe
SizeofSockaddrRFCOMM = 0xa
SizeofSockaddrCAN = 0x10
SizeofSockaddrALG = 0x58
SizeofSockaddrVM = 0x10

View File

@ -252,6 +252,13 @@ type RawSockaddrL2 struct {
_ [1]byte
}
type RawSockaddrRFCOMM struct {
Family uint16
Bdaddr [6]uint8
Channel uint8
_ [1]byte
}
type RawSockaddrCAN struct {
Family uint16
_ [2]byte
@ -407,6 +414,7 @@ const (
SizeofSockaddrNetlink = 0xc
SizeofSockaddrHCI = 0x6
SizeofSockaddrL2 = 0xe
SizeofSockaddrRFCOMM = 0xa
SizeofSockaddrCAN = 0x10
SizeofSockaddrALG = 0x58
SizeofSockaddrVM = 0x10

View File

@ -250,6 +250,13 @@ type RawSockaddrL2 struct {
_ [1]byte
}
type RawSockaddrRFCOMM struct {
Family uint16
Bdaddr [6]uint8
Channel uint8
_ [1]byte
}
type RawSockaddrCAN struct {
Family uint16
_ [2]byte
@ -405,6 +412,7 @@ const (
SizeofSockaddrNetlink = 0xc
SizeofSockaddrHCI = 0x6
SizeofSockaddrL2 = 0xe
SizeofSockaddrRFCOMM = 0xa
SizeofSockaddrCAN = 0x10
SizeofSockaddrALG = 0x58
SizeofSockaddrVM = 0x10

View File

@ -94,16 +94,29 @@ const (
FILE_APPEND_DATA = 0x00000004
FILE_WRITE_ATTRIBUTES = 0x00000100
FILE_SHARE_READ = 0x00000001
FILE_SHARE_WRITE = 0x00000002
FILE_SHARE_DELETE = 0x00000004
FILE_ATTRIBUTE_READONLY = 0x00000001
FILE_ATTRIBUTE_HIDDEN = 0x00000002
FILE_ATTRIBUTE_SYSTEM = 0x00000004
FILE_ATTRIBUTE_DIRECTORY = 0x00000010
FILE_ATTRIBUTE_ARCHIVE = 0x00000020
FILE_ATTRIBUTE_NORMAL = 0x00000080
FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400
FILE_SHARE_READ = 0x00000001
FILE_SHARE_WRITE = 0x00000002
FILE_SHARE_DELETE = 0x00000004
FILE_ATTRIBUTE_READONLY = 0x00000001
FILE_ATTRIBUTE_HIDDEN = 0x00000002
FILE_ATTRIBUTE_SYSTEM = 0x00000004
FILE_ATTRIBUTE_DIRECTORY = 0x00000010
FILE_ATTRIBUTE_ARCHIVE = 0x00000020
FILE_ATTRIBUTE_DEVICE = 0x00000040
FILE_ATTRIBUTE_NORMAL = 0x00000080
FILE_ATTRIBUTE_TEMPORARY = 0x00000100
FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200
FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400
FILE_ATTRIBUTE_COMPRESSED = 0x00000800
FILE_ATTRIBUTE_OFFLINE = 0x00001000
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000
FILE_ATTRIBUTE_ENCRYPTED = 0x00004000
FILE_ATTRIBUTE_INTEGRITY_STREAM = 0x00008000
FILE_ATTRIBUTE_VIRTUAL = 0x00010000
FILE_ATTRIBUTE_NO_SCRUB_DATA = 0x00020000
FILE_ATTRIBUTE_RECALL_ON_OPEN = 0x00040000
FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS = 0x00400000
INVALID_FILE_ATTRIBUTES = 0xffffffff