mirror of
https://github.com/go-vgo/robotgo.git
synced 2025-06-01 14:43:55 +00:00
update dep pkg
This commit is contained in:
parent
186df36c2c
commit
2a6299df59
28
Gopkg.lock
generated
28
Gopkg.lock
generated
@ -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
2
vendor/github.com/BurntSushi/xgb/.gitignore
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
xgbgen/xgbgen
|
||||
.*.swp
|
18
vendor/github.com/BurntSushi/xgb/AUTHORS
generated
vendored
Normal file
18
vendor/github.com/BurntSushi/xgb/AUTHORS
generated
vendored
Normal 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
39
vendor/github.com/BurntSushi/xgb/CONTRIBUTORS
generated
vendored
Normal 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
42
vendor/github.com/BurntSushi/xgb/LICENSE
generated
vendored
Normal 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
78
vendor/github.com/BurntSushi/xgb/Makefile
generated
vendored
Normal 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
54
vendor/github.com/BurntSushi/xgb/README
generated
vendored
Normal 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
29
vendor/github.com/BurntSushi/xgb/STYLE
generated
vendored
Normal 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
110
vendor/github.com/BurntSushi/xgb/auth.go
generated
vendored
Normal 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
185
vendor/github.com/BurntSushi/xgb/conn.go
generated
vendored
Normal 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
165
vendor/github.com/BurntSushi/xgb/cookie.go
generated
vendored
Normal 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
146
vendor/github.com/BurntSushi/xgb/doc.go
generated
vendored
Normal 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
105
vendor/github.com/BurntSushi/xgb/help.go
generated
vendored
Normal 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
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
29
vendor/github.com/BurntSushi/xgb/sync.go
generated
vendored
Normal 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
554
vendor/github.com/BurntSushi/xgb/xgb.go
generated
vendored
Normal 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
13
vendor/github.com/BurntSushi/xgb/xgbgen/COPYING
generated
vendored
Normal 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
718
vendor/github.com/BurntSushi/xgb/xinerama/xinerama.go
generated
vendored
Normal 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
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
6
vendor/github.com/BurntSushi/xgbutil/.gitignore
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
*.swp
|
||||
*.png
|
||||
tst_first
|
||||
tst_graphics
|
||||
TAGS
|
||||
|
13
vendor/github.com/BurntSushi/xgbutil/COPYING
generated
vendored
Normal file
13
vendor/github.com/BurntSushi/xgbutil/COPYING
generated
vendored
Normal 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
36
vendor/github.com/BurntSushi/xgbutil/Makefile
generated
vendored
Normal 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
60
vendor/github.com/BurntSushi/xgbutil/README
generated
vendored
Normal 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
29
vendor/github.com/BurntSushi/xgbutil/STYLE
generated
vendored
Normal 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
67
vendor/github.com/BurntSushi/xgbutil/doc.go
generated
vendored
Normal 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
56
vendor/github.com/BurntSushi/xgbutil/ewmh/doc.go
generated
vendored
Normal 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
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
31
vendor/github.com/BurntSushi/xgbutil/ewmh/winman.go
generated
vendored
Normal 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
1
vendor/github.com/BurntSushi/xgbutil/session.vim
generated
vendored
Normal 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
167
vendor/github.com/BurntSushi/xgbutil/types.go
generated
vendored
Normal 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
389
vendor/github.com/BurntSushi/xgbutil/xevent/callback.go
generated
vendored
Normal 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
76
vendor/github.com/BurntSushi/xgbutil/xevent/doc.go
generated
vendored
Normal 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
|
291
vendor/github.com/BurntSushi/xgbutil/xevent/eventloop.go
generated
vendored
Normal file
291
vendor/github.com/BurntSushi/xgbutil/xevent/eventloop.go
generated
vendored
Normal 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{}{}
|
||||
}
|
||||
}
|
||||
}
|
336
vendor/github.com/BurntSushi/xgbutil/xevent/types_auto.go
generated
vendored
Normal file
336
vendor/github.com/BurntSushi/xgbutil/xevent/types_auto.go
generated
vendored
Normal 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)
|
||||
}
|
90
vendor/github.com/BurntSushi/xgbutil/xevent/types_manual.go
generated
vendored
Normal file
90
vendor/github.com/BurntSushi/xgbutil/xevent/types_manual.go
generated
vendored
Normal 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
237
vendor/github.com/BurntSushi/xgbutil/xevent/xevent.go
generated
vendored
Normal 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
348
vendor/github.com/BurntSushi/xgbutil/xgbutil.go
generated
vendored
Normal 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
103
vendor/github.com/BurntSushi/xgbutil/xprop/atom.go
generated
vendored
Normal 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
40
vendor/github.com/BurntSushi/xgbutil/xprop/doc.go
generated
vendored
Normal 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
270
vendor/github.com/BurntSushi/xgbutil/xprop/xprop.go
generated
vendored
Normal 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
|
||||
}
|
122
vendor/golang.org/x/image/bmp/writer.go
generated
vendored
122
vendor/golang.org/x/image/bmp/writer.go
generated
vendored
@ -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)
|
||||
}
|
||||
|
8
vendor/golang.org/x/sys/unix/syscall_bsd.go
generated
vendored
8
vendor/golang.org/x/sys/unix/syscall_bsd.go
generated
vendored
@ -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
|
||||
}
|
||||
|
2
vendor/golang.org/x/sys/unix/syscall_dragonfly.go
generated
vendored
2
vendor/golang.org/x/sys/unix/syscall_dragonfly.go
generated
vendored
@ -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
|
||||
|
2
vendor/golang.org/x/sys/unix/syscall_freebsd.go
generated
vendored
2
vendor/golang.org/x/sys/unix/syscall_freebsd.go
generated
vendored
@ -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
|
||||
|
75
vendor/golang.org/x/sys/unix/syscall_linux.go
generated
vendored
75
vendor/golang.org/x/sys/unix/syscall_linux.go
generated
vendored
@ -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
|
||||
}
|
||||
|
8
vendor/golang.org/x/sys/unix/syscall_solaris.go
generated
vendored
8
vendor/golang.org/x/sys/unix/syscall_solaris.go
generated
vendored
@ -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
|
||||
}
|
||||
|
4
vendor/golang.org/x/sys/unix/syscall_unix.go
generated
vendored
4
vendor/golang.org/x/sys/unix/syscall_unix.go
generated
vendored
@ -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
|
||||
}
|
||||
|
30
vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go
generated
vendored
30
vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go
generated
vendored
@ -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 {
|
||||
|
30
vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go
generated
vendored
30
vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go
generated
vendored
@ -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 {
|
||||
|
8
vendor/golang.org/x/sys/unix/ztypes_linux_386.go
generated
vendored
8
vendor/golang.org/x/sys/unix/ztypes_linux_386.go
generated
vendored
@ -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
|
||||
|
8
vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go
generated
vendored
8
vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go
generated
vendored
@ -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
|
||||
|
8
vendor/golang.org/x/sys/unix/ztypes_linux_arm.go
generated
vendored
8
vendor/golang.org/x/sys/unix/ztypes_linux_arm.go
generated
vendored
@ -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
|
||||
|
8
vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go
generated
vendored
8
vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go
generated
vendored
@ -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
|
||||
|
8
vendor/golang.org/x/sys/unix/ztypes_linux_mips.go
generated
vendored
8
vendor/golang.org/x/sys/unix/ztypes_linux_mips.go
generated
vendored
@ -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
|
||||
|
8
vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go
generated
vendored
8
vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go
generated
vendored
@ -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
|
||||
|
8
vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go
generated
vendored
8
vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go
generated
vendored
@ -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
|
||||
|
8
vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go
generated
vendored
8
vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go
generated
vendored
@ -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
|
||||
|
8
vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go
generated
vendored
8
vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go
generated
vendored
@ -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
|
||||
|
8
vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go
generated
vendored
8
vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go
generated
vendored
@ -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
|
||||
|
8
vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go
generated
vendored
8
vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go
generated
vendored
@ -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
|
||||
|
33
vendor/golang.org/x/sys/windows/types_windows.go
generated
vendored
33
vendor/golang.org/x/sys/windows/types_windows.go
generated
vendored
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user